(
expr: Arc<dyn PhysicalExpr>,
exprs_with_interval: (Arc<dyn PhysicalExpr>, Arc<dyn PhysicalExpr>),
left_interval: Interval,
right_interval: Interval,
left_expe
| 781 | |
| 782 | #[expect(clippy::too_many_arguments)] |
| 783 | fn experiment( |
| 784 | expr: Arc<dyn PhysicalExpr>, |
| 785 | exprs_with_interval: (Arc<dyn PhysicalExpr>, Arc<dyn PhysicalExpr>), |
| 786 | left_interval: Interval, |
| 787 | right_interval: Interval, |
| 788 | left_expected: Interval, |
| 789 | right_expected: Interval, |
| 790 | result: PropagationResult, |
| 791 | schema: &Schema, |
| 792 | ) -> Result<()> { |
| 793 | let col_stats = [ |
| 794 | (Arc::clone(&exprs_with_interval.0), left_interval), |
| 795 | (Arc::clone(&exprs_with_interval.1), right_interval), |
| 796 | ]; |
| 797 | let expected = [ |
| 798 | (Arc::clone(&exprs_with_interval.0), left_expected), |
| 799 | (Arc::clone(&exprs_with_interval.1), right_expected), |
| 800 | ]; |
| 801 | let mut graph = ExprIntervalGraph::try_new(expr, schema)?; |
| 802 | let expr_indexes = graph.gather_node_indices( |
| 803 | &col_stats.iter().map(|(e, _)| Arc::clone(e)).collect_vec(), |
| 804 | ); |
| 805 | |
| 806 | let mut col_stat_nodes = col_stats |
| 807 | .iter() |
| 808 | .zip(expr_indexes.iter()) |
| 809 | .map(|((_, interval), (_, index))| (*index, interval.clone())) |
| 810 | .collect_vec(); |
| 811 | let expected_nodes = expected |
| 812 | .iter() |
| 813 | .zip(expr_indexes.iter()) |
| 814 | .map(|((_, interval), (_, index))| (*index, interval.clone())) |
| 815 | .collect_vec(); |
| 816 | |
| 817 | let exp_result = graph.update_ranges(&mut col_stat_nodes[..], Interval::TRUE)?; |
| 818 | assert_eq!(exp_result, result); |
| 819 | col_stat_nodes.iter().zip(expected_nodes.iter()).for_each( |
| 820 | |((_, calculated_interval_node), (_, expected))| { |
| 821 | // NOTE: These randomized tests only check for conservative containment, |
| 822 | // not openness/closedness of endpoints. |
| 823 | |
| 824 | // Calculated bounds are relaxed by 1 to cover all strict and |
| 825 | // and non-strict comparison cases since we have only closed bounds. |
| 826 | let one = ScalarValue::new_one(&expected.data_type()).unwrap(); |
| 827 | assert!( |
| 828 | calculated_interval_node.lower() |
| 829 | <= &expected.lower().add(&one).unwrap(), |
| 830 | "{}", |
| 831 | format!( |
| 832 | "Calculated {} must be less than or equal {}", |
| 833 | calculated_interval_node.lower(), |
| 834 | expected.lower() |
| 835 | ) |
| 836 | ); |
| 837 | assert!( |
| 838 | calculated_interval_node.upper() |
| 839 | >= &expected.upper().sub(&one).unwrap(), |
| 840 | "{}", |
searching dependent graphs…