1use arrow::{
21 array::{Array, AsArray, new_null_array},
22 datatypes::{DataType, Field, Schema},
23 record_batch::RecordBatch,
24};
25use std::borrow::Cow;
26use std::collections::HashSet;
27use std::ops::Not;
28use std::sync::Arc;
29use std::sync::LazyLock;
30
31use datafusion_common::config::ConfigOptions;
32use datafusion_common::nested_struct::has_one_of_more_common_fields;
33use datafusion_common::{
34 DFSchema, DataFusionError, Result, ScalarValue, exec_datafusion_err, internal_err,
35};
36use datafusion_common::{
37 HashMap,
38 cast::{as_large_list_array, as_list_array},
39 metadata::FieldMetadata,
40 tree_node::{Transformed, TransformedResult, TreeNode, TreeNodeRewriter},
41};
42use datafusion_expr::expr::HigherOrderFunction;
43use datafusion_expr::physical_planning_context::PhysicalPlanningContext;
44use datafusion_expr::{
45 BinaryExpr, Case, ColumnarValue, Expr, ExprSchemable, Like, Operator, Volatility,
46 and, binary::BinaryTypeCoercer, lit, or, preimage::PreimageResult,
47};
48use datafusion_expr::{Cast, TryCast, simplify::ExprSimplifyResult};
49use datafusion_expr::{expr::ScalarFunction, interval_arithmetic::NullableInterval};
50use datafusion_expr::{
51 expr::{InList, InSubquery},
52 utils::{iter_conjunction, iter_conjunction_owned},
53};
54use datafusion_physical_expr::{create_physical_expr, execution_props::ExecutionProps};
55
56use super::inlist_simplifier::ShortenInListSimplifier;
57use super::utils::*;
58use crate::simplify_expressions::SimplifyContext;
59use crate::simplify_expressions::regex::simplify_regex_expr;
60use crate::simplify_expressions::unwrap_cast::{
61 is_cast_expr_and_support_unwrap_cast_in_comparison_for_binary,
62 is_cast_expr_and_support_unwrap_cast_in_comparison_for_inlist,
63 unwrap_cast_in_comparison_for_binary,
64};
65use crate::{
66 analyzer::type_coercion::TypeCoercionRewriter,
67 simplify_expressions::udf_preimage::rewrite_with_preimage,
68};
69use datafusion_expr::expr_rewriter::rewrite_with_guarantees_map;
70use datafusion_expr_common::casts::try_cast_literal_to_type;
71use indexmap::IndexSet;
72use regex::Regex;
73
74pub struct ExprSimplifier {
106 info: SimplifyContext,
107 guarantees: Vec<(Expr, NullableInterval)>,
110 canonicalize: bool,
113 max_simplifier_cycles: u32,
115}
116
117pub const THRESHOLD_INLINE_INLIST: usize = 3;
118pub const DEFAULT_MAX_SIMPLIFIER_CYCLES: u32 = 3;
119
120impl ExprSimplifier {
121 pub fn new(info: SimplifyContext) -> Self {
126 Self {
127 info,
128 guarantees: vec![],
129 canonicalize: true,
130 max_simplifier_cycles: DEFAULT_MAX_SIMPLIFIER_CYCLES,
131 }
132 }
133
134 pub fn simplify(&self, expr: Expr) -> Result<Expr> {
177 Ok(self.simplify_with_cycle_count_transformed(expr)?.0.data)
178 }
179
180 #[deprecated(
187 since = "48.0.0",
188 note = "Use `simplify_with_cycle_count_transformed` instead"
189 )]
190 #[expect(unused_mut)]
191 pub fn simplify_with_cycle_count(&self, mut expr: Expr) -> Result<(Expr, u32)> {
192 let (transformed, cycle_count) =
193 self.simplify_with_cycle_count_transformed(expr)?;
194 Ok((transformed.data, cycle_count))
195 }
196
197 pub fn simplify_with_cycle_count_transformed(
210 &self,
211 mut expr: Expr,
212 ) -> Result<(Transformed<Expr>, u32)> {
213 let mut simplifier = Simplifier::new(&self.info);
214 let config_options = Some(Arc::clone(self.info.config_options()));
215 let mut const_evaluator = ConstEvaluator::try_new(config_options)?;
216 let mut shorten_in_list_simplifier = ShortenInListSimplifier::new();
217 let guarantees_map: HashMap<&Expr, &NullableInterval> =
218 self.guarantees.iter().map(|(k, v)| (k, v)).collect();
219
220 if self.canonicalize {
221 expr = expr.rewrite(&mut Canonicalizer::new()).data()?
222 }
223
224 let mut num_cycles = 0;
228 let mut has_transformed = false;
229 loop {
230 let Transformed {
231 data, transformed, ..
232 } = expr
233 .rewrite(&mut const_evaluator)?
234 .transform_data(|expr| expr.rewrite(&mut simplifier))?
235 .transform_data(|expr| {
236 rewrite_with_guarantees_map(expr, &guarantees_map)
237 })?;
238 expr = data;
239 num_cycles += 1;
240 has_transformed = has_transformed || transformed;
242 if !transformed || num_cycles >= self.max_simplifier_cycles {
243 break;
244 }
245 }
246 expr = expr.rewrite(&mut shorten_in_list_simplifier).data()?;
248 Ok((
249 Transformed::new_transformed(expr, has_transformed),
250 num_cycles,
251 ))
252 }
253
254 pub fn coerce(&self, expr: Expr, schema: &DFSchema) -> Result<Expr> {
260 let mut expr_rewrite = TypeCoercionRewriter { schema };
261 expr.rewrite(&mut expr_rewrite).data()
262 }
263
264 pub fn with_guarantees(mut self, guarantees: Vec<(Expr, NullableInterval)>) -> Self {
320 self.guarantees = guarantees;
321 self
322 }
323
324 pub fn with_canonicalize(mut self, canonicalize: bool) -> Self {
372 self.canonicalize = canonicalize;
373 self
374 }
375
376 pub fn with_max_cycles(mut self, max_simplifier_cycles: u32) -> Self {
425 self.max_simplifier_cycles = max_simplifier_cycles;
426 self
427 }
428}
429
430struct Canonicalizer {}
437
438impl Canonicalizer {
439 fn new() -> Self {
440 Self {}
441 }
442}
443
444impl TreeNodeRewriter for Canonicalizer {
445 type Node = Expr;
446
447 fn f_up(&mut self, expr: Expr) -> Result<Transformed<Expr>> {
448 let Expr::BinaryExpr(BinaryExpr { left, op, right }) = expr else {
449 return Ok(Transformed::no(expr));
450 };
451 match (left.as_ref(), right.as_ref(), op.swap()) {
452 (Expr::Column(left_col), Expr::Column(right_col), Some(swapped_op))
454 if right_col > left_col =>
455 {
456 Ok(Transformed::yes(Expr::BinaryExpr(BinaryExpr {
457 left: right,
458 op: swapped_op,
459 right: left,
460 })))
461 }
462 (Expr::Literal(_a, _), Expr::Column(_b), Some(swapped_op)) => {
464 Ok(Transformed::yes(Expr::BinaryExpr(BinaryExpr {
465 left: right,
466 op: swapped_op,
467 right: left,
468 })))
469 }
470 _ => Ok(Transformed::no(Expr::BinaryExpr(BinaryExpr {
471 left,
472 op,
473 right,
474 }))),
475 }
476 }
477}
478
479struct ConstEvaluator {
484 can_evaluate: Vec<bool>,
497 execution_props: ExecutionProps,
504}
505
506enum ConstSimplifyResult {
508 Simplified(ScalarValue, Option<FieldMetadata>),
510 NotSimplified(ScalarValue, Option<FieldMetadata>),
512 SimplifyRuntimeError(DataFusionError, Expr),
514}
515
516impl TreeNodeRewriter for ConstEvaluator {
517 type Node = Expr;
518
519 fn f_down(&mut self, expr: Expr) -> Result<Transformed<Expr>> {
520 self.can_evaluate.push(true);
522
523 if !Self::can_evaluate(&expr) {
528 let parent_iter = self.can_evaluate.iter_mut().rev();
530 for p in parent_iter {
531 if !*p {
532 break;
535 }
536 *p = false;
537 }
538 }
539
540 Ok(Transformed::no(expr))
544 }
545
546 fn f_up(&mut self, expr: Expr) -> Result<Transformed<Expr>> {
547 match self.can_evaluate.pop() {
548 Some(true) => match self.evaluate_to_scalar(expr) {
553 ConstSimplifyResult::Simplified(s, m) => {
554 Ok(Transformed::yes(Expr::Literal(s, m)))
555 }
556 ConstSimplifyResult::NotSimplified(s, m) => {
557 Ok(Transformed::no(Expr::Literal(s, m)))
558 }
559 ConstSimplifyResult::SimplifyRuntimeError(err, expr) => {
560 if let Expr::Cast(Cast { ref expr, .. })
563 | Expr::TryCast(TryCast { ref expr, .. }) = expr
564 && matches!(expr.as_ref(), Expr::Literal(_, _))
565 {
566 return Err(err);
567 }
568 Ok(Transformed::yes(expr))
571 }
572 },
573 Some(false) => Ok(Transformed::no(expr)),
574 _ => internal_err!("Failed to pop can_evaluate"),
575 }
576 }
577}
578
579static DUMMY_SCHEMA: LazyLock<Arc<Schema>> =
580 LazyLock::new(|| Arc::new(Schema::new(vec![Field::new(".", DataType::Null, true)])));
581
582static DUMMY_DF_SCHEMA: LazyLock<DFSchema> =
583 LazyLock::new(|| DFSchema::try_from(Arc::clone(&*DUMMY_SCHEMA)).unwrap());
584
585static DUMMY_BATCH: LazyLock<RecordBatch> = LazyLock::new(|| {
586 let col = new_null_array(&DataType::Null, 1);
588 RecordBatch::try_new(DUMMY_SCHEMA.clone(), vec![col]).unwrap()
589});
590
591impl ConstEvaluator {
592 pub fn try_new(config_options: Option<Arc<ConfigOptions>>) -> Result<Self> {
602 let mut execution_props = ExecutionProps::new();
606 execution_props.config_options = config_options;
607
608 Ok(Self {
609 can_evaluate: vec![],
610 execution_props,
611 })
612 }
613
614 fn volatility_ok(volatility: Volatility) -> bool {
616 match volatility {
617 Volatility::Immutable => true,
618 Volatility::Stable => true,
620 Volatility::Volatile => false,
621 }
622 }
623
624 fn can_evaluate(expr: &Expr) -> bool {
627 match expr {
633 #[expect(deprecated)]
635 Expr::AggregateFunction { .. }
636 | Expr::ScalarVariable(_, _)
637 | Expr::Column(_)
638 | Expr::OuterReferenceColumn(_, _)
639 | Expr::Exists { .. }
640 | Expr::InSubquery(_)
641 | Expr::SetComparison(_)
642 | Expr::ScalarSubquery(_)
643 | Expr::WindowFunction { .. }
644 | Expr::GroupingSet(_)
645 | Expr::Wildcard { .. }
646 | Expr::Placeholder(_) => false,
647 Expr::ScalarFunction(ScalarFunction { func, .. }) => {
648 Self::volatility_ok(func.signature().volatility)
649 }
650 Expr::HigherOrderFunction(HigherOrderFunction { func, .. }) => {
651 Self::volatility_ok(func.signature().volatility)
652 }
653 Expr::Cast(Cast { expr, field }) | Expr::TryCast(TryCast { expr, field }) => {
654 if let (
655 Ok(DataType::Struct(source_fields)),
656 DataType::Struct(target_fields),
657 ) = (expr.get_type(&DFSchema::empty()), field.data_type())
658 {
659 if source_fields.len() != target_fields.len() {
661 return false;
662 }
663
664 if !has_one_of_more_common_fields(&source_fields, target_fields) {
666 return false;
667 }
668
669 if let Expr::Literal(ScalarValue::Struct(struct_array), _) =
673 expr.as_ref()
674 && struct_array.len() == 0
675 {
676 return false;
677 }
678 }
679 true
680 }
681 Expr::Literal(_, _)
682 | Expr::Alias(..)
683 | Expr::Unnest(_)
684 | Expr::BinaryExpr { .. }
685 | Expr::Not(_)
686 | Expr::IsNotNull(_)
687 | Expr::IsNull(_)
688 | Expr::IsTrue(_)
689 | Expr::IsFalse(_)
690 | Expr::IsUnknown(_)
691 | Expr::IsNotTrue(_)
692 | Expr::IsNotFalse(_)
693 | Expr::IsNotUnknown(_)
694 | Expr::Negative(_)
695 | Expr::Between { .. }
696 | Expr::Like { .. }
697 | Expr::SimilarTo { .. }
698 | Expr::Case(_)
699 | Expr::InList { .. }
700 | Expr::Lambda(_)
701 | Expr::LambdaVariable(_) => true,
702 }
703 }
704
705 pub(crate) fn evaluate_to_scalar(&mut self, expr: Expr) -> ConstSimplifyResult {
707 if let Expr::Literal(s, m) = expr {
708 return ConstSimplifyResult::NotSimplified(s, m);
709 }
710
711 let phys_expr = match create_physical_expr(
712 &expr,
713 &DUMMY_DF_SCHEMA,
714 &self.execution_props,
715 &PhysicalPlanningContext::default(),
716 ) {
717 Ok(e) => e,
718 Err(err) => return ConstSimplifyResult::SimplifyRuntimeError(err, expr),
719 };
720 let metadata = phys_expr
721 .return_field(DUMMY_BATCH.schema_ref())
722 .ok()
723 .and_then(|f| {
724 let m = f.metadata();
725 match m.is_empty() {
726 true => None,
727 false => Some(FieldMetadata::from(m)),
728 }
729 });
730 let col_val = match phys_expr.evaluate(&DUMMY_BATCH) {
731 Ok(v) => v,
732 Err(err) => return ConstSimplifyResult::SimplifyRuntimeError(err, expr),
733 };
734 match col_val {
735 ColumnarValue::Array(a) => {
736 if a.len() != 1 {
737 ConstSimplifyResult::SimplifyRuntimeError(
738 exec_datafusion_err!(
739 "Could not evaluate the expression, found a result of length {}",
740 a.len()
741 ),
742 expr,
743 )
744 } else if as_list_array(&a).is_ok() {
745 ConstSimplifyResult::Simplified(
746 ScalarValue::List(a.as_list::<i32>().to_owned().into()),
747 metadata,
748 )
749 } else if as_large_list_array(&a).is_ok() {
750 ConstSimplifyResult::Simplified(
751 ScalarValue::LargeList(a.as_list::<i64>().to_owned().into()),
752 metadata,
753 )
754 } else {
755 match ScalarValue::try_from_array(&a, 0) {
757 Ok(s) => ConstSimplifyResult::Simplified(s, metadata),
758 Err(err) => ConstSimplifyResult::SimplifyRuntimeError(err, expr),
759 }
760 }
761 }
762 ColumnarValue::Scalar(s) => ConstSimplifyResult::Simplified(s, metadata),
763 }
764 }
765}
766
767struct Simplifier<'a> {
777 info: &'a SimplifyContext,
778}
779
780impl<'a> Simplifier<'a> {
781 pub fn new(info: &'a SimplifyContext) -> Self {
782 Self { info }
783 }
784}
785
786impl TreeNodeRewriter for Simplifier<'_> {
787 type Node = Expr;
788
789 fn f_up(&mut self, expr: Expr) -> Result<Transformed<Expr>> {
791 use datafusion_expr::Operator::{
792 And, BitwiseAnd, BitwiseOr, BitwiseShiftLeft, BitwiseShiftRight, BitwiseXor,
793 Divide, Eq, Modulo, Multiply, NotEq, Or, RegexIMatch, RegexMatch,
794 RegexNotIMatch, RegexNotMatch,
795 };
796
797 let info = self.info;
798 Ok(match expr {
799 ref expr @ Expr::BinaryExpr(BinaryExpr {
803 ref left,
804 ref op,
805 ref right,
806 }) if op.returns_null_on_null()
807 && (is_null(left.as_ref()) || is_null(right.as_ref())) =>
808 {
809 Transformed::yes(Expr::Literal(
810 ScalarValue::try_new_null(&info.get_data_type(expr)?)?,
811 None,
812 ))
813 }
814
815 Expr::BinaryExpr(BinaryExpr {
817 left,
818 op: And | Or,
819 right,
820 }) if is_null(&left) && is_null(&right) => Transformed::yes(lit_bool_null()),
821
822 Expr::BinaryExpr(BinaryExpr {
830 left,
831 op: Eq,
832 right,
833 }) if is_bool_lit(&left) && info.is_boolean_type(&right)? => {
834 Transformed::yes(match as_bool_lit(&left)? {
835 Some(true) => *right,
836 Some(false) => Expr::Not(right),
837 None => lit_bool_null(),
838 })
839 }
840 Expr::BinaryExpr(BinaryExpr {
844 left,
845 op: Eq,
846 right,
847 }) if is_bool_lit(&right) && info.is_boolean_type(&left)? => {
848 Transformed::yes(match as_bool_lit(&right)? {
849 Some(true) => *left,
850 Some(false) => Expr::Not(left),
851 None => lit_bool_null(),
852 })
853 }
854 Expr::BinaryExpr(BinaryExpr {
859 left,
860 op: Eq,
861 right,
862 }) if (left == right) & !left.is_volatile() => {
863 Transformed::yes(match !info.nullable(&left)? {
864 true => lit(true),
865 false => Expr::BinaryExpr(BinaryExpr {
866 left: Box::new(Expr::IsNotNull(left)),
867 op: Or,
868 right: Box::new(lit_bool_null()),
869 }),
870 })
871 }
872
873 Expr::BinaryExpr(BinaryExpr {
880 left,
881 op: NotEq,
882 right,
883 }) if is_bool_lit(&left) && info.is_boolean_type(&right)? => {
884 Transformed::yes(match as_bool_lit(&left)? {
885 Some(true) => Expr::Not(right),
886 Some(false) => *right,
887 None => lit_bool_null(),
888 })
889 }
890 Expr::BinaryExpr(BinaryExpr {
894 left,
895 op: NotEq,
896 right,
897 }) if is_bool_lit(&right) && info.is_boolean_type(&left)? => {
898 Transformed::yes(match as_bool_lit(&right)? {
899 Some(true) => Expr::Not(left),
900 Some(false) => *left,
901 None => lit_bool_null(),
902 })
903 }
904
905 Expr::BinaryExpr(BinaryExpr {
911 left,
912 op: Or,
913 right: _,
914 }) if is_true(&left) => Transformed::yes(*left),
915 Expr::BinaryExpr(BinaryExpr {
917 left,
918 op: Or,
919 right,
920 }) if is_false(&left) => Transformed::yes(*right),
921 Expr::BinaryExpr(BinaryExpr {
923 left: _,
924 op: Or,
925 right,
926 }) if is_true(&right) => Transformed::yes(*right),
927 Expr::BinaryExpr(BinaryExpr {
929 left,
930 op: Or,
931 right,
932 }) if is_false(&right) => Transformed::yes(*left),
933 Expr::BinaryExpr(BinaryExpr {
935 left,
936 op: Or,
937 right,
938 }) if is_not_of(&right, &left) && !info.nullable(&left)? => {
939 Transformed::yes(lit(true))
940 }
941 Expr::BinaryExpr(BinaryExpr {
943 left,
944 op: Or,
945 right,
946 }) if is_not_of(&left, &right) && !info.nullable(&right)? => {
947 Transformed::yes(lit(true))
948 }
949 Expr::BinaryExpr(BinaryExpr {
951 left,
952 op: Or,
953 right,
954 }) if expr_contains(&left, &right, Or) => Transformed::yes(*left),
955 Expr::BinaryExpr(BinaryExpr {
957 left,
958 op: Or,
959 right,
960 }) if expr_contains(&right, &left, Or) => Transformed::yes(*right),
961 Expr::BinaryExpr(BinaryExpr {
963 left,
964 op: Or,
965 right,
966 }) if is_op_with(And, &right, &left) => Transformed::yes(*left),
967 Expr::BinaryExpr(BinaryExpr {
969 left,
970 op: Or,
971 right,
972 }) if is_op_with(And, &left, &right) => Transformed::yes(*right),
973 Expr::BinaryExpr(BinaryExpr {
976 left,
977 op: Or,
978 right,
979 }) if has_common_conjunction(&left, &right) => {
980 let lhs: IndexSet<Expr> = iter_conjunction_owned(*left).collect();
981 let (common, rhs): (Vec<_>, Vec<_>) = iter_conjunction_owned(*right)
982 .partition(|e| lhs.contains(e) && !e.is_volatile());
983
984 let new_rhs = rhs.into_iter().reduce(and);
985 let new_lhs = lhs.into_iter().filter(|e| !common.contains(e)).reduce(and);
986 let common_conjunction = common.into_iter().reduce(and).unwrap();
987
988 let new_expr = match (new_lhs, new_rhs) {
989 (Some(lhs), Some(rhs)) => and(common_conjunction, or(lhs, rhs)),
990 (_, _) => common_conjunction,
991 };
992 Transformed::yes(new_expr)
993 }
994
995 Expr::BinaryExpr(BinaryExpr {
1001 left,
1002 op: And,
1003 right,
1004 }) if is_true(&left) => Transformed::yes(*right),
1005 Expr::BinaryExpr(BinaryExpr {
1007 left,
1008 op: And,
1009 right: _,
1010 }) if is_false(&left) => Transformed::yes(*left),
1011 Expr::BinaryExpr(BinaryExpr {
1013 left,
1014 op: And,
1015 right,
1016 }) if is_true(&right) => Transformed::yes(*left),
1017 Expr::BinaryExpr(BinaryExpr {
1019 left: _,
1020 op: And,
1021 right,
1022 }) if is_false(&right) => Transformed::yes(*right),
1023 Expr::BinaryExpr(BinaryExpr {
1025 left,
1026 op: And,
1027 right,
1028 }) if is_not_of(&right, &left) && !info.nullable(&left)? => {
1029 Transformed::yes(lit(false))
1030 }
1031 Expr::BinaryExpr(BinaryExpr {
1033 left,
1034 op: And,
1035 right,
1036 }) if is_not_of(&left, &right) && !info.nullable(&right)? => {
1037 Transformed::yes(lit(false))
1038 }
1039 Expr::BinaryExpr(BinaryExpr {
1041 left,
1042 op: And,
1043 right,
1044 }) if expr_contains(&left, &right, And) => Transformed::yes(*left),
1045 Expr::BinaryExpr(BinaryExpr {
1047 left,
1048 op: And,
1049 right,
1050 }) if expr_contains(&right, &left, And) => Transformed::yes(*right),
1051 Expr::BinaryExpr(BinaryExpr {
1053 left,
1054 op: And,
1055 right,
1056 }) if is_op_with(Or, &right, &left) => Transformed::yes(*left),
1057 Expr::BinaryExpr(BinaryExpr {
1059 left,
1060 op: And,
1061 right,
1062 }) if is_op_with(Or, &left, &right) => Transformed::yes(*right),
1063 Expr::BinaryExpr(BinaryExpr {
1065 left,
1066 op: And,
1067 right,
1068 }) if can_reduce_to_equal_statement(&left, &right) => {
1069 if let Expr::BinaryExpr(BinaryExpr {
1070 left: left_left,
1071 right: left_right,
1072 ..
1073 }) = *left
1074 {
1075 Transformed::yes(Expr::BinaryExpr(BinaryExpr {
1076 left: left_left,
1077 op: Eq,
1078 right: left_right,
1079 }))
1080 } else {
1081 return internal_err!(
1082 "can_reduce_to_equal_statement should only be called with a BinaryExpr"
1083 );
1084 }
1085 }
1086 Expr::BinaryExpr(BinaryExpr {
1088 left,
1089 op: And,
1090 right,
1091 }) if is_eq_and_ne_with_different_literal(&left, &right) => {
1092 Transformed::yes(*left)
1093 }
1094 Expr::BinaryExpr(BinaryExpr {
1096 left,
1097 op: And,
1098 right,
1099 }) if is_eq_and_ne_with_different_literal(&right, &left) => {
1100 Transformed::yes(*right)
1101 }
1102
1103 Expr::BinaryExpr(BinaryExpr {
1109 left,
1110 op: Multiply,
1111 right,
1112 }) if is_one(&right) => {
1113 simplify_right_is_one_case(info, left, &Multiply, &right)?
1114 }
1115 Expr::BinaryExpr(BinaryExpr {
1117 left,
1118 op: Multiply,
1119 right,
1120 }) if is_one(&left) => {
1121 simplify_right_is_one_case(info, right, &Multiply, &left)?
1123 }
1124
1125 Expr::BinaryExpr(BinaryExpr {
1127 left,
1128 op: Multiply,
1129 right,
1130 }) if !info.nullable(&left)?
1131 && !info.get_data_type(&left)?.is_floating()
1132 && is_zero(&right) =>
1133 {
1134 Transformed::yes(*right)
1135 }
1136 Expr::BinaryExpr(BinaryExpr {
1138 left,
1139 op: Multiply,
1140 right,
1141 }) if !info.nullable(&right)?
1142 && !info.get_data_type(&right)?.is_floating()
1143 && is_zero(&left) =>
1144 {
1145 Transformed::yes(*left)
1146 }
1147
1148 Expr::BinaryExpr(BinaryExpr {
1154 left,
1155 op: Divide,
1156 right,
1157 }) if is_one(&right) => {
1158 simplify_right_is_one_case(info, left, &Divide, &right)?
1159 }
1160
1161 Expr::BinaryExpr(BinaryExpr {
1167 left,
1168 op: Modulo,
1169 right,
1170 }) if !info.nullable(&left)?
1171 && !info.get_data_type(&left)?.is_floating()
1172 && is_one(&right) =>
1173 {
1174 Transformed::yes(Expr::Literal(
1175 ScalarValue::new_zero(&info.get_data_type(&left)?)?,
1176 None,
1177 ))
1178 }
1179
1180 Expr::BinaryExpr(BinaryExpr {
1186 left,
1187 op: BitwiseAnd,
1188 right,
1189 }) if !info.nullable(&left)? && is_zero(&right) => Transformed::yes(*right),
1190
1191 Expr::BinaryExpr(BinaryExpr {
1193 left,
1194 op: BitwiseAnd,
1195 right,
1196 }) if !info.nullable(&right)? && is_zero(&left) => Transformed::yes(*left),
1197
1198 Expr::BinaryExpr(BinaryExpr {
1200 left,
1201 op: BitwiseAnd,
1202 right,
1203 }) if is_negative_of(&left, &right) && !info.nullable(&right)? => {
1204 Transformed::yes(Expr::Literal(
1205 ScalarValue::new_zero(&info.get_data_type(&left)?)?,
1206 None,
1207 ))
1208 }
1209
1210 Expr::BinaryExpr(BinaryExpr {
1212 left,
1213 op: BitwiseAnd,
1214 right,
1215 }) if is_negative_of(&right, &left) && !info.nullable(&left)? => {
1216 Transformed::yes(Expr::Literal(
1217 ScalarValue::new_zero(&info.get_data_type(&left)?)?,
1218 None,
1219 ))
1220 }
1221
1222 Expr::BinaryExpr(BinaryExpr {
1224 left,
1225 op: BitwiseAnd,
1226 right,
1227 }) if expr_contains(&left, &right, BitwiseAnd) => Transformed::yes(*left),
1228
1229 Expr::BinaryExpr(BinaryExpr {
1231 left,
1232 op: BitwiseAnd,
1233 right,
1234 }) if expr_contains(&right, &left, BitwiseAnd) => Transformed::yes(*right),
1235
1236 Expr::BinaryExpr(BinaryExpr {
1238 left,
1239 op: BitwiseAnd,
1240 right,
1241 }) if !info.nullable(&right)? && is_op_with(BitwiseOr, &right, &left) => {
1242 Transformed::yes(*left)
1243 }
1244
1245 Expr::BinaryExpr(BinaryExpr {
1247 left,
1248 op: BitwiseAnd,
1249 right,
1250 }) if !info.nullable(&left)? && is_op_with(BitwiseOr, &left, &right) => {
1251 Transformed::yes(*right)
1252 }
1253
1254 Expr::BinaryExpr(BinaryExpr {
1260 left,
1261 op: BitwiseOr,
1262 right,
1263 }) if is_zero(&right) => Transformed::yes(*left),
1264
1265 Expr::BinaryExpr(BinaryExpr {
1267 left,
1268 op: BitwiseOr,
1269 right,
1270 }) if is_zero(&left) => Transformed::yes(*right),
1271
1272 Expr::BinaryExpr(BinaryExpr {
1274 left,
1275 op: BitwiseOr,
1276 right,
1277 }) if is_negative_of(&left, &right) && !info.nullable(&right)? => {
1278 Transformed::yes(Expr::Literal(
1279 ScalarValue::new_negative_one(&info.get_data_type(&left)?)?,
1280 None,
1281 ))
1282 }
1283
1284 Expr::BinaryExpr(BinaryExpr {
1286 left,
1287 op: BitwiseOr,
1288 right,
1289 }) if is_negative_of(&right, &left) && !info.nullable(&left)? => {
1290 Transformed::yes(Expr::Literal(
1291 ScalarValue::new_negative_one(&info.get_data_type(&left)?)?,
1292 None,
1293 ))
1294 }
1295
1296 Expr::BinaryExpr(BinaryExpr {
1298 left,
1299 op: BitwiseOr,
1300 right,
1301 }) if expr_contains(&left, &right, BitwiseOr) => Transformed::yes(*left),
1302
1303 Expr::BinaryExpr(BinaryExpr {
1305 left,
1306 op: BitwiseOr,
1307 right,
1308 }) if expr_contains(&right, &left, BitwiseOr) => Transformed::yes(*right),
1309
1310 Expr::BinaryExpr(BinaryExpr {
1312 left,
1313 op: BitwiseOr,
1314 right,
1315 }) if !info.nullable(&right)? && is_op_with(BitwiseAnd, &right, &left) => {
1316 Transformed::yes(*left)
1317 }
1318
1319 Expr::BinaryExpr(BinaryExpr {
1321 left,
1322 op: BitwiseOr,
1323 right,
1324 }) if !info.nullable(&left)? && is_op_with(BitwiseAnd, &left, &right) => {
1325 Transformed::yes(*right)
1326 }
1327
1328 Expr::BinaryExpr(BinaryExpr {
1334 left,
1335 op: BitwiseXor,
1336 right,
1337 }) if !info.nullable(&left)? && is_zero(&right) => Transformed::yes(*left),
1338
1339 Expr::BinaryExpr(BinaryExpr {
1341 left,
1342 op: BitwiseXor,
1343 right,
1344 }) if !info.nullable(&right)? && is_zero(&left) => Transformed::yes(*right),
1345
1346 Expr::BinaryExpr(BinaryExpr {
1348 left,
1349 op: BitwiseXor,
1350 right,
1351 }) if is_negative_of(&left, &right) && !info.nullable(&right)? => {
1352 Transformed::yes(Expr::Literal(
1353 ScalarValue::new_negative_one(&info.get_data_type(&left)?)?,
1354 None,
1355 ))
1356 }
1357
1358 Expr::BinaryExpr(BinaryExpr {
1360 left,
1361 op: BitwiseXor,
1362 right,
1363 }) if is_negative_of(&right, &left) && !info.nullable(&left)? => {
1364 Transformed::yes(Expr::Literal(
1365 ScalarValue::new_negative_one(&info.get_data_type(&left)?)?,
1366 None,
1367 ))
1368 }
1369
1370 Expr::BinaryExpr(BinaryExpr {
1372 left,
1373 op: BitwiseXor,
1374 right,
1375 }) if expr_contains(&left, &right, BitwiseXor) => {
1376 let expr = delete_xor_in_complex_expr(&left, &right, false);
1377 Transformed::yes(if expr == *right {
1378 Expr::Literal(
1379 ScalarValue::new_zero(&info.get_data_type(&right)?)?,
1380 None,
1381 )
1382 } else {
1383 expr
1384 })
1385 }
1386
1387 Expr::BinaryExpr(BinaryExpr {
1389 left,
1390 op: BitwiseXor,
1391 right,
1392 }) if expr_contains(&right, &left, BitwiseXor) => {
1393 let expr = delete_xor_in_complex_expr(&right, &left, true);
1394 Transformed::yes(if expr == *left {
1395 Expr::Literal(
1396 ScalarValue::new_zero(&info.get_data_type(&left)?)?,
1397 None,
1398 )
1399 } else {
1400 expr
1401 })
1402 }
1403
1404 Expr::BinaryExpr(BinaryExpr {
1410 left,
1411 op: BitwiseShiftRight,
1412 right,
1413 }) if is_zero(&right) => Transformed::yes(*left),
1414
1415 Expr::BinaryExpr(BinaryExpr {
1421 left,
1422 op: BitwiseShiftLeft,
1423 right,
1424 }) if is_zero(&right) => Transformed::yes(*left),
1425
1426 Expr::Not(inner) => Transformed::yes(negate_clause(*inner)),
1430
1431 Expr::Negative(inner) => Transformed::yes(distribute_negation(*inner)),
1435
1436 Expr::BinaryExpr(BinaryExpr {
1444 left,
1445 op: op @ (Eq | NotEq),
1446 right,
1447 }) if is_case_with_literal_outputs(&left) && is_lit(&right) => {
1448 let case = into_case(*left)?;
1449 Transformed::yes(Expr::Case(Case {
1450 expr: None,
1451 when_then_expr: case
1452 .when_then_expr
1453 .into_iter()
1454 .map(|(when, then)| {
1455 (
1456 when,
1457 Box::new(Expr::BinaryExpr(BinaryExpr {
1458 left: then,
1459 op,
1460 right: right.clone(),
1461 })),
1462 )
1463 })
1464 .collect(),
1465 else_expr: case.else_expr.map(|els| {
1466 Box::new(Expr::BinaryExpr(BinaryExpr {
1467 left: els,
1468 op,
1469 right,
1470 }))
1471 }),
1472 }))
1473 }
1474
1475 Expr::Case(Case {
1481 expr: None,
1482 when_then_expr,
1483 mut else_expr,
1484 }) if when_then_expr
1485 .iter()
1486 .any(|(when, _)| is_true(when.as_ref()) || is_false(when.as_ref())) =>
1487 {
1488 let out_type = info.get_data_type(&when_then_expr[0].1)?;
1489 let mut new_when_then_expr = Vec::with_capacity(when_then_expr.len());
1490
1491 for (when, then) in when_then_expr.into_iter() {
1492 if is_true(when.as_ref()) {
1493 else_expr = Some(then);
1496 break;
1497 } else if !is_false(when.as_ref()) {
1498 new_when_then_expr.push((when, then));
1499 }
1500 }
1502
1503 if new_when_then_expr.is_empty() {
1505 if let Some(else_expr) = else_expr {
1507 return Ok(Transformed::yes(*else_expr));
1508 } else {
1510 let null =
1511 Expr::Literal(ScalarValue::try_new_null(&out_type)?, None);
1512 return Ok(Transformed::yes(null));
1513 }
1514 }
1515
1516 Transformed::yes(Expr::Case(Case {
1517 expr: None,
1518 when_then_expr: new_when_then_expr,
1519 else_expr,
1520 }))
1521 }
1522
1523 Expr::Case(Case {
1535 expr: None,
1536 when_then_expr,
1537 else_expr,
1538 }) if !when_then_expr.is_empty()
1539 && (when_then_expr.len() < 3 || (when_then_expr.iter().all(|(_, then)| is_bool_lit(then))
1543 && when_then_expr.iter().filter(|(_, then)| is_true(then)).count() < 3))
1544 && info.is_boolean_type(&when_then_expr[0].1)? =>
1545 {
1546 let mut filter_expr = lit(false);
1548 let mut out_expr = lit(false);
1550
1551 for (when, then) in when_then_expr {
1552 let when = is_exactly_true(*when, info)?;
1553 let case_expr =
1554 when.clone().and(filter_expr.clone().not()).and(*then);
1555
1556 out_expr = out_expr.or(case_expr);
1557 filter_expr = filter_expr.or(when);
1558 }
1559
1560 let else_expr = else_expr.map(|b| *b).unwrap_or_else(lit_bool_null);
1561 let case_expr = filter_expr.not().and(else_expr);
1562 out_expr = out_expr.or(case_expr);
1563
1564 out_expr.rewrite(self)?
1566 }
1567 Expr::Case(Case {
1588 expr: None,
1589 when_then_expr,
1590 else_expr,
1591 }) if !when_then_expr.is_empty()
1592 && when_then_expr
1593 .iter()
1594 .all(|(_, then)| is_bool_lit(then)) && when_then_expr
1597 .iter()
1598 .filter(|(_, then)| is_false(then))
1599 .count()
1600 < 3
1601 && else_expr.as_deref().is_none_or(is_bool_lit) =>
1602 {
1603 Transformed::yes(
1604 Expr::Case(Case {
1605 expr: None,
1606 when_then_expr: when_then_expr
1607 .into_iter()
1608 .map(|(when, then)| (when, Box::new(Expr::Not(then))))
1609 .collect(),
1610 else_expr: else_expr
1611 .map(|else_expr| Box::new(Expr::Not(else_expr))),
1612 })
1613 .not(),
1614 )
1615 }
1616 Expr::ScalarFunction(ScalarFunction { func: udf, args }) => {
1617 match udf.simplify(args, info)? {
1618 ExprSimplifyResult::Original(args) => {
1619 Transformed::no(Expr::ScalarFunction(ScalarFunction {
1620 func: udf,
1621 args,
1622 }))
1623 }
1624 ExprSimplifyResult::Simplified(expr) => Transformed::yes(expr),
1625 }
1626 }
1627
1628 Expr::AggregateFunction(datafusion_expr::expr::AggregateFunction {
1629 ref func,
1630 ..
1631 }) => match (func.simplify(), expr) {
1632 (Some(simplify_function), Expr::AggregateFunction(af)) => {
1633 Transformed::yes(simplify_function(af, info)?)
1634 }
1635 (_, expr) => Transformed::no(expr),
1636 },
1637
1638 Expr::WindowFunction(ref window_fun) => match (window_fun.simplify(), expr) {
1639 (Some(simplify_function), Expr::WindowFunction(wf)) => {
1640 Transformed::yes(simplify_function(*wf, info)?)
1641 }
1642 (_, expr) => Transformed::no(expr),
1643 },
1644
1645 Expr::Between(between) => Transformed::yes(if between.negated {
1652 let l = *between.expr.clone();
1653 let r = *between.expr;
1654 or(l.lt(*between.low), r.gt(*between.high))
1655 } else {
1656 and(
1657 between.expr.clone().gt_eq(*between.low),
1658 between.expr.lt_eq(*between.high),
1659 )
1660 }),
1661
1662 Expr::BinaryExpr(BinaryExpr {
1666 left,
1667 op: op @ (RegexMatch | RegexNotMatch | RegexIMatch | RegexNotIMatch),
1668 right,
1669 }) => simplify_regex_expr(left, op, right)?,
1670
1671 Expr::Like(like) => {
1673 let escape_char = like.escape_char.unwrap_or('\\');
1675
1676 match StringScalar::try_from_expr(&like.pattern) {
1677 Some(string_scalar) => {
1678 let pattern_str = string_scalar.as_str();
1679 match pattern_str {
1680 None => return Ok(Transformed::yes(lit_bool_null())),
1681 Some("%") => {
1682 let result_for_non_null = lit(!like.negated);
1689 Transformed::yes(if !info.nullable(&like.expr)? {
1690 result_for_non_null
1691 } else {
1692 Expr::Case(Case {
1693 expr: Some(Box::new(Expr::IsNotNull(like.expr))),
1694 when_then_expr: vec![(
1695 Box::new(lit(true)),
1696 Box::new(result_for_non_null),
1697 )],
1698 else_expr: None,
1699 })
1700 })
1701 }
1702 Some(pattern_str)
1703 if pattern_str.contains("%%")
1704 && !pattern_str.contains(escape_char) =>
1705 {
1706 static LIKE_REGEX: LazyLock<Regex> =
1710 LazyLock::new(|| Regex::new("%%+").unwrap());
1711 let simplified_pattern =
1712 LIKE_REGEX.replace_all(pattern_str, "%").to_string();
1713 Transformed::yes(Expr::Like(Like {
1714 pattern: Box::new(
1715 string_scalar.to_expr(&simplified_pattern),
1716 ),
1717 ..like
1718 }))
1719 }
1720 Some(pattern_str)
1721 if !like.case_insensitive
1722 && !pattern_str
1723 .contains(['%', '_', escape_char].as_ref()) =>
1724 {
1725 Transformed::yes(Expr::BinaryExpr(BinaryExpr {
1728 left: like.expr.clone(),
1729 op: if like.negated { NotEq } else { Eq },
1730 right: like.pattern.clone(),
1731 }))
1732 }
1733
1734 Some(_pattern_str) => Transformed::no(Expr::Like(like)),
1735 }
1736 }
1737 None => Transformed::no(Expr::Like(like)),
1738 }
1739 }
1740
1741 Expr::IsNotNull(expr) | Expr::IsNotUnknown(expr)
1743 if !info.nullable(&expr)? =>
1744 {
1745 Transformed::yes(lit(true))
1746 }
1747
1748 Expr::IsNull(expr) | Expr::IsUnknown(expr) if !info.nullable(&expr)? => {
1750 Transformed::yes(lit(false))
1751 }
1752
1753 Expr::InList(InList {
1756 expr: _,
1757 list,
1758 negated,
1759 }) if list.is_empty() => Transformed::yes(lit(negated)),
1760
1761 Expr::InList(InList {
1764 expr,
1765 list,
1766 negated: _,
1767 }) if is_null(expr.as_ref()) && !list.is_empty() => {
1768 Transformed::yes(lit_bool_null())
1769 }
1770
1771 Expr::InList(InList {
1773 expr,
1774 mut list,
1775 negated,
1776 }) if list.len() == 1
1777 && matches!(list.first(), Some(Expr::ScalarSubquery { .. })) =>
1778 {
1779 let Expr::ScalarSubquery(subquery) = list.remove(0) else {
1780 unreachable!()
1781 };
1782
1783 Transformed::yes(Expr::InSubquery(InSubquery::new(
1784 expr, subquery, negated,
1785 )))
1786 }
1787
1788 Expr::BinaryExpr(BinaryExpr {
1792 left,
1793 op: Or,
1794 right,
1795 }) if are_inlist_and_eq(left.as_ref(), right.as_ref()) => {
1796 let lhs = to_inlist(*left).unwrap();
1797 let rhs = to_inlist(*right).unwrap();
1798 #[allow(clippy::allow_attributes, clippy::mutable_key_type)]
1799 let mut seen: HashSet<Expr> = HashSet::new();
1801 let list = lhs
1802 .list
1803 .into_iter()
1804 .chain(rhs.list)
1805 .filter(|e| seen.insert(e.to_owned()))
1806 .collect::<Vec<_>>();
1807
1808 let merged_inlist = InList {
1809 expr: lhs.expr,
1810 list,
1811 negated: false,
1812 };
1813
1814 Transformed::yes(Expr::InList(merged_inlist))
1815 }
1816
1817 Expr::BinaryExpr(BinaryExpr {
1834 left,
1835 op: And,
1836 right,
1837 }) if are_inlist_and_eq_and_match_neg(
1838 left.as_ref(),
1839 right.as_ref(),
1840 false,
1841 false,
1842 ) =>
1843 {
1844 match (*left, *right) {
1845 (Expr::InList(l1), Expr::InList(l2)) => {
1846 return inlist_intersection(l1, &l2, false).map(Transformed::yes);
1847 }
1848 _ => unreachable!(),
1850 }
1851 }
1852
1853 Expr::BinaryExpr(BinaryExpr {
1854 left,
1855 op: And,
1856 right,
1857 }) if are_inlist_and_eq_and_match_neg(
1858 left.as_ref(),
1859 right.as_ref(),
1860 true,
1861 true,
1862 ) =>
1863 {
1864 match (*left, *right) {
1865 (Expr::InList(l1), Expr::InList(l2)) => {
1866 return inlist_union(l1, l2, true).map(Transformed::yes);
1867 }
1868 _ => unreachable!(),
1870 }
1871 }
1872
1873 Expr::BinaryExpr(BinaryExpr {
1874 left,
1875 op: And,
1876 right,
1877 }) if are_inlist_and_eq_and_match_neg(
1878 left.as_ref(),
1879 right.as_ref(),
1880 false,
1881 true,
1882 ) =>
1883 {
1884 match (*left, *right) {
1885 (Expr::InList(l1), Expr::InList(l2)) => {
1886 return inlist_except(l1, &l2).map(Transformed::yes);
1887 }
1888 _ => unreachable!(),
1890 }
1891 }
1892
1893 Expr::BinaryExpr(BinaryExpr {
1894 left,
1895 op: And,
1896 right,
1897 }) if are_inlist_and_eq_and_match_neg(
1898 left.as_ref(),
1899 right.as_ref(),
1900 true,
1901 false,
1902 ) =>
1903 {
1904 match (*left, *right) {
1905 (Expr::InList(l1), Expr::InList(l2)) => {
1906 return inlist_except(l2, &l1).map(Transformed::yes);
1907 }
1908 _ => unreachable!(),
1910 }
1911 }
1912
1913 Expr::BinaryExpr(BinaryExpr {
1914 left,
1915 op: Or,
1916 right,
1917 }) if are_inlist_and_eq_and_match_neg(
1918 left.as_ref(),
1919 right.as_ref(),
1920 true,
1921 true,
1922 ) =>
1923 {
1924 match (*left, *right) {
1925 (Expr::InList(l1), Expr::InList(l2)) => {
1926 return inlist_intersection(l1, &l2, true).map(Transformed::yes);
1927 }
1928 _ => unreachable!(),
1930 }
1931 }
1932
1933 Expr::BinaryExpr(BinaryExpr { left, op, right })
1940 if is_cast_expr_and_support_unwrap_cast_in_comparison_for_binary(
1941 info, &left, op, &right,
1942 ) && op.supports_propagation() =>
1943 {
1944 unwrap_cast_in_comparison_for_binary(info, *left, *right, op)?
1945 }
1946 Expr::BinaryExpr(BinaryExpr { left, op, right })
1950 if is_cast_expr_and_support_unwrap_cast_in_comparison_for_binary(
1951 info, &right, op, &left,
1952 ) && op.supports_propagation()
1953 && op.swap().is_some() =>
1954 {
1955 unwrap_cast_in_comparison_for_binary(
1956 info,
1957 *right,
1958 *left,
1959 op.swap().unwrap(),
1960 )?
1961 }
1962 Expr::InList(InList {
1965 expr: mut left,
1966 list,
1967 negated,
1968 }) if is_cast_expr_and_support_unwrap_cast_in_comparison_for_inlist(
1969 info, &left, &list,
1970 ) =>
1971 {
1972 let (Expr::TryCast(TryCast {
1973 expr: left_expr, ..
1974 })
1975 | Expr::Cast(Cast {
1976 expr: left_expr, ..
1977 })) = left.as_mut()
1978 else {
1979 return internal_err!("Expect cast expr, but got {:?}", left)?;
1980 };
1981
1982 let expr_type = info.get_data_type(left_expr)?;
1983 let right_exprs = list
1984 .into_iter()
1985 .map(|right| {
1986 match right {
1987 Expr::Literal(right_lit_value, _) => {
1988 let Some(value) = try_cast_literal_to_type(&right_lit_value, &expr_type) else {
1991 internal_err!(
1992 "Can't cast the list expr {:?} to type {}",
1993 right_lit_value, &expr_type
1994 )?
1995 };
1996 Ok(lit(value))
1997 }
1998 other_expr => internal_err!(
1999 "Only support literal expr to optimize, but the expr is {:?}",
2000 &other_expr
2001 ),
2002 }
2003 })
2004 .collect::<Result<Vec<_>>>()?;
2005
2006 Transformed::yes(Expr::InList(InList {
2007 expr: std::mem::take(left_expr),
2008 list: right_exprs,
2009 negated,
2010 }))
2011 }
2012
2013 Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
2022 use datafusion_expr::Operator::*;
2023 let is_preimage_op = matches!(
2024 op,
2025 Eq | NotEq
2026 | Lt
2027 | LtEq
2028 | Gt
2029 | GtEq
2030 | IsDistinctFrom
2031 | IsNotDistinctFrom
2032 );
2033 if !is_preimage_op || is_null(&right) {
2034 return Ok(Transformed::no(Expr::BinaryExpr(BinaryExpr {
2035 left,
2036 op,
2037 right,
2038 })));
2039 }
2040
2041 if let PreimageResult::Range { interval, expr } =
2042 get_preimage(left.as_ref(), right.as_ref(), info)?
2043 {
2044 rewrite_with_preimage(*interval, op, expr)?
2045 } else if let Some(swapped) = op.swap() {
2046 if let PreimageResult::Range { interval, expr } =
2047 get_preimage(right.as_ref(), left.as_ref(), info)?
2048 {
2049 rewrite_with_preimage(*interval, swapped, expr)?
2050 } else {
2051 Transformed::no(Expr::BinaryExpr(BinaryExpr { left, op, right }))
2052 }
2053 } else {
2054 Transformed::no(Expr::BinaryExpr(BinaryExpr { left, op, right }))
2055 }
2056 }
2057 Expr::InList(InList {
2060 expr,
2061 list,
2062 negated,
2063 }) => {
2064 if list.len() > THRESHOLD_INLINE_INLIST || list.iter().any(is_null) {
2065 return Ok(Transformed::no(Expr::InList(InList {
2066 expr,
2067 list,
2068 negated,
2069 })));
2070 }
2071
2072 let (op, combiner): (Operator, fn(Expr, Expr) -> Expr) =
2073 if negated { (NotEq, and) } else { (Eq, or) };
2074
2075 let mut rewritten: Option<Expr> = None;
2076 for item in &list {
2077 let PreimageResult::Range { interval, expr } =
2078 get_preimage(expr.as_ref(), item, info)?
2079 else {
2080 return Ok(Transformed::no(Expr::InList(InList {
2081 expr,
2082 list,
2083 negated,
2084 })));
2085 };
2086
2087 let range_expr = rewrite_with_preimage(*interval, op, expr)?.data;
2088 rewritten = Some(match rewritten {
2089 None => range_expr,
2090 Some(acc) => combiner(acc, range_expr),
2091 });
2092 }
2093
2094 if let Some(rewritten) = rewritten {
2095 Transformed::yes(rewritten)
2096 } else {
2097 Transformed::no(Expr::InList(InList {
2098 expr,
2099 list,
2100 negated,
2101 }))
2102 }
2103 }
2104
2105 expr => Transformed::no(expr),
2107 })
2108 }
2109}
2110
2111fn get_preimage(
2112 left_expr: &Expr,
2113 right_expr: &Expr,
2114 info: &SimplifyContext,
2115) -> Result<PreimageResult> {
2116 let Expr::ScalarFunction(ScalarFunction { func, args }) = left_expr else {
2117 return Ok(PreimageResult::None);
2118 };
2119 if !is_literal_or_literal_cast(right_expr) {
2120 return Ok(PreimageResult::None);
2121 }
2122 if func.signature().volatility != Volatility::Immutable {
2123 return Ok(PreimageResult::None);
2124 }
2125 func.preimage(args, right_expr, info)
2126}
2127
2128fn is_literal_or_literal_cast(expr: &Expr) -> bool {
2129 match expr {
2130 Expr::Literal(_, _) => true,
2131 Expr::Cast(Cast { expr, .. }) => matches!(expr.as_ref(), Expr::Literal(_, _)),
2132 Expr::TryCast(TryCast { expr, .. }) => {
2133 matches!(expr.as_ref(), Expr::Literal(_, _))
2134 }
2135 _ => false,
2136 }
2137}
2138
2139pub(crate) enum StringScalar<'a> {
2141 Utf8(&'a ScalarValue),
2142 LargeUtf8(&'a ScalarValue),
2143 Utf8View(&'a ScalarValue),
2144}
2145
2146impl<'a> StringScalar<'a> {
2147 pub(crate) fn try_from_expr(expr: &'a Expr) -> Option<Self> {
2150 match expr {
2151 Expr::Literal(scalar, _) => Self::try_from_scalar(scalar),
2152 _ => None,
2153 }
2154 }
2155
2156 fn try_from_scalar(scalar: &'a ScalarValue) -> Option<Self> {
2159 match scalar {
2160 ScalarValue::Utf8(_) => Some(Self::Utf8(scalar)),
2161 ScalarValue::LargeUtf8(_) => Some(Self::LargeUtf8(scalar)),
2162 ScalarValue::Utf8View(_) => Some(Self::Utf8View(scalar)),
2163 _ => None,
2164 }
2165 }
2166
2167 pub(crate) fn as_str(&self) -> Option<&'a str> {
2169 match self {
2170 Self::Utf8(scalar) | Self::LargeUtf8(scalar) | Self::Utf8View(scalar) => {
2171 scalar.try_as_str().flatten()
2172 }
2173 }
2174 }
2175
2176 pub(crate) fn to_expr(&self, val: &str) -> Expr {
2178 match self {
2179 Self::Utf8(_) => Expr::Literal(ScalarValue::Utf8(Some(val.to_owned())), None),
2180 Self::LargeUtf8(_) => {
2181 Expr::Literal(ScalarValue::LargeUtf8(Some(val.to_owned())), None)
2182 }
2183 Self::Utf8View(_) => {
2184 Expr::Literal(ScalarValue::Utf8View(Some(val.to_owned())), None)
2185 }
2186 }
2187 }
2188}
2189
2190#[allow(clippy::allow_attributes, clippy::mutable_key_type)] fn has_common_conjunction(lhs: &Expr, rhs: &Expr) -> bool {
2192 let lhs_set: HashSet<&Expr> = iter_conjunction(lhs).collect();
2193 iter_conjunction(rhs).any(|e| lhs_set.contains(&e) && !e.is_volatile())
2194}
2195
2196fn are_inlist_and_eq_and_match_neg(
2198 left: &Expr,
2199 right: &Expr,
2200 is_left_neg: bool,
2201 is_right_neg: bool,
2202) -> bool {
2203 match (left, right) {
2204 (Expr::InList(l), Expr::InList(r)) => {
2205 l.expr == r.expr && l.negated == is_left_neg && r.negated == is_right_neg
2206 }
2207 _ => false,
2208 }
2209}
2210
2211fn are_inlist_and_eq(left: &Expr, right: &Expr) -> bool {
2213 let left = as_inlist(left);
2214 let right = as_inlist(right);
2215 if let (Some(lhs), Some(rhs)) = (left, right) {
2216 matches!(lhs.expr.as_ref(), Expr::Column(_))
2217 && matches!(rhs.expr.as_ref(), Expr::Column(_))
2218 && lhs.expr == rhs.expr
2219 && !lhs.negated
2220 && !rhs.negated
2221 } else {
2222 false
2223 }
2224}
2225
2226fn as_inlist(expr: &'_ Expr) -> Option<Cow<'_, InList>> {
2228 match expr {
2229 Expr::InList(inlist) => Some(Cow::Borrowed(inlist)),
2230 Expr::BinaryExpr(BinaryExpr { left, op, right }) if *op == Operator::Eq => {
2231 match (left.as_ref(), right.as_ref()) {
2232 (Expr::Column(_), Expr::Literal(_, _)) => Some(Cow::Owned(InList {
2233 expr: left.clone(),
2234 list: vec![*right.clone()],
2235 negated: false,
2236 })),
2237 (Expr::Literal(_, _), Expr::Column(_)) => Some(Cow::Owned(InList {
2238 expr: right.clone(),
2239 list: vec![*left.clone()],
2240 negated: false,
2241 })),
2242 _ => None,
2243 }
2244 }
2245 _ => None,
2246 }
2247}
2248
2249fn to_inlist(expr: Expr) -> Option<InList> {
2250 match expr {
2251 Expr::InList(inlist) => Some(inlist),
2252 Expr::BinaryExpr(BinaryExpr {
2253 left,
2254 op: Operator::Eq,
2255 right,
2256 }) => match (left.as_ref(), right.as_ref()) {
2257 (Expr::Column(_), Expr::Literal(_, _)) => Some(InList {
2258 expr: left,
2259 list: vec![*right],
2260 negated: false,
2261 }),
2262 (Expr::Literal(_, _), Expr::Column(_)) => Some(InList {
2263 expr: right,
2264 list: vec![*left],
2265 negated: false,
2266 }),
2267 _ => None,
2268 },
2269 _ => None,
2270 }
2271}
2272
2273#[allow(clippy::allow_attributes, clippy::mutable_key_type)] fn inlist_union(mut l1: InList, l2: InList, negated: bool) -> Result<Expr> {
2277 let l1_items: HashSet<_> = l1.list.iter().collect();
2279
2280 let keep_l2: Vec<_> = l2
2282 .list
2283 .into_iter()
2284 .filter_map(|e| if l1_items.contains(&e) { None } else { Some(e) })
2285 .collect();
2286
2287 l1.list.extend(keep_l2);
2288 l1.negated = negated;
2289 Ok(Expr::InList(l1))
2290}
2291
2292#[allow(clippy::allow_attributes, clippy::mutable_key_type)] fn inlist_intersection(mut l1: InList, l2: &InList, negated: bool) -> Result<Expr> {
2296 let l2_items = l2.list.iter().collect::<HashSet<_>>();
2297
2298 l1.list.retain(|e| l2_items.contains(e));
2300
2301 if l1.list.is_empty() {
2304 return Ok(lit(negated));
2305 }
2306 Ok(Expr::InList(l1))
2307}
2308
2309#[allow(clippy::allow_attributes, clippy::mutable_key_type)] fn inlist_except(mut l1: InList, l2: &InList) -> Result<Expr> {
2313 let l2_items = l2.list.iter().collect::<HashSet<_>>();
2314
2315 l1.list.retain(|e| !l2_items.contains(e));
2317
2318 if l1.list.is_empty() {
2319 return Ok(lit(false));
2320 }
2321 Ok(Expr::InList(l1))
2322}
2323
2324fn is_exactly_true(expr: Expr, info: &SimplifyContext) -> Result<Expr> {
2326 if !info.nullable(&expr)? {
2327 Ok(expr)
2328 } else {
2329 Ok(Expr::BinaryExpr(BinaryExpr {
2330 left: Box::new(expr),
2331 op: Operator::IsNotDistinctFrom,
2332 right: Box::new(lit(true)),
2333 }))
2334 }
2335}
2336
2337fn simplify_right_is_one_case(
2342 info: &SimplifyContext,
2343 left: Box<Expr>,
2344 op: &Operator,
2345 right: &Expr,
2346) -> Result<Transformed<Expr>> {
2347 let left_type = info.get_data_type(&left)?;
2349 let right_type = info.get_data_type(right)?;
2350 match BinaryTypeCoercer::new(&left_type, op, &right_type).get_result_type() {
2351 Ok(result_type) => {
2352 if left_type != result_type {
2354 Ok(Transformed::yes(Expr::Cast(Cast::new(left, result_type))))
2355 } else {
2356 Ok(Transformed::yes(*left))
2357 }
2358 }
2359 Err(_) => Ok(Transformed::yes(*left)),
2360 }
2361}
2362
2363#[cfg(test)]
2364mod tests {
2365 use super::*;
2366 use crate::test::test_table_scan_with_name;
2367 use arrow::{
2368 array::{Int32Array, StructArray},
2369 datatypes::{FieldRef, Fields},
2370 };
2371 use datafusion_common::{DFSchemaRef, ToDFSchema, assert_contains};
2372 use datafusion_expr::{
2373 expr::WindowFunction,
2374 function::{
2375 AccumulatorArgs, AggregateFunctionSimplification,
2376 WindowFunctionSimplification,
2377 },
2378 interval_arithmetic::Interval,
2379 *,
2380 };
2381 use datafusion_functions_window_common::field::WindowUDFFieldArgs;
2382 use datafusion_functions_window_common::partition::PartitionEvaluatorArgs;
2383 use datafusion_physical_expr::PhysicalExpr;
2384 use std::hash::Hash;
2385 use std::sync::LazyLock;
2386 use std::{
2387 collections::HashMap,
2388 ops::{BitAnd, BitOr, BitXor},
2389 sync::Arc,
2390 };
2391
2392 #[test]
2396 fn api_basic() {
2397 let simplifier = ExprSimplifier::new(
2398 SimplifyContext::builder()
2399 .with_schema(test_schema())
2400 .build(),
2401 );
2402
2403 let expr = lit(1) + lit(2);
2404 let expected = lit(3);
2405 assert_eq!(expected, simplifier.simplify(expr).unwrap());
2406 }
2407
2408 #[test]
2409 fn basic_coercion() {
2410 let schema = test_schema();
2411 let simplifier = ExprSimplifier::new(
2412 SimplifyContext::builder()
2413 .with_schema(Arc::clone(&schema))
2414 .build(),
2415 );
2416
2417 let expr = (lit(1i64) + lit(2i32)).lt(col("i"));
2420 let expected = lit(3i64).lt(col("i"));
2422
2423 let expr = simplifier.coerce(expr, &schema).unwrap();
2424
2425 assert_eq!(expected, simplifier.simplify(expr).unwrap());
2426 }
2427
2428 fn test_schema() -> DFSchemaRef {
2429 static TEST_SCHEMA: LazyLock<DFSchemaRef> = LazyLock::new(|| {
2430 Schema::new(vec![
2431 Field::new("i", DataType::Int64, false),
2432 Field::new("b", DataType::Boolean, true),
2433 ])
2434 .to_dfschema_ref()
2435 .unwrap()
2436 });
2437 Arc::clone(&TEST_SCHEMA)
2438 }
2439
2440 #[test]
2441 fn simplify_and_constant_prop() {
2442 let simplifier = ExprSimplifier::new(
2443 SimplifyContext::builder()
2444 .with_schema(test_schema())
2445 .build(),
2446 );
2447
2448 let expr = (col("i") * (lit(1) - lit(1))).gt(lit(0));
2451 let expected = lit(false);
2452 assert_eq!(expected, simplifier.simplify(expr).unwrap());
2453 }
2454
2455 #[test]
2456 fn simplify_and_constant_prop_with_case() {
2457 let simplifier = ExprSimplifier::new(
2458 SimplifyContext::builder()
2459 .with_schema(test_schema())
2460 .build(),
2461 );
2462
2463 let expr = when(col("i").gt(lit(5)).and(lit(false)), col("i").gt(lit(5)))
2471 .when(col("i").lt(lit(5)).and(lit(true)), col("i").lt(lit(5)))
2472 .otherwise(lit(false))
2473 .unwrap();
2474 let expected = col("i").lt(lit(5));
2475 assert_eq!(expected, simplifier.simplify(expr).unwrap());
2476 }
2477
2478 #[test]
2483 fn test_simplify_canonicalize() {
2484 {
2485 let expr = lit(1).lt(col("c2")).and(col("c2").gt(lit(1)));
2486 let expected = col("c2").gt(lit(1));
2487 assert_eq!(simplify(expr), expected);
2488 }
2489 {
2490 let expr = col("c1").lt(col("c2")).and(col("c2").gt(col("c1")));
2491 let expected = col("c2").gt(col("c1"));
2492 assert_eq!(simplify(expr), expected);
2493 }
2494 {
2495 let expr = col("c1")
2496 .eq(lit(1))
2497 .and(lit(1).eq(col("c1")))
2498 .and(col("c1").eq(lit(3)));
2499 let expected = col("c1").eq(lit(1)).and(col("c1").eq(lit(3)));
2500 assert_eq!(simplify(expr), expected);
2501 }
2502 {
2503 let expr = col("c1")
2504 .eq(col("c2"))
2505 .and(col("c1").gt(lit(5)))
2506 .and(col("c2").eq(col("c1")));
2507 let expected = col("c2").eq(col("c1")).and(col("c1").gt(lit(5)));
2508 assert_eq!(simplify(expr), expected);
2509 }
2510 {
2511 let expr = col("c1")
2512 .eq(lit(1))
2513 .and(col("c2").gt(lit(3)).or(lit(3).lt(col("c2"))));
2514 let expected = col("c1").eq(lit(1)).and(col("c2").gt(lit(3)));
2515 assert_eq!(simplify(expr), expected);
2516 }
2517 {
2518 let expr = col("c1").lt(lit(5)).and(col("c1").gt_eq(lit(5)));
2519 let expected = col("c1").lt(lit(5)).and(col("c1").gt_eq(lit(5)));
2520 assert_eq!(simplify(expr), expected);
2521 }
2522 {
2523 let expr = col("c1").lt(lit(5)).and(col("c1").gt_eq(lit(5)));
2524 let expected = col("c1").lt(lit(5)).and(col("c1").gt_eq(lit(5)));
2525 assert_eq!(simplify(expr), expected);
2526 }
2527 {
2528 let expr = col("c1").gt(col("c2")).and(col("c1").gt(col("c2")));
2529 let expected = col("c2").lt(col("c1"));
2530 assert_eq!(simplify(expr), expected);
2531 }
2532 }
2533
2534 #[test]
2535 fn test_simplify_eq_not_self() {
2536 let expr_a = col("c2").eq(col("c2"));
2539 let expected_a = col("c2").is_not_null().or(lit_bool_null());
2540
2541 let expr_b = col("c2_non_null").eq(col("c2_non_null"));
2543 let expected_b = lit(true);
2544
2545 assert_eq!(simplify(expr_a), expected_a);
2546 assert_eq!(simplify(expr_b), expected_b);
2547 }
2548
2549 fn in_subquery_expr(a_nullable: bool) -> Expr {
2551 let schema = Schema::new(vec![Field::new("a", DataType::Int64, a_nullable)]);
2552 let source = Arc::new(LogicalTableSource::new(Arc::new(schema)));
2553 let subquery = LogicalPlanBuilder::scan("t", source, None)
2554 .unwrap()
2555 .project(vec![col("a")])
2556 .unwrap()
2557 .build()
2558 .unwrap();
2559
2560 in_subquery(col("c3_non_null"), Arc::new(subquery))
2561 }
2562
2563 #[test]
2564 fn test_simplify_eq_not_self_in_subquery() {
2565 let expr_a = in_subquery_expr(true);
2569 let expected_a = expr_a.clone().is_not_null().or(lit_bool_null());
2570
2571 let expr_b = in_subquery_expr(false);
2573 let expected_b = lit(true);
2574
2575 assert_eq!(simplify(expr_a.clone().eq(expr_a)), expected_a);
2576 assert_eq!(simplify(expr_b.clone().eq(expr_b)), expected_b);
2577 }
2578
2579 #[test]
2580 fn test_simplify_or_true() {
2581 let expr_a = col("c2").or(lit(true));
2582 let expr_b = lit(true).or(col("c2"));
2583 let expected = lit(true);
2584
2585 assert_eq!(simplify(expr_a), expected);
2586 assert_eq!(simplify(expr_b), expected);
2587 }
2588
2589 #[test]
2590 fn test_simplify_or_false() {
2591 let expr_a = lit(false).or(col("c2"));
2592 let expr_b = col("c2").or(lit(false));
2593 let expected = col("c2");
2594
2595 assert_eq!(simplify(expr_a), expected);
2596 assert_eq!(simplify(expr_b), expected);
2597 }
2598
2599 #[test]
2600 fn test_simplify_or_same() {
2601 let expr = col("c2").or(col("c2"));
2602 let expected = col("c2");
2603
2604 assert_eq!(simplify(expr), expected);
2605 }
2606
2607 #[test]
2608 fn test_simplify_or_not_self() {
2609 let expr_a = col("c2_non_null").or(col("c2_non_null").not());
2612 let expr_b = col("c2_non_null").not().or(col("c2_non_null"));
2613 let expected = lit(true);
2614
2615 assert_eq!(simplify(expr_a), expected);
2616 assert_eq!(simplify(expr_b), expected);
2617 }
2618
2619 #[test]
2620 fn test_simplify_and_false() {
2621 let expr_a = lit(false).and(col("c2"));
2622 let expr_b = col("c2").and(lit(false));
2623 let expected = lit(false);
2624
2625 assert_eq!(simplify(expr_a), expected);
2626 assert_eq!(simplify(expr_b), expected);
2627 }
2628
2629 #[test]
2630 fn test_simplify_and_same() {
2631 let expr = col("c2").and(col("c2"));
2632 let expected = col("c2");
2633
2634 assert_eq!(simplify(expr), expected);
2635 }
2636
2637 #[test]
2638 fn test_simplify_and_true() {
2639 let expr_a = lit(true).and(col("c2"));
2640 let expr_b = col("c2").and(lit(true));
2641 let expected = col("c2");
2642
2643 assert_eq!(simplify(expr_a), expected);
2644 assert_eq!(simplify(expr_b), expected);
2645 }
2646
2647 #[test]
2648 fn test_simplify_and_not_self() {
2649 let expr_a = col("c2_non_null").and(col("c2_non_null").not());
2652 let expr_b = col("c2_non_null").not().and(col("c2_non_null"));
2653 let expected = lit(false);
2654
2655 assert_eq!(simplify(expr_a), expected);
2656 assert_eq!(simplify(expr_b), expected);
2657 }
2658
2659 #[test]
2660 fn test_simplify_eq_and_neq_with_different_literals() {
2661 let expr = col("c2").eq(lit(1)).and(col("c2").not_eq(lit(0)));
2663 let expected = col("c2").eq(lit(1));
2664 assert_eq!(simplify(expr), expected);
2665
2666 let expr = col("c2").not_eq(lit(0)).and(col("c2").eq(lit(1)));
2668 let expected = col("c2").eq(lit(1));
2669 assert_eq!(simplify(expr), expected);
2670
2671 let expr = col("c2").eq(lit(1)).and(col("c2").not_eq(lit(1)));
2674 let result = simplify(expr.clone());
2676 assert_eq!(result, expr);
2678 }
2679
2680 #[test]
2681 fn test_simplify_multiply_by_one() {
2682 let expr_a = col("c2") * lit(1);
2683 let expr_b = lit(1) * col("c2");
2684 let expected = col("c2");
2685
2686 assert_eq!(simplify(expr_a), expected);
2687 assert_eq!(simplify(expr_b), expected);
2688
2689 let expr = col("c2") * lit(ScalarValue::Decimal128(Some(10000000000), 38, 10));
2690 assert_eq!(simplify(expr), expected);
2691
2692 let expr = lit(ScalarValue::Decimal128(Some(10000000000), 31, 10)) * col("c2");
2693 assert_eq!(simplify(expr), expected);
2694 }
2695
2696 #[test]
2697 fn test_simplify_multiply_by_null() {
2698 let null = lit(ScalarValue::Int64(None));
2699 {
2701 let expr = col("c3") * null.clone();
2702 assert_eq!(simplify(expr), null);
2703 }
2704 {
2706 let expr = null.clone() * col("c3");
2707 assert_eq!(simplify(expr), null);
2708 }
2709 }
2710
2711 #[test]
2712 fn test_simplify_multiply_by_zero() {
2713 {
2715 let expr_a = col("c2") * lit(0);
2716 let expr_b = lit(0) * col("c2");
2717
2718 assert_eq!(simplify(expr_a.clone()), expr_a);
2719 assert_eq!(simplify(expr_b.clone()), expr_b);
2720 }
2721 {
2723 let expr = lit(0) * col("c2_non_null");
2724 assert_eq!(simplify(expr), lit(0));
2725 }
2726 {
2728 let expr = col("c2_non_null") * lit(0);
2729 assert_eq!(simplify(expr), lit(0));
2730 }
2731 {
2733 let expr = col("c2_non_null") * lit(ScalarValue::Decimal128(Some(0), 31, 10));
2734 assert_eq!(
2735 simplify(expr),
2736 lit(ScalarValue::Decimal128(Some(0), 31, 10))
2737 );
2738 let expr = binary_expr(
2739 lit(ScalarValue::Decimal128(Some(0), 31, 10)),
2740 Operator::Multiply,
2741 col("c2_non_null"),
2742 );
2743 assert_eq!(
2744 simplify(expr),
2745 lit(ScalarValue::Decimal128(Some(0), 31, 10))
2746 );
2747 }
2748 }
2749
2750 #[test]
2751 fn test_simplify_divide_by_one() {
2752 let expr = binary_expr(col("c2"), Operator::Divide, lit(1));
2753 let expected = col("c2");
2754 assert_eq!(simplify(expr), expected);
2755 let expr = col("c2") / lit(ScalarValue::Decimal128(Some(10000000000), 31, 10));
2756 assert_eq!(simplify(expr), expected);
2757 }
2758
2759 #[test]
2760 fn test_simplify_divide_null() {
2761 let null = lit(ScalarValue::Int64(None));
2763 {
2764 let expr = col("c3") / null.clone();
2765 assert_eq!(simplify(expr), null);
2766 }
2767 {
2769 let expr = null.clone() / col("c3");
2770 assert_eq!(simplify(expr), null);
2771 }
2772 }
2773
2774 #[test]
2775 fn test_simplify_divide_by_same() {
2776 let expr = col("c2") / col("c2");
2777 let expected = expr.clone();
2779
2780 assert_eq!(simplify(expr), expected);
2781 }
2782
2783 #[test]
2784 fn test_simplify_modulo_by_null() {
2785 let null = lit(ScalarValue::Int64(None));
2786 {
2788 let expr = col("c3") % null.clone();
2789 assert_eq!(simplify(expr), null);
2790 }
2791 {
2793 let expr = null.clone() % col("c3");
2794 assert_eq!(simplify(expr), null);
2795 }
2796 }
2797
2798 #[test]
2799 fn test_simplify_modulo_by_one() {
2800 let expr = col("c2") % lit(1);
2801 let expected = expr.clone();
2803
2804 assert_eq!(simplify(expr), expected);
2805 }
2806
2807 #[test]
2808 fn test_simplify_divide_zero_by_zero() {
2809 let expr = lit(0) / lit(0);
2812 let expected = expr.clone();
2813
2814 assert_eq!(simplify(expr), expected);
2815 }
2816
2817 #[test]
2818 fn test_simplify_divide_by_zero() {
2819 let expr = col("c2_non_null") / lit(0);
2822 let expected = expr.clone();
2823
2824 assert_eq!(simplify(expr), expected);
2825 }
2826
2827 #[test]
2828 fn test_simplify_modulo_by_one_non_null() {
2829 let expr = col("c3_non_null") % lit(1);
2830 let expected = lit(0_i64);
2831 assert_eq!(simplify(expr), expected);
2832 let expr =
2833 col("c3_non_null") % lit(ScalarValue::Decimal128(Some(10000000000), 31, 10));
2834 assert_eq!(simplify(expr), expected);
2835 }
2836
2837 #[test]
2838 fn test_simplify_bitwise_xor_by_null() {
2839 let null = lit(ScalarValue::Int64(None));
2840 {
2842 let expr = col("c3") ^ null.clone();
2843 assert_eq!(simplify(expr), null);
2844 }
2845 {
2847 let expr = null.clone() ^ col("c3");
2848 assert_eq!(simplify(expr), null);
2849 }
2850 }
2851
2852 #[test]
2853 fn test_simplify_bitwise_shift_right_by_null() {
2854 let null = lit(ScalarValue::Int64(None));
2855 {
2857 let expr = col("c3") >> null.clone();
2858 assert_eq!(simplify(expr), null);
2859 }
2860 {
2862 let expr = null.clone() >> col("c3");
2863 assert_eq!(simplify(expr), null);
2864 }
2865 }
2866
2867 #[test]
2868 fn test_simplify_bitwise_shift_left_by_null() {
2869 let null = lit(ScalarValue::Int64(None));
2870 {
2872 let expr = col("c3") << null.clone();
2873 assert_eq!(simplify(expr), null);
2874 }
2875 {
2877 let expr = null.clone() << col("c3");
2878 assert_eq!(simplify(expr), null);
2879 }
2880 }
2881
2882 #[test]
2883 fn test_simplify_bitwise_and_by_zero() {
2884 {
2886 let expr = col("c2_non_null") & lit(0);
2887 assert_eq!(simplify(expr), lit(0));
2888 }
2889 {
2891 let expr = lit(0) & col("c2_non_null");
2892 assert_eq!(simplify(expr), lit(0));
2893 }
2894 }
2895
2896 #[test]
2897 fn test_simplify_bitwise_or_by_zero() {
2898 {
2900 let expr = col("c2_non_null") | lit(0);
2901 assert_eq!(simplify(expr), col("c2_non_null"));
2902 }
2903 {
2905 let expr = lit(0) | col("c2_non_null");
2906 assert_eq!(simplify(expr), col("c2_non_null"));
2907 }
2908 }
2909
2910 #[test]
2911 fn test_simplify_bitwise_xor_by_zero() {
2912 {
2914 let expr = col("c2_non_null") ^ lit(0);
2915 assert_eq!(simplify(expr), col("c2_non_null"));
2916 }
2917 {
2919 let expr = lit(0) ^ col("c2_non_null");
2920 assert_eq!(simplify(expr), col("c2_non_null"));
2921 }
2922 }
2923
2924 #[test]
2925 fn test_simplify_bitwise_bitwise_shift_right_by_zero() {
2926 {
2928 let expr = col("c2_non_null") >> lit(0);
2929 assert_eq!(simplify(expr), col("c2_non_null"));
2930 }
2931 }
2932
2933 #[test]
2934 fn test_simplify_bitwise_bitwise_shift_left_by_zero() {
2935 {
2937 let expr = col("c2_non_null") << lit(0);
2938 assert_eq!(simplify(expr), col("c2_non_null"));
2939 }
2940 }
2941
2942 #[test]
2943 fn test_simplify_bitwise_and_by_null() {
2944 let null = Expr::Literal(ScalarValue::Int64(None), None);
2945 {
2947 let expr = col("c3") & null.clone();
2948 assert_eq!(simplify(expr), null);
2949 }
2950 {
2952 let expr = null.clone() & col("c3");
2953 assert_eq!(simplify(expr), null);
2954 }
2955 }
2956
2957 #[test]
2958 fn test_simplify_concat_by_null() {
2959 let null = Expr::Literal(ScalarValue::Utf8(None), None);
2960 {
2962 let expr = binary_expr(col("c1"), Operator::StringConcat, null.clone());
2963 assert_eq!(simplify(expr), null);
2964 }
2965 {
2967 let expr = binary_expr(null.clone(), Operator::StringConcat, col("c1"));
2968 assert_eq!(simplify(expr), null);
2969 }
2970 }
2971
2972 #[test]
2973 fn test_simplify_composed_bitwise_and() {
2974 let expr = bitwise_and(
2977 bitwise_and(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
2978 col("c2").gt(lit(5)),
2979 );
2980 let expected = bitwise_and(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
2981
2982 assert_eq!(simplify(expr), expected);
2983
2984 let expr = bitwise_and(
2987 col("c2").gt(lit(5)),
2988 bitwise_and(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
2989 );
2990 let expected = bitwise_and(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
2991 assert_eq!(simplify(expr), expected);
2992 }
2993
2994 #[test]
2995 fn test_simplify_composed_bitwise_or() {
2996 let expr = bitwise_or(
2999 bitwise_or(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
3000 col("c2").gt(lit(5)),
3001 );
3002 let expected = bitwise_or(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
3003
3004 assert_eq!(simplify(expr), expected);
3005
3006 let expr = bitwise_or(
3009 col("c2").gt(lit(5)),
3010 bitwise_or(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
3011 );
3012 let expected = bitwise_or(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
3013
3014 assert_eq!(simplify(expr), expected);
3015 }
3016
3017 #[test]
3018 fn test_simplify_composed_bitwise_xor() {
3019 let expr = bitwise_xor(
3023 col("c2"),
3024 bitwise_xor(
3025 bitwise_xor(col("c2"), bitwise_or(col("c2"), col("c1"))),
3026 bitwise_and(col("c1"), col("c2")),
3027 ),
3028 );
3029
3030 let expected = bitwise_xor(
3031 bitwise_or(col("c2"), col("c1")),
3032 bitwise_and(col("c1"), col("c2")),
3033 );
3034
3035 assert_eq!(simplify(expr), expected);
3036
3037 let expr = bitwise_xor(
3041 col("c2"),
3042 bitwise_xor(
3043 bitwise_xor(col("c2"), bitwise_or(col("c2"), col("c1"))),
3044 bitwise_xor(bitwise_and(col("c1"), col("c2")), col("c2")),
3045 ),
3046 );
3047
3048 let expected = bitwise_xor(
3049 col("c2"),
3050 bitwise_xor(
3051 bitwise_or(col("c2"), col("c1")),
3052 bitwise_and(col("c1"), col("c2")),
3053 ),
3054 );
3055
3056 assert_eq!(simplify(expr), expected);
3057
3058 let expr = bitwise_xor(
3062 bitwise_xor(
3063 bitwise_xor(col("c2"), bitwise_or(col("c2"), col("c1"))),
3064 bitwise_and(col("c1"), col("c2")),
3065 ),
3066 col("c2"),
3067 );
3068
3069 let expected = bitwise_xor(
3070 bitwise_or(col("c2"), col("c1")),
3071 bitwise_and(col("c1"), col("c2")),
3072 );
3073
3074 assert_eq!(simplify(expr), expected);
3075
3076 let expr = bitwise_xor(
3080 bitwise_xor(
3081 bitwise_xor(col("c2"), bitwise_or(col("c2"), col("c1"))),
3082 bitwise_xor(bitwise_and(col("c1"), col("c2")), col("c2")),
3083 ),
3084 col("c2"),
3085 );
3086
3087 let expected = bitwise_xor(
3088 bitwise_xor(
3089 bitwise_or(col("c2"), col("c1")),
3090 bitwise_and(col("c1"), col("c2")),
3091 ),
3092 col("c2"),
3093 );
3094
3095 assert_eq!(simplify(expr), expected);
3096 }
3097
3098 #[test]
3099 fn test_simplify_negated_bitwise_and() {
3100 let expr = (-col("c3_non_null")) & col("c3_non_null");
3102 let expected = lit(0i64);
3103
3104 assert_eq!(simplify(expr), expected);
3105 let expr = col("c3_non_null") & (-col("c3_non_null"));
3107 let expected = lit(0i64);
3108
3109 assert_eq!(simplify(expr), expected);
3110 }
3111
3112 #[test]
3113 fn test_simplify_negated_bitwise_or() {
3114 let expr = (-col("c3_non_null")) | col("c3_non_null");
3116 let expected = lit(-1i64);
3117
3118 assert_eq!(simplify(expr), expected);
3119
3120 let expr = col("c3_non_null") | (-col("c3_non_null"));
3122 let expected = lit(-1i64);
3123
3124 assert_eq!(simplify(expr), expected);
3125 }
3126
3127 #[test]
3128 fn test_simplify_negated_bitwise_xor() {
3129 let expr = (-col("c3_non_null")) ^ col("c3_non_null");
3131 let expected = lit(-1i64);
3132
3133 assert_eq!(simplify(expr), expected);
3134
3135 let expr = col("c3_non_null") ^ (-col("c3_non_null"));
3137 let expected = lit(-1i64);
3138
3139 assert_eq!(simplify(expr), expected);
3140 }
3141
3142 #[test]
3143 fn test_simplify_bitwise_and_or() {
3144 let expr = bitwise_and(
3146 col("c2_non_null").lt(lit(3)),
3147 bitwise_or(col("c2_non_null").lt(lit(3)), col("c1_non_null")),
3148 );
3149 let expected = col("c2_non_null").lt(lit(3));
3150
3151 assert_eq!(simplify(expr), expected);
3152 }
3153
3154 #[test]
3155 fn test_simplify_bitwise_or_and() {
3156 let expr = bitwise_or(
3158 col("c2_non_null").lt(lit(3)),
3159 bitwise_and(col("c2_non_null").lt(lit(3)), col("c1_non_null")),
3160 );
3161 let expected = col("c2_non_null").lt(lit(3));
3162
3163 assert_eq!(simplify(expr), expected);
3164 }
3165
3166 #[test]
3167 fn test_simplify_simple_bitwise_and() {
3168 let expr = (col("c2").gt(lit(5))).bitand(col("c2").gt(lit(5)));
3170 let expected = col("c2").gt(lit(5));
3171
3172 assert_eq!(simplify(expr), expected);
3173 }
3174
3175 #[test]
3176 fn test_simplify_simple_bitwise_or() {
3177 let expr = (col("c2").gt(lit(5))).bitor(col("c2").gt(lit(5)));
3179 let expected = col("c2").gt(lit(5));
3180
3181 assert_eq!(simplify(expr), expected);
3182 }
3183
3184 #[test]
3185 fn test_simplify_simple_bitwise_xor() {
3186 let expr = (col("c4")).bitxor(col("c4"));
3188 let expected = lit(0u32);
3189
3190 assert_eq!(simplify(expr), expected);
3191
3192 let expr = col("c3").bitxor(col("c3"));
3194 let expected = lit(0i64);
3195
3196 assert_eq!(simplify(expr), expected);
3197 }
3198
3199 #[test]
3200 fn test_simplify_modulo_by_zero_non_null() {
3201 let expr = col("c2_non_null") % lit(0);
3204 let expected = expr.clone();
3205
3206 assert_eq!(simplify(expr), expected);
3207 }
3208
3209 #[test]
3210 fn test_simplify_simple_and() {
3211 let expr = (col("c2").gt(lit(5))).and(col("c2").gt(lit(5)));
3213 let expected = col("c2").gt(lit(5));
3214
3215 assert_eq!(simplify(expr), expected);
3216 }
3217
3218 #[test]
3219 fn test_simplify_composed_and() {
3220 let expr = and(
3222 and(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
3223 col("c2").gt(lit(5)),
3224 );
3225 let expected = and(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
3226
3227 assert_eq!(simplify(expr), expected);
3228 }
3229
3230 #[test]
3231 fn test_simplify_negated_and() {
3232 let expr = and(col("c2").gt(lit(5)), Expr::not(col("c2").gt(lit(5))));
3234 let expected = col("c2").gt(lit(5)).and(col("c2").lt_eq(lit(5)));
3235
3236 assert_eq!(simplify(expr), expected);
3237 }
3238
3239 #[test]
3240 fn test_simplify_or_and() {
3241 let l = col("c2").gt(lit(5));
3242 let r = and(col("c1").lt(lit(6)), col("c2").gt(lit(5)));
3243
3244 let expr = or(l.clone(), r.clone());
3246
3247 let expected = l.clone();
3248 assert_eq!(simplify(expr), expected);
3249
3250 let expr = or(r, l);
3252 assert_eq!(simplify(expr), expected);
3253 }
3254
3255 #[test]
3256 fn test_simplify_or_and_non_null() {
3257 let l = col("c2_non_null").gt(lit(5));
3258 let r = and(col("c1_non_null").lt(lit(6)), col("c2_non_null").gt(lit(5)));
3259
3260 let expr = or(l.clone(), r.clone());
3262
3263 let expected = col("c2_non_null").gt(lit(5));
3265
3266 assert_eq!(simplify(expr), expected);
3267
3268 let expr = or(l, r);
3270
3271 assert_eq!(simplify(expr), expected);
3272 }
3273
3274 #[test]
3275 fn test_simplify_and_or() {
3276 let l = col("c2").gt(lit(5));
3277 let r = or(col("c1").lt(lit(6)), col("c2").gt(lit(5)));
3278
3279 let expr = and(l.clone(), r.clone());
3281
3282 let expected = l.clone();
3283 assert_eq!(simplify(expr), expected);
3284
3285 let expr = and(r, l);
3287 assert_eq!(simplify(expr), expected);
3288 }
3289
3290 #[test]
3291 fn test_simplify_and_or_non_null() {
3292 let l = col("c2_non_null").gt(lit(5));
3293 let r = or(col("c1_non_null").lt(lit(6)), col("c2_non_null").gt(lit(5)));
3294
3295 let expr = and(l.clone(), r.clone());
3297
3298 let expected = col("c2_non_null").gt(lit(5));
3300
3301 assert_eq!(simplify(expr), expected);
3302
3303 let expr = and(l, r);
3305
3306 assert_eq!(simplify(expr), expected);
3307 }
3308
3309 #[test]
3310 fn test_simplify_by_de_morgan_laws() {
3311 let expr = and(col("c3"), col("c4")).not();
3314 let expected = or(col("c3").not(), col("c4").not());
3315 assert_eq!(simplify(expr), expected);
3316 let expr = or(col("c3"), col("c4")).not();
3318 let expected = and(col("c3").not(), col("c4").not());
3319 assert_eq!(simplify(expr), expected);
3320 let expr = col("c3").not().not();
3322 let expected = col("c3");
3323 assert_eq!(simplify(expr), expected);
3324
3325 let expr = -bitwise_and(col("c3"), col("c4"));
3328 let expected = bitwise_or(-col("c3"), -col("c4"));
3329 assert_eq!(simplify(expr), expected);
3330 let expr = -bitwise_or(col("c3"), col("c4"));
3332 let expected = bitwise_and(-col("c3"), -col("c4"));
3333 assert_eq!(simplify(expr), expected);
3334 let expr = -(-col("c3"));
3336 let expected = col("c3");
3337 assert_eq!(simplify(expr), expected);
3338 }
3339
3340 #[test]
3341 fn test_simplify_null_and_false() {
3342 let expr = and(lit_bool_null(), lit(false));
3343 let expr_eq = lit(false);
3344
3345 assert_eq!(simplify(expr), expr_eq);
3346 }
3347
3348 #[test]
3349 fn test_simplify_divide_null_by_null() {
3350 let null = lit(ScalarValue::Int32(None));
3351 let expr_plus = null.clone() / null.clone();
3352 let expr_eq = null;
3353
3354 assert_eq!(simplify(expr_plus), expr_eq);
3355 }
3356
3357 #[test]
3358 fn test_simplify_simplify_arithmetic_expr() {
3359 let expr_plus = lit(1) + lit(1);
3360
3361 assert_eq!(simplify(expr_plus), lit(2));
3362 }
3363
3364 #[test]
3365 fn test_simplify_simplify_eq_expr() {
3366 let expr_eq = binary_expr(lit(1), Operator::Eq, lit(1));
3367
3368 assert_eq!(simplify(expr_eq), lit(true));
3369 }
3370
3371 #[test]
3372 fn test_simplify_regex() {
3373 assert_contains!(
3375 try_simplify(regex_match(col("c1"), lit("foo{")))
3376 .unwrap_err()
3377 .to_string(),
3378 "regex parse error"
3379 );
3380
3381 assert_no_change(regex_match(col("c1"), lit("foo.*")));
3383 assert_no_change(regex_match(col("c1"), lit("(foo)")));
3384 assert_no_change(regex_match(col("c1"), lit("%")));
3385 assert_no_change(regex_match(col("c1"), lit("_")));
3386 assert_no_change(regex_match(col("c1"), lit("f%o")));
3387 assert_no_change(regex_match(col("c1"), lit("^f%o")));
3388 assert_no_change(regex_match(col("c1"), lit("f_o")));
3389
3390 assert_change(
3392 regex_match(col("c1"), lit("")),
3393 if_not_null(col("c1"), true),
3394 );
3395 assert_change(
3396 regex_not_match(col("c1"), lit("")),
3397 if_not_null(col("c1"), false),
3398 );
3399 assert_change(
3400 regex_imatch(col("c1"), lit("")),
3401 if_not_null(col("c1"), true),
3402 );
3403 assert_change(
3404 regex_not_imatch(col("c1"), lit("")),
3405 if_not_null(col("c1"), false),
3406 );
3407
3408 assert_change(regex_match(col("c1"), lit("x")), col("c1").like(lit("%x%")));
3410
3411 assert_change(
3413 regex_match(col("c1"), lit("foo")),
3414 col("c1").like(lit("%foo%")),
3415 );
3416
3417 assert_change(regex_match(col("c1"), lit("^$")), col("c1").eq(lit("")));
3419 assert_change(
3420 regex_not_match(col("c1"), lit("^$")),
3421 col("c1").not_eq(lit("")),
3422 );
3423 assert_change(
3424 regex_match(col("c1"), lit("^foo$")),
3425 col("c1").eq(lit("foo")),
3426 );
3427 assert_change(
3428 regex_not_match(col("c1"), lit("^foo$")),
3429 col("c1").not_eq(lit("foo")),
3430 );
3431
3432 assert_change(
3434 regex_match(col("c1"), lit("^(foo|bar)$")),
3435 col("c1").eq(lit("foo")).or(col("c1").eq(lit("bar"))),
3436 );
3437 assert_change(
3438 regex_not_match(col("c1"), lit("^(foo|bar)$")),
3439 col("c1")
3440 .not_eq(lit("foo"))
3441 .and(col("c1").not_eq(lit("bar"))),
3442 );
3443 assert_change(
3444 regex_match(col("c1"), lit("^(foo)$")),
3445 col("c1").eq(lit("foo")),
3446 );
3447 assert_change(
3448 regex_match(col("c1"), lit("^(foo|bar|baz)$")),
3449 ((col("c1").eq(lit("foo"))).or(col("c1").eq(lit("bar"))))
3450 .or(col("c1").eq(lit("baz"))),
3451 );
3452 assert_change(
3453 regex_match(col("c1"), lit("^(foo|bar|baz|qux)$")),
3454 col("c1")
3455 .in_list(vec![lit("foo"), lit("bar"), lit("baz"), lit("qux")], false),
3456 );
3457 assert_change(
3458 regex_match(col("c1"), lit("^(fo_o)$")),
3459 col("c1").eq(lit("fo_o")),
3460 );
3461 assert_change(
3462 regex_match(col("c1"), lit("^(fo_o)$")),
3463 col("c1").eq(lit("fo_o")),
3464 );
3465 assert_change(
3466 regex_match(col("c1"), lit("^(fo_o|ba_r)$")),
3467 col("c1").eq(lit("fo_o")).or(col("c1").eq(lit("ba_r"))),
3468 );
3469 assert_change(
3470 regex_not_match(col("c1"), lit("^(fo_o|ba_r)$")),
3471 col("c1")
3472 .not_eq(lit("fo_o"))
3473 .and(col("c1").not_eq(lit("ba_r"))),
3474 );
3475 assert_change(
3476 regex_match(col("c1"), lit("^(fo_o|ba_r|ba_z)$")),
3477 ((col("c1").eq(lit("fo_o"))).or(col("c1").eq(lit("ba_r"))))
3478 .or(col("c1").eq(lit("ba_z"))),
3479 );
3480 assert_change(
3481 regex_match(col("c1"), lit("^(fo_o|ba_r|baz|qu_x)$")),
3482 col("c1").in_list(
3483 vec![lit("fo_o"), lit("ba_r"), lit("baz"), lit("qu_x")],
3484 false,
3485 ),
3486 );
3487
3488 assert_no_change(regex_match(col("c1"), lit("(foo|bar)")));
3490 assert_no_change(regex_match(col("c1"), lit("(foo|bar)*")));
3491 assert_no_change(regex_match(col("c1"), lit("(fo_o|b_ar)")));
3492 assert_no_change(regex_match(col("c1"), lit("(foo|ba_r)*")));
3493 assert_no_change(regex_match(col("c1"), lit("(fo_o|ba_r)*")));
3494 assert_no_change(regex_match(col("c1"), lit("^(foo|bar)*")));
3495 assert_no_change(regex_match(col("c1"), lit("^(foo)(bar)$")));
3496 assert_no_change(regex_match(col("c1"), lit("^")));
3497 assert_no_change(regex_match(col("c1"), lit("$")));
3498 assert_no_change(regex_match(col("c1"), lit("$^")));
3499 assert_no_change(regex_match(col("c1"), lit("$foo^")));
3500
3501 assert_change(
3503 regex_match(col("c1"), lit("^foo")),
3504 col("c1").like(lit("foo%")),
3505 );
3506 assert_change(
3507 regex_match(col("c1"), lit("foo$")),
3508 col("c1").like(lit("%foo")),
3509 );
3510 assert_change(
3511 regex_match(col("c1"), lit("^foo|bar$")),
3512 col("c1").like(lit("foo%")).or(col("c1").like(lit("%bar"))),
3513 );
3514
3515 assert_change(
3517 regex_match(col("c1"), lit("foo|bar|baz")),
3518 col("c1")
3519 .like(lit("%foo%"))
3520 .or(col("c1").like(lit("%bar%")))
3521 .or(col("c1").like(lit("%baz%"))),
3522 );
3523 assert_change(
3524 regex_match(col("c1"), lit("foo|x|baz")),
3525 col("c1")
3526 .like(lit("%foo%"))
3527 .or(col("c1").like(lit("%x%")))
3528 .or(col("c1").like(lit("%baz%"))),
3529 );
3530 assert_change(
3531 regex_not_match(col("c1"), lit("foo|bar|baz")),
3532 col("c1")
3533 .not_like(lit("%foo%"))
3534 .and(col("c1").not_like(lit("%bar%")))
3535 .and(col("c1").not_like(lit("%baz%"))),
3536 );
3537 assert_change(
3539 regex_match(col("c1"), lit("foo|^x$|baz")),
3540 col("c1")
3541 .like(lit("%foo%"))
3542 .or(col("c1").eq(lit("x")))
3543 .or(col("c1").like(lit("%baz%"))),
3544 );
3545 assert_change(
3546 regex_not_match(col("c1"), lit("foo|^bar$|baz")),
3547 col("c1")
3548 .not_like(lit("%foo%"))
3549 .and(col("c1").not_eq(lit("bar")))
3550 .and(col("c1").not_like(lit("%baz%"))),
3551 );
3552 assert_no_change(regex_match(col("c1"), lit("foo|bar|baz|blarg|bozo|etc")));
3554 }
3555
3556 #[test]
3557 fn test_simplify_not_regex_match() {
3558 let pattern = || lit("foo.*");
3559
3560 assert_eq!(
3562 simplify(regex_match(col("c1"), pattern()).not()),
3563 regex_not_match(col("c1"), pattern()),
3564 );
3565 assert_eq!(
3567 simplify(regex_not_match(col("c1"), pattern()).not()),
3568 regex_match(col("c1"), pattern()),
3569 );
3570 assert_eq!(
3572 simplify(regex_imatch(col("c1"), pattern()).not()),
3573 regex_not_imatch(col("c1"), pattern()),
3574 );
3575 assert_eq!(
3577 simplify(regex_not_imatch(col("c1"), pattern()).not()),
3578 regex_imatch(col("c1"), pattern()),
3579 );
3580 }
3581
3582 #[track_caller]
3583 fn assert_no_change(expr: Expr) {
3584 let optimized = simplify(expr.clone());
3585 assert_eq!(expr, optimized);
3586 }
3587
3588 #[track_caller]
3589 fn assert_change(expr: Expr, expected: Expr) {
3590 let optimized = simplify(expr);
3591 assert_eq!(optimized, expected);
3592 }
3593
3594 fn regex_match(left: Expr, right: Expr) -> Expr {
3595 Expr::BinaryExpr(BinaryExpr {
3596 left: Box::new(left),
3597 op: Operator::RegexMatch,
3598 right: Box::new(right),
3599 })
3600 }
3601
3602 fn regex_not_match(left: Expr, right: Expr) -> Expr {
3603 Expr::BinaryExpr(BinaryExpr {
3604 left: Box::new(left),
3605 op: Operator::RegexNotMatch,
3606 right: Box::new(right),
3607 })
3608 }
3609
3610 fn regex_imatch(left: Expr, right: Expr) -> Expr {
3611 Expr::BinaryExpr(BinaryExpr {
3612 left: Box::new(left),
3613 op: Operator::RegexIMatch,
3614 right: Box::new(right),
3615 })
3616 }
3617
3618 fn regex_not_imatch(left: Expr, right: Expr) -> Expr {
3619 Expr::BinaryExpr(BinaryExpr {
3620 left: Box::new(left),
3621 op: Operator::RegexNotIMatch,
3622 right: Box::new(right),
3623 })
3624 }
3625
3626 fn try_simplify(expr: Expr) -> Result<Expr> {
3631 let schema = expr_test_schema();
3632 let simplifier =
3633 ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build());
3634 simplifier.simplify(expr)
3635 }
3636
3637 fn coerce(expr: Expr) -> Expr {
3638 let schema = expr_test_schema();
3639 let simplifier = ExprSimplifier::new(
3640 SimplifyContext::builder()
3641 .with_schema(Arc::clone(&schema))
3642 .build(),
3643 );
3644 simplifier.coerce(expr, schema.as_ref()).unwrap()
3645 }
3646
3647 fn simplify(expr: Expr) -> Expr {
3648 try_simplify(expr).unwrap()
3649 }
3650
3651 fn try_simplify_with_cycle_count(expr: Expr) -> Result<(Expr, u32)> {
3652 let schema = expr_test_schema();
3653 let simplifier =
3654 ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build());
3655 let (expr, count) = simplifier.simplify_with_cycle_count_transformed(expr)?;
3656 Ok((expr.data, count))
3657 }
3658
3659 fn simplify_with_cycle_count(expr: Expr) -> (Expr, u32) {
3660 try_simplify_with_cycle_count(expr).unwrap()
3661 }
3662
3663 fn simplify_with_guarantee(
3664 expr: Expr,
3665 guarantees: Vec<(Expr, NullableInterval)>,
3666 ) -> Expr {
3667 let schema = expr_test_schema();
3668 let simplifier =
3669 ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build())
3670 .with_guarantees(guarantees);
3671 simplifier.simplify(expr).unwrap()
3672 }
3673
3674 fn expr_test_schema() -> DFSchemaRef {
3675 static EXPR_TEST_SCHEMA: LazyLock<DFSchemaRef> = LazyLock::new(|| {
3676 Arc::new(
3677 DFSchema::from_unqualified_fields(
3678 vec![
3679 Field::new("c1", DataType::Utf8, true),
3680 Field::new("c2", DataType::Boolean, true),
3681 Field::new("c3", DataType::Int64, true),
3682 Field::new("c4", DataType::UInt32, true),
3683 Field::new("c1_non_null", DataType::Utf8, false),
3684 Field::new("c2_non_null", DataType::Boolean, false),
3685 Field::new("c3_non_null", DataType::Int64, false),
3686 Field::new("c4_non_null", DataType::UInt32, false),
3687 Field::new("c5", DataType::FixedSizeBinary(3), true),
3688 ]
3689 .into(),
3690 HashMap::new(),
3691 )
3692 .unwrap(),
3693 )
3694 });
3695 Arc::clone(&EXPR_TEST_SCHEMA)
3696 }
3697
3698 #[test]
3699 fn simplify_expr_null_comparison() {
3700 assert_eq!(
3702 simplify(lit(true).eq(lit(ScalarValue::Boolean(None)))),
3703 lit(ScalarValue::Boolean(None)),
3704 );
3705
3706 assert_eq!(
3708 simplify(
3709 lit(ScalarValue::Boolean(None)).not_eq(lit(ScalarValue::Boolean(None)))
3710 ),
3711 lit(ScalarValue::Boolean(None)),
3712 );
3713
3714 assert_eq!(
3716 simplify(col("c2").not_eq(lit(ScalarValue::Boolean(None)))),
3717 lit(ScalarValue::Boolean(None)),
3718 );
3719
3720 assert_eq!(
3722 simplify(lit(ScalarValue::Boolean(None)).eq(col("c2"))),
3723 lit(ScalarValue::Boolean(None)),
3724 );
3725 }
3726
3727 #[test]
3728 fn simplify_expr_is_not_null() {
3729 assert_eq!(
3730 simplify(Expr::IsNotNull(Box::new(col("c1")))),
3731 Expr::IsNotNull(Box::new(col("c1")))
3732 );
3733
3734 assert_eq!(
3736 simplify(Expr::IsNotNull(Box::new(col("c1_non_null")))),
3737 lit(true)
3738 );
3739 }
3740
3741 #[test]
3742 fn simplify_expr_is_null() {
3743 assert_eq!(
3744 simplify(Expr::IsNull(Box::new(col("c1")))),
3745 Expr::IsNull(Box::new(col("c1")))
3746 );
3747
3748 assert_eq!(
3750 simplify(Expr::IsNull(Box::new(col("c1_non_null")))),
3751 lit(false)
3752 );
3753 }
3754
3755 #[test]
3756 fn simplify_expr_is_unknown() {
3757 assert_eq!(simplify(col("c2").is_unknown()), col("c2").is_unknown(),);
3758
3759 assert_eq!(simplify(col("c2_non_null").is_unknown()), lit(false));
3761 }
3762
3763 #[test]
3764 fn simplify_expr_is_not_known() {
3765 assert_eq!(
3766 simplify(col("c2").is_not_unknown()),
3767 col("c2").is_not_unknown()
3768 );
3769
3770 assert_eq!(simplify(col("c2_non_null").is_not_unknown()), lit(true));
3772 }
3773
3774 #[test]
3775 fn simplify_expr_eq() {
3776 let schema = expr_test_schema();
3777 assert_eq!(col("c2").get_type(&schema).unwrap(), DataType::Boolean);
3778
3779 assert_eq!(simplify(lit(true).eq(lit(true))), lit(true));
3781
3782 assert_eq!(simplify(lit(true).eq(lit(false))), lit(false),);
3784
3785 assert_eq!(simplify(col("c2").eq(lit(true))), col("c2"));
3787
3788 assert_eq!(simplify(col("c2").eq(lit(false))), col("c2").not(),);
3790 }
3791
3792 #[test]
3793 fn simplify_expr_eq_skip_nonboolean_type() {
3794 let schema = expr_test_schema();
3795
3796 assert_eq!(col("c1").get_type(&schema).unwrap(), DataType::Utf8);
3802
3803 assert_eq!(simplify(col("c1").eq(lit("foo"))), col("c1").eq(lit("foo")),);
3805 }
3806
3807 #[test]
3808 fn simplify_expr_not_eq() {
3809 let schema = expr_test_schema();
3810
3811 assert_eq!(col("c2").get_type(&schema).unwrap(), DataType::Boolean);
3812
3813 assert_eq!(simplify(col("c2").not_eq(lit(true))), col("c2").not(),);
3815
3816 assert_eq!(simplify(col("c2").not_eq(lit(false))), col("c2"),);
3818
3819 assert_eq!(simplify(lit(true).not_eq(lit(true))), lit(false),);
3821
3822 assert_eq!(simplify(lit(true).not_eq(lit(false))), lit(true),);
3823 }
3824
3825 #[test]
3826 fn simplify_expr_not_eq_skip_nonboolean_type() {
3827 let schema = expr_test_schema();
3828
3829 assert_eq!(col("c1").get_type(&schema).unwrap(), DataType::Utf8);
3833
3834 assert_eq!(
3835 simplify(col("c1").not_eq(lit("foo"))),
3836 col("c1").not_eq(lit("foo")),
3837 );
3838 }
3839
3840 #[test]
3841 fn simplify_literal_case_equality() {
3842 let simple_case = Expr::Case(Case::new(
3844 None,
3845 vec![(
3846 Box::new(col("c2_non_null").not_eq(lit(false))),
3847 Box::new(lit("ok")),
3848 )],
3849 Some(Box::new(lit("not_ok"))),
3850 ));
3851
3852 assert_eq!(
3860 simplify(binary_expr(simple_case.clone(), Operator::Eq, lit("ok"),)),
3861 col("c2_non_null"),
3862 );
3863
3864 assert_eq!(
3872 simplify(binary_expr(simple_case, Operator::NotEq, lit("ok"),)),
3873 not(col("c2_non_null")),
3874 );
3875
3876 let complex_case = Expr::Case(Case::new(
3877 None,
3878 vec![
3879 (
3880 Box::new(col("c1").eq(lit("inboxed"))),
3881 Box::new(lit("pending")),
3882 ),
3883 (
3884 Box::new(col("c1").eq(lit("scheduled"))),
3885 Box::new(lit("pending")),
3886 ),
3887 (
3888 Box::new(col("c1").eq(lit("completed"))),
3889 Box::new(lit("completed")),
3890 ),
3891 (
3892 Box::new(col("c1").eq(lit("paused"))),
3893 Box::new(lit("paused")),
3894 ),
3895 (Box::new(col("c2")), Box::new(lit("running"))),
3896 (
3897 Box::new(col("c1").eq(lit("invoked")).and(col("c3").gt(lit(0)))),
3898 Box::new(lit("backing-off")),
3899 ),
3900 ],
3901 Some(Box::new(lit("ready"))),
3902 ));
3903
3904 assert_eq!(
3905 simplify(binary_expr(
3906 complex_case.clone(),
3907 Operator::Eq,
3908 lit("completed"),
3909 )),
3910 not_distinct_from(col("c1").eq(lit("completed")), lit(true)).and(
3911 distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3912 .and(distinct_from(col("c1").eq(lit("scheduled")), lit(true)))
3913 )
3914 );
3915
3916 assert_eq!(
3917 simplify(binary_expr(
3918 complex_case.clone(),
3919 Operator::NotEq,
3920 lit("completed"),
3921 )),
3922 distinct_from(col("c1").eq(lit("completed")), lit(true))
3923 .or(not_distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3924 .or(not_distinct_from(col("c1").eq(lit("scheduled")), lit(true))))
3925 );
3926
3927 assert_eq!(
3928 simplify(binary_expr(
3929 complex_case.clone(),
3930 Operator::Eq,
3931 lit("running"),
3932 )),
3933 not_distinct_from(col("c2"), lit(true)).and(
3934 distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3935 .and(distinct_from(col("c1").eq(lit("scheduled")), lit(true)))
3936 .and(distinct_from(col("c1").eq(lit("completed")), lit(true)))
3937 .and(distinct_from(col("c1").eq(lit("paused")), lit(true)))
3938 )
3939 );
3940
3941 assert_eq!(
3942 simplify(binary_expr(
3943 complex_case.clone(),
3944 Operator::Eq,
3945 lit("ready"),
3946 )),
3947 distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3948 .and(distinct_from(col("c1").eq(lit("scheduled")), lit(true)))
3949 .and(distinct_from(col("c1").eq(lit("completed")), lit(true)))
3950 .and(distinct_from(col("c1").eq(lit("paused")), lit(true)))
3951 .and(distinct_from(col("c2"), lit(true)))
3952 .and(distinct_from(
3953 col("c1").eq(lit("invoked")).and(col("c3").gt(lit(0))),
3954 lit(true)
3955 ))
3956 );
3957
3958 assert_eq!(
3959 simplify(binary_expr(
3960 complex_case.clone(),
3961 Operator::NotEq,
3962 lit("ready"),
3963 )),
3964 not_distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3965 .or(not_distinct_from(col("c1").eq(lit("scheduled")), lit(true)))
3966 .or(not_distinct_from(col("c1").eq(lit("completed")), lit(true)))
3967 .or(not_distinct_from(col("c1").eq(lit("paused")), lit(true)))
3968 .or(not_distinct_from(col("c2"), lit(true)))
3969 .or(not_distinct_from(
3970 col("c1").eq(lit("invoked")).and(col("c3").gt(lit(0))),
3971 lit(true)
3972 ))
3973 );
3974 }
3975
3976 #[test]
3977 fn simplify_expr_case_when_then_else() {
3978 assert_eq!(
3984 simplify(Expr::Case(Case::new(
3985 None,
3986 vec![(
3987 Box::new(col("c2_non_null").not_eq(lit(false))),
3988 Box::new(lit("ok").eq(lit("not_ok"))),
3989 )],
3990 Some(Box::new(col("c2_non_null").eq(lit(true)))),
3991 ))),
3992 lit(false) );
3994
3995 assert_eq!(
4004 simplify(simplify(Expr::Case(Case::new(
4005 None,
4006 vec![(
4007 Box::new(col("c2_non_null").not_eq(lit(false))),
4008 Box::new(lit("ok").eq(lit("ok"))),
4009 )],
4010 Some(Box::new(col("c2_non_null").eq(lit(true)))),
4011 )))),
4012 col("c2_non_null")
4013 );
4014
4015 assert_eq!(
4022 simplify(simplify(Expr::Case(Case::new(
4023 None,
4024 vec![(Box::new(col("c2").is_null()), Box::new(lit(true)),)],
4025 Some(Box::new(col("c2"))),
4026 )))),
4027 col("c2")
4028 .is_null()
4029 .or(col("c2").is_not_null().and(col("c2")))
4030 );
4031
4032 assert_eq!(
4040 simplify(simplify(Expr::Case(Case::new(
4041 None,
4042 vec![
4043 (Box::new(col("c1_non_null")), Box::new(lit(true)),),
4044 (Box::new(col("c2_non_null")), Box::new(lit(false)),),
4045 ],
4046 Some(Box::new(lit(true))),
4047 )))),
4048 col("c1_non_null").or(col("c1_non_null").not().and(col("c2_non_null").not()))
4049 );
4050
4051 assert_eq!(
4059 simplify(simplify(Expr::Case(Case::new(
4060 None,
4061 vec![
4062 (Box::new(col("c1_non_null")), Box::new(lit(true)),),
4063 (Box::new(col("c2_non_null")), Box::new(lit(false)),),
4064 ],
4065 Some(Box::new(lit(true))),
4066 )))),
4067 col("c1_non_null").or(col("c1_non_null").not().and(col("c2_non_null").not()))
4068 );
4069
4070 assert_eq!(
4072 simplify(simplify(Expr::Case(Case::new(
4073 None,
4074 vec![(Box::new(col("c3").gt(lit(0_i64))), Box::new(lit(true)))],
4075 None,
4076 )))),
4077 not_distinct_from(col("c3").gt(lit(0_i64)), lit(true)).or(distinct_from(
4078 col("c3").gt(lit(0_i64)),
4079 lit(true)
4080 )
4081 .and(lit_bool_null()))
4082 );
4083
4084 assert_eq!(
4086 simplify(simplify(Expr::Case(Case::new(
4087 None,
4088 vec![(Box::new(col("c3").gt(lit(0_i64))), Box::new(lit(true)))],
4089 Some(Box::new(lit(false))),
4090 )))),
4091 not_distinct_from(col("c3").gt(lit(0_i64)), lit(true))
4092 );
4093 }
4094
4095 #[test]
4096 fn simplify_expr_case_when_first_true() {
4097 assert_eq!(
4099 simplify(Expr::Case(Case::new(
4100 None,
4101 vec![(Box::new(lit(true)), Box::new(lit(1)),)],
4102 Some(Box::new(col("c1"))),
4103 ))),
4104 lit(1)
4105 );
4106
4107 assert_eq!(
4109 simplify(Expr::Case(Case::new(
4110 None,
4111 vec![(Box::new(lit(true)), Box::new(lit("a")),)],
4112 Some(Box::new(lit("b"))),
4113 ))),
4114 lit("a")
4115 );
4116
4117 assert_eq!(
4119 simplify(Expr::Case(Case::new(
4120 None,
4121 vec![
4122 (Box::new(lit(true)), Box::new(lit("a"))),
4123 (Box::new(lit("x").gt(lit(5))), Box::new(lit("b"))),
4124 ],
4125 Some(Box::new(lit("c"))),
4126 ))),
4127 lit("a")
4128 );
4129
4130 assert_eq!(
4132 simplify(Expr::Case(Case::new(
4133 None,
4134 vec![(Box::new(lit(true)), Box::new(lit("a")),)],
4135 None,
4136 ))),
4137 lit("a")
4138 );
4139
4140 let expr = Expr::Case(Case::new(
4142 None,
4143 vec![(Box::new(col("c2")), Box::new(lit(1)))],
4144 Some(Box::new(lit(2))),
4145 ));
4146 assert_eq!(simplify(expr.clone()), expr);
4147
4148 let expr = Expr::Case(Case::new(
4150 None,
4151 vec![(Box::new(lit(false)), Box::new(lit(1)))],
4152 Some(Box::new(lit(2))),
4153 ));
4154 assert_ne!(simplify(expr), lit(1));
4155
4156 let expr = Expr::Case(Case::new(
4158 None,
4159 vec![(Box::new(col("c1").gt(lit(5))), Box::new(lit(1)))],
4160 Some(Box::new(lit(2))),
4161 ));
4162 assert_eq!(simplify(expr.clone()), expr);
4163 }
4164
4165 #[test]
4166 fn simplify_expr_case_when_any_true() {
4167 assert_eq!(
4169 simplify(Expr::Case(Case::new(
4170 None,
4171 vec![
4172 (Box::new(col("c3").gt(lit(0))), Box::new(lit("a"))),
4173 (Box::new(lit(true)), Box::new(lit("b"))),
4174 ],
4175 Some(Box::new(lit("c"))),
4176 ))),
4177 Expr::Case(Case::new(
4178 None,
4179 vec![(Box::new(col("c3").gt(lit(0))), Box::new(lit("a")))],
4180 Some(Box::new(lit("b"))),
4181 ))
4182 );
4183
4184 assert_eq!(
4187 simplify(Expr::Case(Case::new(
4188 None,
4189 vec![
4190 (Box::new(col("c3").gt(lit(0))), Box::new(lit("a"))),
4191 (Box::new(col("c4").lt(lit(0))), Box::new(lit("b"))),
4192 (Box::new(lit(true)), Box::new(lit("c"))),
4193 (Box::new(col("c3").eq(lit(0))), Box::new(lit("d"))),
4194 ],
4195 Some(Box::new(lit("e"))),
4196 ))),
4197 Expr::Case(Case::new(
4198 None,
4199 vec![
4200 (Box::new(col("c3").gt(lit(0))), Box::new(lit("a"))),
4201 (Box::new(col("c4").lt(lit(0))), Box::new(lit("b"))),
4202 ],
4203 Some(Box::new(lit("c"))),
4204 ))
4205 );
4206
4207 assert_eq!(
4210 simplify(Expr::Case(Case::new(
4211 None,
4212 vec![
4213 (Box::new(col("c3").gt(lit(0))), Box::new(lit(1))),
4214 (Box::new(col("c4").lt(lit(0))), Box::new(lit(2))),
4215 (Box::new(lit(true)), Box::new(lit(3))),
4216 ],
4217 None,
4218 ))),
4219 Expr::Case(Case::new(
4220 None,
4221 vec![
4222 (Box::new(col("c3").gt(lit(0))), Box::new(lit(1))),
4223 (Box::new(col("c4").lt(lit(0))), Box::new(lit(2))),
4224 ],
4225 Some(Box::new(lit(3))),
4226 ))
4227 );
4228
4229 let expr = Expr::Case(Case::new(
4231 None,
4232 vec![
4233 (Box::new(col("c3").gt(lit(0))), Box::new(col("c3"))),
4234 (Box::new(col("c4").lt(lit(0))), Box::new(lit(2))),
4235 ],
4236 Some(Box::new(lit(3))),
4237 ));
4238 assert_eq!(simplify(expr.clone()), expr);
4239 }
4240
4241 #[test]
4242 fn simplify_expr_case_when_any_false() {
4243 assert_eq!(
4245 simplify(Expr::Case(Case::new(
4246 None,
4247 vec![(Box::new(lit(false)), Box::new(lit("a")))],
4248 None,
4249 ))),
4250 Expr::Literal(ScalarValue::Utf8(None), None)
4251 );
4252
4253 assert_eq!(
4255 simplify(Expr::Case(Case::new(
4256 None,
4257 vec![(Box::new(lit(false)), Box::new(lit(2)))],
4258 Some(Box::new(lit(1))),
4259 ))),
4260 lit(1),
4261 );
4262
4263 assert_eq!(
4265 simplify(Expr::Case(Case::new(
4266 None,
4267 vec![
4268 (Box::new(col("c3").lt(lit(10))), Box::new(lit("b"))),
4269 (Box::new(lit(false)), Box::new(col("c3"))),
4270 ],
4271 Some(Box::new(col("c4"))),
4272 ))),
4273 Expr::Case(Case::new(
4274 None,
4275 vec![(Box::new(col("c3").lt(lit(10))), Box::new(lit("b")))],
4276 Some(Box::new(col("c4"))),
4277 ))
4278 );
4279
4280 let expr = Expr::Case(Case::new(
4282 None,
4283 vec![(Box::new(col("c3").eq(lit(4))), Box::new(lit(1)))],
4284 Some(Box::new(lit(2))),
4285 ));
4286 assert_eq!(simplify(expr.clone()), expr);
4287 }
4288
4289 fn distinct_from(left: impl Into<Expr>, right: impl Into<Expr>) -> Expr {
4290 Expr::BinaryExpr(BinaryExpr {
4291 left: Box::new(left.into()),
4292 op: Operator::IsDistinctFrom,
4293 right: Box::new(right.into()),
4294 })
4295 }
4296
4297 fn not_distinct_from(left: impl Into<Expr>, right: impl Into<Expr>) -> Expr {
4298 Expr::BinaryExpr(BinaryExpr {
4299 left: Box::new(left.into()),
4300 op: Operator::IsNotDistinctFrom,
4301 right: Box::new(right.into()),
4302 })
4303 }
4304
4305 #[test]
4306 fn simplify_expr_bool_or() {
4307 assert_eq!(simplify(col("c2").or(lit(true))), lit(true),);
4309
4310 assert_eq!(simplify(col("c2").or(lit(false))), col("c2"),);
4312
4313 assert_eq!(simplify(lit(true).or(lit_bool_null())), lit(true),);
4315
4316 assert_eq!(simplify(lit_bool_null().or(lit(true))), lit(true),);
4318
4319 assert_eq!(simplify(lit(false).or(lit_bool_null())), lit_bool_null(),);
4321
4322 assert_eq!(simplify(lit_bool_null().or(lit(false))), lit_bool_null(),);
4324
4325 let expr = col("c1").between(lit(0), lit(10));
4329 let expr = expr.or(lit_bool_null());
4330 let result = simplify(expr);
4331
4332 let expected_expr = or(
4333 and(col("c1").gt_eq(lit(0)), col("c1").lt_eq(lit(10))),
4334 lit_bool_null(),
4335 );
4336 assert_eq!(expected_expr, result);
4337 }
4338
4339 #[test]
4340 fn simplify_inlist() {
4341 assert_eq!(simplify(in_list(col("c1"), vec![], false)), lit(false));
4342 assert_eq!(simplify(in_list(col("c1"), vec![], true)), lit(true));
4343
4344 assert_eq!(
4346 simplify(in_list(lit_bool_null(), vec![col("c1"), lit(1)], false)),
4347 lit_bool_null()
4348 );
4349
4350 assert_eq!(
4352 simplify(in_list(lit_bool_null(), vec![col("c1"), lit(1)], true)),
4353 lit_bool_null()
4354 );
4355
4356 assert_eq!(
4357 simplify(in_list(col("c1"), vec![lit(1)], false)),
4358 col("c1").eq(lit(1))
4359 );
4360 assert_eq!(
4361 simplify(in_list(col("c1"), vec![lit(1)], true)),
4362 col("c1").not_eq(lit(1))
4363 );
4364
4365 assert_eq!(
4368 simplify(in_list(col("c1") * lit(10), vec![lit(2)], false)),
4369 (col("c1") * lit(10)).eq(lit(2))
4370 );
4371
4372 assert_eq!(
4373 simplify(in_list(col("c1"), vec![lit(1), lit(2)], false)),
4374 col("c1").eq(lit(1)).or(col("c1").eq(lit(2)))
4375 );
4376 assert_eq!(
4377 simplify(in_list(col("c1"), vec![lit(1), lit(2)], true)),
4378 col("c1").not_eq(lit(1)).and(col("c1").not_eq(lit(2)))
4379 );
4380
4381 let subquery = Arc::new(test_table_scan_with_name("test").unwrap());
4382 assert_eq!(
4383 simplify(in_list(
4384 col("c1"),
4385 vec![scalar_subquery(Arc::clone(&subquery))],
4386 false
4387 )),
4388 in_subquery(col("c1"), Arc::clone(&subquery))
4389 );
4390 assert_eq!(
4391 simplify(in_list(
4392 col("c1"),
4393 vec![scalar_subquery(Arc::clone(&subquery))],
4394 true
4395 )),
4396 not_in_subquery(col("c1"), subquery)
4397 );
4398
4399 let subquery1 =
4400 scalar_subquery(Arc::new(test_table_scan_with_name("test1").unwrap()));
4401 let subquery2 =
4402 scalar_subquery(Arc::new(test_table_scan_with_name("test2").unwrap()));
4403
4404 assert_eq!(
4406 simplify(in_list(
4407 col("c1"),
4408 vec![subquery1.clone(), subquery2.clone()],
4409 true
4410 )),
4411 col("c1")
4412 .not_eq(subquery1.clone())
4413 .and(col("c1").not_eq(subquery2.clone()))
4414 );
4415
4416 assert_eq!(
4418 simplify(in_list(
4419 col("c1"),
4420 vec![subquery1.clone(), subquery2.clone()],
4421 false
4422 )),
4423 col("c1").eq(subquery1).or(col("c1").eq(subquery2))
4424 );
4425
4426 let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false).and(
4428 in_list(col("c1"), vec![lit(5), lit(6), lit(7), lit(8)], false),
4429 );
4430 assert_eq!(simplify(expr), lit(false));
4431
4432 let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false).and(
4434 in_list(col("c1"), vec![lit(4), lit(5), lit(6), lit(7)], false),
4435 );
4436 assert_eq!(simplify(expr), col("c1").eq(lit(4)));
4437
4438 let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).or(
4440 in_list(col("c1"), vec![lit(5), lit(6), lit(7), lit(8)], true),
4441 );
4442 assert_eq!(simplify(expr), lit(true));
4443
4444 let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).or(
4446 in_list(col("c1"), vec![lit(4), lit(5), lit(6), lit(7)], true),
4447 );
4448 assert_eq!(simplify(expr), col("c1").not_eq(lit(4)));
4449
4450 let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).and(
4452 in_list(col("c1"), vec![lit(4), lit(5), lit(6), lit(7)], true),
4453 );
4454 assert_eq!(
4455 simplify(expr),
4456 in_list(
4457 col("c1"),
4458 vec![lit(1), lit(2), lit(3), lit(4), lit(5), lit(6), lit(7)],
4459 true
4460 )
4461 );
4462
4463 let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false).or(
4465 in_list(col("c1"), vec![lit(2), lit(3), lit(4), lit(5)], false),
4466 );
4467 assert_eq!(
4468 simplify(expr),
4469 in_list(
4470 col("c1"),
4471 vec![lit(1), lit(2), lit(3), lit(4), lit(5)],
4472 false
4473 )
4474 );
4475
4476 let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3)], false).and(in_list(
4478 col("c1"),
4479 vec![lit(1), lit(2), lit(3), lit(4), lit(5)],
4480 true,
4481 ));
4482 assert_eq!(simplify(expr), lit(false));
4483
4484 let expr =
4486 in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).and(in_list(
4487 col("c1"),
4488 vec![lit(1), lit(2), lit(3), lit(4), lit(5)],
4489 false,
4490 ));
4491 assert_eq!(simplify(expr), col("c1").eq(lit(5)));
4492
4493 let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false).and(
4495 in_list(col("c1"), vec![lit(5), lit(6), lit(7), lit(8)], true),
4496 );
4497 assert_eq!(
4498 simplify(expr),
4499 in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false)
4500 );
4501
4502 let expr = in_list(
4505 col("c1"),
4506 vec![lit(1), lit(2), lit(3), lit(4), lit(5), lit(6)],
4507 false,
4508 )
4509 .and(in_list(
4510 col("c1"),
4511 vec![lit(1), lit(3), lit(5), lit(6)],
4512 false,
4513 ))
4514 .and(in_list(col("c1"), vec![lit(3), lit(6)], false));
4515 assert_eq!(
4516 simplify(expr),
4517 col("c1").eq(lit(3)).or(col("c1").eq(lit(6)))
4518 );
4519
4520 let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).and(
4522 in_list(col("c1"), vec![lit(5), lit(6), lit(7), lit(8)], false)
4523 .and(in_list(
4524 col("c1"),
4525 vec![lit(3), lit(4), lit(5), lit(6)],
4526 true,
4527 ))
4528 .and(in_list(col("c1"), vec![lit(8), lit(9), lit(10)], false)),
4529 );
4530 assert_eq!(simplify(expr), col("c1").eq(lit(8)));
4531
4532 let expr =
4535 in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).or(col("c1")
4536 .not_eq(lit(5))
4537 .or(in_list(
4538 col("c1"),
4539 vec![lit(6), lit(7), lit(8), lit(9)],
4540 true,
4541 )));
4542 assert_eq!(simplify(expr.clone()), expr);
4546 }
4547
4548 #[test]
4549 fn simplify_null_in_empty_inlist() {
4550 let expr = in_list(lit_bool_null(), vec![], false);
4552 assert_eq!(simplify(expr), lit(false));
4553
4554 let expr = in_list(lit_bool_null(), vec![], true);
4556 assert_eq!(simplify(expr), lit(true));
4557
4558 let null_null = || Expr::Literal(ScalarValue::Null, None);
4560 let expr = in_list(null_null(), vec![], false);
4561 assert_eq!(simplify(expr), lit(false));
4562
4563 let expr = in_list(null_null(), vec![], true);
4565 assert_eq!(simplify(expr), lit(true));
4566 }
4567
4568 #[test]
4569 fn just_simplifier_simplify_null_in_empty_inlist() {
4570 let simplify = |expr: Expr| -> Expr {
4571 let schema = expr_test_schema();
4572 let info = SimplifyContext::builder().with_schema(schema).build();
4573 let simplifier = &mut Simplifier::new(&info);
4574 expr.rewrite(simplifier)
4575 .expect("Failed to simplify expression")
4576 .data
4577 };
4578
4579 let expr = in_list(lit_bool_null(), vec![], false);
4581 assert_eq!(simplify(expr), lit(false));
4582
4583 let expr = in_list(lit_bool_null(), vec![], true);
4585 assert_eq!(simplify(expr), lit(true));
4586
4587 let null_null = || Expr::Literal(ScalarValue::Null, None);
4589 let expr = in_list(null_null(), vec![], false);
4590 assert_eq!(simplify(expr), lit(false));
4591
4592 let expr = in_list(null_null(), vec![], true);
4594 assert_eq!(simplify(expr), lit(true));
4595 }
4596
4597 #[test]
4598 fn simplify_large_or() {
4599 let expr = (0..5)
4600 .map(|i| col("c1").eq(lit(i)))
4601 .fold(lit(false), |acc, e| acc.or(e));
4602 assert_eq!(
4603 simplify(expr),
4604 in_list(col("c1"), (0..5).map(lit).collect(), false),
4605 );
4606 }
4607
4608 #[test]
4609 fn simplify_expr_bool_and() {
4610 assert_eq!(simplify(col("c2").and(lit(true))), col("c2"),);
4612 assert_eq!(simplify(col("c2").and(lit(false))), lit(false),);
4614
4615 assert_eq!(simplify(lit(true).and(lit_bool_null())), lit_bool_null(),);
4617
4618 assert_eq!(simplify(lit_bool_null().and(lit(true))), lit_bool_null(),);
4620
4621 assert_eq!(simplify(lit(false).and(lit_bool_null())), lit(false),);
4623
4624 assert_eq!(simplify(lit_bool_null().and(lit(false))), lit(false),);
4626
4627 let expr = col("c1").between(lit(0), lit(10));
4631 let expr = expr.and(lit_bool_null());
4632 let result = simplify(expr);
4633
4634 let expected_expr = and(
4635 and(col("c1").gt_eq(lit(0)), col("c1").lt_eq(lit(10))),
4636 lit_bool_null(),
4637 );
4638 assert_eq!(expected_expr, result);
4639 }
4640
4641 #[test]
4642 fn simplify_expr_between() {
4643 let expr = col("c2").between(lit(3), lit(4));
4645 assert_eq!(
4646 simplify(expr),
4647 and(col("c2").gt_eq(lit(3)), col("c2").lt_eq(lit(4)))
4648 );
4649
4650 let expr = col("c2").not_between(lit(3), lit(4));
4652 assert_eq!(
4653 simplify(expr),
4654 or(col("c2").lt(lit(3)), col("c2").gt(lit(4)))
4655 );
4656 }
4657
4658 #[test]
4659 fn test_like_and_ilike() {
4660 let null = lit(ScalarValue::Utf8(None));
4661
4662 let expr = col("c1").like(null.clone());
4664 assert_eq!(simplify(expr), lit_bool_null());
4665
4666 let expr = col("c1").not_like(null.clone());
4667 assert_eq!(simplify(expr), lit_bool_null());
4668
4669 let expr = col("c1").ilike(null.clone());
4670 assert_eq!(simplify(expr), lit_bool_null());
4671
4672 let expr = col("c1").not_ilike(null.clone());
4673 assert_eq!(simplify(expr), lit_bool_null());
4674
4675 let expr = col("c1").like(lit("%"));
4677 assert_eq!(simplify(expr), if_not_null(col("c1"), true));
4678
4679 let expr = col("c1").not_like(lit("%"));
4680 assert_eq!(simplify(expr), if_not_null(col("c1"), false));
4681
4682 let expr = col("c1").ilike(lit("%"));
4683 assert_eq!(simplify(expr), if_not_null(col("c1"), true));
4684
4685 let expr = col("c1").not_ilike(lit("%"));
4686 assert_eq!(simplify(expr), if_not_null(col("c1"), false));
4687
4688 let expr = col("c1").like(lit("%%"));
4690 assert_eq!(simplify(expr), if_not_null(col("c1"), true));
4691
4692 let expr = col("c1").not_like(lit("%%"));
4693 assert_eq!(simplify(expr), if_not_null(col("c1"), false));
4694
4695 let expr = col("c1").ilike(lit("%%"));
4696 assert_eq!(simplify(expr), if_not_null(col("c1"), true));
4697
4698 let expr = col("c1").not_ilike(lit("%%"));
4699 assert_eq!(simplify(expr), if_not_null(col("c1"), false));
4700
4701 let expr = col("c1_non_null").like(lit("%"));
4703 assert_eq!(simplify(expr), lit(true));
4704
4705 let expr = col("c1_non_null").not_like(lit("%"));
4706 assert_eq!(simplify(expr), lit(false));
4707
4708 let expr = col("c1_non_null").ilike(lit("%"));
4709 assert_eq!(simplify(expr), lit(true));
4710
4711 let expr = col("c1_non_null").not_ilike(lit("%"));
4712 assert_eq!(simplify(expr), lit(false));
4713
4714 let expr = col("c1_non_null").like(lit("%%"));
4716 assert_eq!(simplify(expr), lit(true));
4717
4718 let expr = col("c1_non_null").not_like(lit("%%"));
4719 assert_eq!(simplify(expr), lit(false));
4720
4721 let expr = col("c1_non_null").ilike(lit("%%"));
4722 assert_eq!(simplify(expr), lit(true));
4723
4724 let expr = col("c1_non_null").not_ilike(lit("%%"));
4725 assert_eq!(simplify(expr), lit(false));
4726
4727 let expr = null.clone().like(lit("%"));
4729 assert_eq!(simplify(expr), lit_bool_null());
4730
4731 let expr = null.clone().not_like(lit("%"));
4732 assert_eq!(simplify(expr), lit_bool_null());
4733
4734 let expr = null.clone().ilike(lit("%"));
4735 assert_eq!(simplify(expr), lit_bool_null());
4736
4737 let expr = null.clone().not_ilike(lit("%"));
4738 assert_eq!(simplify(expr), lit_bool_null());
4739
4740 let expr = null.clone().like(lit("%%"));
4742 assert_eq!(simplify(expr), lit_bool_null());
4743
4744 let expr = null.clone().not_like(lit("%%"));
4745 assert_eq!(simplify(expr), lit_bool_null());
4746
4747 let expr = null.clone().ilike(lit("%%"));
4748 assert_eq!(simplify(expr), lit_bool_null());
4749
4750 let expr = null.clone().not_ilike(lit("%%"));
4751 assert_eq!(simplify(expr), lit_bool_null());
4752
4753 let expr = null.clone().like(lit("a%"));
4755 assert_eq!(simplify(expr), lit_bool_null());
4756
4757 let expr = null.clone().not_like(lit("a%"));
4758 assert_eq!(simplify(expr), lit_bool_null());
4759
4760 let expr = null.clone().ilike(lit("a%"));
4761 assert_eq!(simplify(expr), lit_bool_null());
4762
4763 let expr = null.clone().not_ilike(lit("a%"));
4764 assert_eq!(simplify(expr), lit_bool_null());
4765
4766 let expr = col("c1").like(lit("a"));
4768 assert_eq!(simplify(expr), col("c1").eq(lit("a")));
4769 let expr = col("c1").not_like(lit("a"));
4770 assert_eq!(simplify(expr), col("c1").not_eq(lit("a")));
4771 let expr = col("c1").like(lit("a_"));
4772 assert_eq!(simplify(expr), col("c1").like(lit("a_")));
4773 let expr = col("c1").not_like(lit("a_"));
4774 assert_eq!(simplify(expr), col("c1").not_like(lit("a_")));
4775
4776 let expr = col("c1").ilike(lit("a"));
4777 assert_eq!(simplify(expr), col("c1").ilike(lit("a")));
4778 let expr = col("c1").not_ilike(lit("a"));
4779 assert_eq!(simplify(expr), col("c1").not_ilike(lit("a")));
4780 }
4781
4782 #[test]
4783 fn test_simplify_with_guarantee() {
4784 let expr_x = col("c3").gt(lit(3_i64));
4786 let expr_y = (col("c4") + lit(2_u32)).lt(lit(10_u32));
4787 let expr_z = col("c1").in_list(vec![lit("a"), lit("b")], true);
4788 let expr = expr_x.clone().and(expr_y.or(expr_z));
4789
4790 let guarantees = vec![
4792 (col("c3"), NullableInterval::from(ScalarValue::Int64(None))),
4793 (col("c4"), NullableInterval::from(ScalarValue::UInt32(None))),
4794 (col("c1"), NullableInterval::from(ScalarValue::Utf8(None))),
4795 ];
4796
4797 let output = simplify_with_guarantee(expr.clone(), guarantees);
4798 assert_eq!(output, lit_bool_null());
4799
4800 let guarantees = vec![
4802 (
4803 col("c3"),
4804 NullableInterval::NotNull {
4805 values: Interval::make(Some(0_i64), Some(2_i64)).unwrap(),
4806 },
4807 ),
4808 (
4809 col("c4"),
4810 NullableInterval::from(ScalarValue::UInt32(Some(9))),
4811 ),
4812 (col("c1"), NullableInterval::from(ScalarValue::from("a"))),
4813 ];
4814 let output = simplify_with_guarantee(expr.clone(), guarantees);
4815 assert_eq!(output, lit(false));
4816
4817 let guarantees = vec![
4819 (
4820 col("c3"),
4821 NullableInterval::MaybeNull {
4822 values: Interval::make(Some(0_i64), Some(2_i64)).unwrap(),
4823 },
4824 ),
4825 (
4826 col("c4"),
4827 NullableInterval::MaybeNull {
4828 values: Interval::make(Some(9_u32), Some(9_u32)).unwrap(),
4829 },
4830 ),
4831 (
4832 col("c1"),
4833 NullableInterval::NotNull {
4834 values: Interval::try_new(
4835 ScalarValue::from("d"),
4836 ScalarValue::from("f"),
4837 )
4838 .unwrap(),
4839 },
4840 ),
4841 ];
4842 let output = simplify_with_guarantee(expr.clone(), guarantees);
4843 assert_eq!(&output, &expr_x);
4844
4845 let guarantees = vec![
4847 (
4848 col("c3"),
4849 NullableInterval::from(ScalarValue::Int64(Some(9))),
4850 ),
4851 (
4852 col("c4"),
4853 NullableInterval::from(ScalarValue::UInt32(Some(3))),
4854 ),
4855 ];
4856 let output = simplify_with_guarantee(expr.clone(), guarantees);
4857 assert_eq!(output, lit(true));
4858
4859 let guarantees = vec![(
4861 col("c4"),
4862 NullableInterval::from(ScalarValue::UInt32(Some(3))),
4863 )];
4864 let output = simplify_with_guarantee(expr, guarantees);
4865 assert_eq!(&output, &expr_x);
4866 }
4867
4868 #[test]
4869 fn test_expression_partial_simplify_1() {
4870 let expr = (lit(1) + lit(2)) + (lit(4) / lit(0));
4872 let expected = (lit(3)) + (lit(4) / lit(0));
4873
4874 assert_eq!(simplify(expr), expected);
4875 }
4876
4877 #[test]
4878 fn test_expression_partial_simplify_2() {
4879 let expr = (lit(1).gt(lit(2))).and(lit(4) / lit(0));
4881 let expected = lit(false);
4882
4883 assert_eq!(simplify(expr), expected);
4884 }
4885
4886 #[test]
4887 fn test_simplify_cycles() {
4888 let expr = lit(true);
4890 let expected = lit(true);
4891 let (expr, num_iter) = simplify_with_cycle_count(expr);
4892 assert_eq!(expr, expected);
4893 assert_eq!(num_iter, 1);
4894
4895 let expr = lit(true).not_eq(lit_bool_null()).or(lit(5).gt(lit(10)));
4897 let expected = lit_bool_null();
4898 let (expr, num_iter) = simplify_with_cycle_count(expr);
4899 assert_eq!(expr, expected);
4900 assert_eq!(num_iter, 2);
4901
4902 let expr = (((col("c4") - lit(10)) + lit(10)) * lit(100)) / lit(100);
4905 let expected = expr.clone();
4906 let (expr, num_iter) = simplify_with_cycle_count(expr);
4907 assert_eq!(expr, expected);
4908 assert_eq!(num_iter, 1);
4909
4910 let expr = col("c4")
4912 .lt(lit(1))
4913 .or(col("c3").lt(lit(2)))
4914 .and(col("c3_non_null").lt(lit(3)))
4915 .and(lit(false));
4916 let expected = lit(false);
4917 let (expr, num_iter) = simplify_with_cycle_count(expr);
4918 assert_eq!(expr, expected);
4919 assert_eq!(num_iter, 2);
4920 }
4921
4922 fn boolean_test_schema() -> DFSchemaRef {
4923 static BOOLEAN_TEST_SCHEMA: LazyLock<DFSchemaRef> = LazyLock::new(|| {
4924 Schema::new(vec![
4925 Field::new("A", DataType::Boolean, false),
4926 Field::new("B", DataType::Boolean, false),
4927 Field::new("C", DataType::Boolean, false),
4928 Field::new("D", DataType::Boolean, false),
4929 ])
4930 .to_dfschema_ref()
4931 .unwrap()
4932 });
4933 Arc::clone(&BOOLEAN_TEST_SCHEMA)
4934 }
4935
4936 #[test]
4937 fn simplify_common_factor_conjunction_in_disjunction() {
4938 let schema = boolean_test_schema();
4939 let simplifier =
4940 ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build());
4941
4942 let a = || col("A");
4943 let b = || col("B");
4944 let c = || col("C");
4945 let d = || col("D");
4946
4947 let expr = a().and(b()).or(a().and(c()));
4949 let expected = a().and(b().or(c()));
4950
4951 assert_eq!(expected, simplifier.simplify(expr).unwrap());
4952
4953 let expr = a().and(b()).or(a().and(c())).or(a().and(d()));
4955 let expected = a().and(b().or(c()).or(d()));
4956 assert_eq!(expected, simplifier.simplify(expr).unwrap());
4957
4958 let expr = a().or(b().and(c().and(a())));
4960 let expected = a();
4961 assert_eq!(expected, simplifier.simplify(expr).unwrap());
4962 }
4963
4964 #[test]
4965 fn test_simplify_udaf() {
4966 let udaf = AggregateUDF::new_from_impl(SimplifyMockUdaf::new_with_simplify());
4967 let aggregate_function_expr =
4968 Expr::AggregateFunction(expr::AggregateFunction::new_udf(
4969 udaf.into(),
4970 vec![],
4971 false,
4972 None,
4973 vec![],
4974 None,
4975 ));
4976
4977 let expected = col("result_column");
4978 assert_eq!(simplify(aggregate_function_expr), expected);
4979
4980 let udaf = AggregateUDF::new_from_impl(SimplifyMockUdaf::new_without_simplify());
4981 let aggregate_function_expr =
4982 Expr::AggregateFunction(expr::AggregateFunction::new_udf(
4983 udaf.into(),
4984 vec![],
4985 false,
4986 None,
4987 vec![],
4988 None,
4989 ));
4990
4991 let expected = aggregate_function_expr.clone();
4992 assert_eq!(simplify(aggregate_function_expr), expected);
4993 }
4994
4995 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
4998 struct SimplifyMockUdaf {
4999 simplify: bool,
5000 }
5001
5002 impl SimplifyMockUdaf {
5003 fn new_with_simplify() -> Self {
5005 Self { simplify: true }
5006 }
5007 fn new_without_simplify() -> Self {
5009 Self { simplify: false }
5010 }
5011 }
5012
5013 impl AggregateUDFImpl for SimplifyMockUdaf {
5014 fn name(&self) -> &str {
5015 "mock_simplify"
5016 }
5017
5018 fn signature(&self) -> &Signature {
5019 unimplemented!()
5020 }
5021
5022 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
5023 unimplemented!("not needed for tests")
5024 }
5025
5026 fn accumulator(
5027 &self,
5028 _acc_args: AccumulatorArgs,
5029 ) -> Result<Box<dyn Accumulator>> {
5030 unimplemented!("not needed for tests")
5031 }
5032
5033 fn groups_accumulator_supported(&self, _args: AccumulatorArgs) -> bool {
5034 unimplemented!("not needed for testing")
5035 }
5036
5037 fn create_groups_accumulator(
5038 &self,
5039 _args: AccumulatorArgs,
5040 ) -> Result<Box<dyn GroupsAccumulator>> {
5041 unimplemented!("not needed for testing")
5042 }
5043
5044 fn simplify(&self) -> Option<AggregateFunctionSimplification> {
5045 if self.simplify {
5046 Some(Box::new(|_, _| Ok(col("result_column"))))
5047 } else {
5048 None
5049 }
5050 }
5051 }
5052
5053 #[test]
5054 fn test_simplify_udwf() {
5055 let udwf = WindowFunctionDefinition::WindowUDF(
5056 WindowUDF::new_from_impl(SimplifyMockUdwf::new_with_simplify()).into(),
5057 );
5058 let window_function_expr = Expr::from(WindowFunction::new(udwf, vec![]));
5059
5060 let expected = col("result_column");
5061 assert_eq!(simplify(window_function_expr), expected);
5062
5063 let udwf = WindowFunctionDefinition::WindowUDF(
5064 WindowUDF::new_from_impl(SimplifyMockUdwf::new_without_simplify()).into(),
5065 );
5066 let window_function_expr = Expr::from(WindowFunction::new(udwf, vec![]));
5067
5068 let expected = window_function_expr.clone();
5069 assert_eq!(simplify(window_function_expr), expected);
5070 }
5071
5072 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
5075 struct SimplifyMockUdwf {
5076 simplify: bool,
5077 }
5078
5079 impl SimplifyMockUdwf {
5080 fn new_with_simplify() -> Self {
5082 Self { simplify: true }
5083 }
5084 fn new_without_simplify() -> Self {
5086 Self { simplify: false }
5087 }
5088 }
5089
5090 impl WindowUDFImpl for SimplifyMockUdwf {
5091 fn name(&self) -> &str {
5092 "mock_simplify"
5093 }
5094
5095 fn signature(&self) -> &Signature {
5096 unimplemented!()
5097 }
5098
5099 fn simplify(&self) -> Option<WindowFunctionSimplification> {
5100 if self.simplify {
5101 Some(Box::new(|_, _| Ok(col("result_column"))))
5102 } else {
5103 None
5104 }
5105 }
5106
5107 fn partition_evaluator(
5108 &self,
5109 _partition_evaluator_args: PartitionEvaluatorArgs,
5110 ) -> Result<Box<dyn PartitionEvaluator>> {
5111 unimplemented!("not needed for tests")
5112 }
5113
5114 fn field(&self, _field_args: WindowUDFFieldArgs) -> Result<FieldRef> {
5115 unimplemented!("not needed for tests")
5116 }
5117
5118 fn limit_effect(&self, _args: &[Arc<dyn PhysicalExpr>]) -> LimitEffect {
5119 LimitEffect::Unknown
5120 }
5121 }
5122 #[derive(Debug, PartialEq, Eq, Hash)]
5123 struct VolatileUdf {
5124 signature: Signature,
5125 }
5126
5127 impl VolatileUdf {
5128 pub fn new() -> Self {
5129 Self {
5130 signature: Signature::exact(vec![], Volatility::Volatile),
5131 }
5132 }
5133 }
5134 impl ScalarUDFImpl for VolatileUdf {
5135 fn name(&self) -> &str {
5136 "VolatileUdf"
5137 }
5138
5139 fn signature(&self) -> &Signature {
5140 &self.signature
5141 }
5142
5143 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
5144 Ok(DataType::Int16)
5145 }
5146
5147 fn invoke_with_args(&self, _args: ScalarFunctionArgs) -> Result<ColumnarValue> {
5148 panic!("dummy - not implemented")
5149 }
5150 }
5151
5152 #[test]
5153 fn test_optimize_volatile_conditions() {
5154 let fun = Arc::new(ScalarUDF::new_from_impl(VolatileUdf::new()));
5155 let rand = Expr::ScalarFunction(ScalarFunction::new_udf(fun, vec![]));
5156 {
5157 let expr = rand
5158 .clone()
5159 .eq(lit(0))
5160 .or(col("column1").eq(lit(2)).and(rand.clone().eq(lit(0))));
5161
5162 assert_eq!(simplify(expr.clone()), expr);
5163 }
5164
5165 {
5166 let expr = col("column1")
5167 .eq(lit(2))
5168 .or(col("column1").eq(lit(2)).and(rand.clone().eq(lit(0))));
5169
5170 assert_eq!(simplify(expr), col("column1").eq(lit(2)));
5171 }
5172
5173 {
5174 let expr = (col("column1").eq(lit(2)).and(rand.clone().eq(lit(0)))).or(col(
5175 "column1",
5176 )
5177 .eq(lit(2))
5178 .and(rand.clone().eq(lit(0))));
5179
5180 assert_eq!(
5181 simplify(expr),
5182 col("column1")
5183 .eq(lit(2))
5184 .and((rand.clone().eq(lit(0))).or(rand.clone().eq(lit(0))))
5185 );
5186 }
5187 }
5188
5189 #[test]
5190 fn simplify_fixed_size_binary_eq_lit() {
5191 let bytes = [1u8, 2, 3].as_slice();
5192
5193 let expr = col("c5").eq(lit(bytes));
5195
5196 let coerced = coerce(expr.clone());
5198 let schema = expr_test_schema();
5199 assert_eq!(
5200 coerced,
5201 col("c5")
5202 .cast_to(&DataType::Binary, schema.as_ref())
5203 .unwrap()
5204 .eq(lit(bytes))
5205 );
5206
5207 assert_eq!(
5209 simplify(coerced),
5210 col("c5").eq(Expr::Literal(
5211 ScalarValue::FixedSizeBinary(3, Some(bytes.to_vec()),),
5212 None
5213 ))
5214 );
5215 }
5216
5217 #[test]
5218 fn simplify_cast_literal() {
5219 let expr = Expr::Cast(Cast::new(Box::new(lit(123i32)), DataType::Int64));
5223 let expected = lit(123i64);
5224 assert_eq!(simplify(expr), expected);
5225
5226 let expr = Expr::Cast(Cast::new(
5229 Box::new(lit(1761630189642i64)),
5230 DataType::Timestamp(
5231 arrow::datatypes::TimeUnit::Nanosecond,
5232 Some("+00:00".into()),
5233 ),
5234 ));
5235 let result = simplify(expr);
5237 match result {
5238 Expr::Literal(ScalarValue::TimestampNanosecond(Some(val), tz), _) => {
5239 assert_eq!(val, 1761630189642i64);
5240 assert_eq!(tz.as_deref(), Some("+00:00"));
5241 }
5242 other => panic!("Expected TimestampNanosecond literal, got: {other:?}"),
5243 }
5244
5245 let expr = Expr::Cast(Cast::new(
5249 Box::new(lit("1761630189642")),
5250 DataType::Timestamp(
5251 arrow::datatypes::TimeUnit::Nanosecond,
5252 Some("+00:00".into()),
5253 ),
5254 ));
5255
5256 let schema = test_schema();
5258 let simplifier =
5259 ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build());
5260 let result = simplifier.simplify(expr);
5261 assert!(result.is_err(), "Expected error for invalid cast");
5262 let err_msg = result.unwrap_err().to_string();
5263 assert_contains!(err_msg, "Error parsing timestamp");
5264 }
5265
5266 fn if_not_null(expr: Expr, then: bool) -> Expr {
5267 Expr::Case(Case {
5268 expr: Some(expr.is_not_null().into()),
5269 when_then_expr: vec![(lit(true).into(), lit(then).into())],
5270 else_expr: None,
5271 })
5272 }
5273
5274 fn make_struct_cast_expr(source_fields: Fields, target_fields: Fields) -> Expr {
5280 let arrays: Vec<Arc<dyn Array>> = vec![
5282 Arc::new(Int32Array::from(vec![Some(1)])),
5283 Arc::new(Int32Array::from(vec![Some(2)])),
5284 ];
5285 let struct_array = StructArray::try_new(source_fields, arrays, None).unwrap();
5286
5287 Expr::Cast(Cast::new(
5288 Box::new(Expr::Literal(
5289 ScalarValue::Struct(Arc::new(struct_array)),
5290 None,
5291 )),
5292 DataType::Struct(target_fields),
5293 ))
5294 }
5295
5296 #[test]
5297 fn test_struct_cast_different_field_counts_not_foldable() {
5298 let source_fields = Fields::from(vec![
5302 Arc::new(Field::new("a", DataType::Int32, true)),
5303 Arc::new(Field::new("b", DataType::Int32, true)),
5304 ]);
5305
5306 let target_fields = Fields::from(vec![
5307 Arc::new(Field::new("x", DataType::Int32, true)),
5308 Arc::new(Field::new("y", DataType::Int32, true)),
5309 Arc::new(Field::new("z", DataType::Int32, true)),
5310 ]);
5311
5312 let expr = make_struct_cast_expr(source_fields, target_fields);
5313
5314 let simplifier = ExprSimplifier::new(
5315 SimplifyContext::builder()
5316 .with_schema(test_schema())
5317 .build(),
5318 );
5319
5320 let result = simplifier.simplify(expr.clone()).unwrap();
5322 assert_eq!(
5324 result, expr,
5325 "Struct cast with different field counts should remain unchanged (no const-folding)"
5326 );
5327 }
5328
5329 #[test]
5330 fn test_struct_cast_same_field_count_foldable() {
5331 let source_fields = Fields::from(vec![
5334 Arc::new(Field::new("a", DataType::Int32, true)),
5335 Arc::new(Field::new("b", DataType::Int32, true)),
5336 ]);
5337
5338 let target_fields = Fields::from(vec![
5339 Arc::new(Field::new("a", DataType::Int32, true)),
5340 Arc::new(Field::new("b", DataType::Int32, true)),
5341 ]);
5342
5343 let expr = make_struct_cast_expr(source_fields, target_fields);
5344
5345 let simplifier = ExprSimplifier::new(
5346 SimplifyContext::builder()
5347 .with_schema(test_schema())
5348 .build(),
5349 );
5350
5351 let result = simplifier.simplify(expr.clone()).unwrap();
5353 assert!(matches!(result, Expr::Literal(_, _)));
5355 assert_ne!(
5357 result, expr,
5358 "Struct cast with same field count should be simplified (not identical to input)"
5359 );
5360 }
5361
5362 #[test]
5363 fn test_struct_cast_different_names_same_count() {
5364 let source_fields = Fields::from(vec![
5368 Arc::new(Field::new("a", DataType::Int32, true)),
5369 Arc::new(Field::new("b", DataType::Int32, true)),
5370 ]);
5371
5372 let target_fields = Fields::from(vec![
5373 Arc::new(Field::new("x", DataType::Int32, true)),
5374 Arc::new(Field::new("y", DataType::Int32, true)),
5375 ]);
5376
5377 let expr = make_struct_cast_expr(source_fields, target_fields);
5378
5379 let simplifier = ExprSimplifier::new(
5380 SimplifyContext::builder()
5381 .with_schema(test_schema())
5382 .build(),
5383 );
5384
5385 let result = simplifier.simplify(expr.clone()).unwrap();
5387 assert_eq!(
5388 result, expr,
5389 "Struct cast with different names but same field count should not be simplified"
5390 );
5391 }
5392
5393 #[test]
5394 fn test_struct_cast_empty_array_not_foldable() {
5395 let source_fields = Fields::from(vec![
5400 Arc::new(Field::new("a", DataType::Int32, true)),
5401 Arc::new(Field::new("b", DataType::Int32, true)),
5402 ]);
5403
5404 let target_fields = Fields::from(vec![
5405 Arc::new(Field::new("a", DataType::Int32, true)),
5406 Arc::new(Field::new("b", DataType::Int32, true)),
5407 ]);
5408
5409 let arrays: Vec<Arc<dyn Array>> = vec![
5411 Arc::new(Int32Array::new(vec![].into(), None)),
5412 Arc::new(Int32Array::new(vec![].into(), None)),
5413 ];
5414 let struct_array = StructArray::try_new(source_fields, arrays, None).unwrap();
5415
5416 let expr = Expr::Cast(Cast::new(
5417 Box::new(Expr::Literal(
5418 ScalarValue::Struct(Arc::new(struct_array)),
5419 None,
5420 )),
5421 DataType::Struct(target_fields),
5422 ));
5423
5424 let simplifier = ExprSimplifier::new(
5425 SimplifyContext::builder()
5426 .with_schema(test_schema())
5427 .build(),
5428 );
5429
5430 let result = simplifier.simplify(expr.clone()).unwrap();
5432 assert_eq!(
5433 result, expr,
5434 "Struct cast with empty (0-row) array should remain unchanged"
5435 );
5436 }
5437}