vortex_array/expr/analysis/
null_sensitive.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_utils::aliases::hash_map::HashMap;
5
6use super::labeling::label_tree;
7use crate::expr::Expression;
8
9pub type BooleanLabels<'a> = HashMap<&'a Expression, bool>;
10
11/// Label each expression in the tree with whether it is null-sensitive.
12///
13/// See [`crate::expr::VTable::is_null_sensitive`] for a definition of null sensitivity.
14/// This function operates on a tree of expressions, not just a single expression.
15pub fn label_null_sensitive(expr: &Expression) -> BooleanLabels<'_> {
16    label_tree(
17        expr,
18        |expr| expr.is_null_sensitive(),
19        |acc, &child| acc | child,
20    )
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26    use crate::expr::exprs::binary::eq;
27    use crate::expr::exprs::get_item::col;
28    use crate::expr::exprs::is_null::is_null;
29    use crate::expr::exprs::literal::lit;
30
31    #[test]
32    fn test_null_sensitive_with_is_null() {
33        let expr = is_null(col("col1"));
34        let labels = label_null_sensitive(&expr);
35
36        // The root expression should be null-sensitive
37        assert_eq!(labels.get(&expr), Some(&true));
38    }
39
40    #[test]
41    fn test_null_sensitive_without_is_null() {
42        let expr = eq(col("col1"), lit(5));
43        let labels = label_null_sensitive(&expr);
44
45        // Since the default is conservative (true), all expressions are sensitive
46        assert_eq!(labels.get(&expr), Some(&true));
47    }
48
49    #[test]
50    fn test_null_sensitive_nested() {
51        let left = eq(col("col1"), lit(5));
52        let right = is_null(col("col2"));
53        let expr = eq(left.clone(), right.clone());
54
55        let labels = label_null_sensitive(&expr);
56
57        // With conservative defaults, all are sensitive
58        assert_eq!(labels.get(&left), Some(&true));
59        assert_eq!(labels.get(&right), Some(&true));
60        assert_eq!(labels.get(&expr), Some(&true));
61    }
62}