## Coverage Report

#### Created: 2024-10-13 08:39

    /Users/andrewlamb/Software/datafusion/datafusion/expr/src/simplify.rs

    Line
    Count
    Source (jump to first uncovered line)
    1
    // Licensed to the Apache Software Foundation (ASF) under one
    2
    // or more contributor license agreements.  See the NOTICE file
    3
    // distributed with this work for additional information
    4
    // regarding copyright ownership.  The ASF licenses this file
    5
    // to you under the Apache License, Version 2.0 (the
    6
    // "License"); you may not use this file except in compliance
    7
    // with the License.  You may obtain a copy of the License at
    8
    //
    9
    //   http://www.apache.org/licenses/LICENSE-2.0
    10
    //
    11
    // Unless required by applicable law or agreed to in writing,
    12
    // software distributed under the License is distributed on an
    13
    // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14
    // KIND, either express or implied.  See the License for the
    15
    // specific language governing permissions and limitations
    16
    // under the License.
    17
    18
    //! Structs and traits to provide the information needed for expression simplification.
    19
    20
    use arrow::datatypes::DataType;
    21
    use datafusion_common::{DFSchemaRef, DataFusionError, Result};
    22
    23
    use crate::{execution_props::ExecutionProps, Expr, ExprSchemable};
    24
    25
    /// Provides the information necessary to apply algebraic simplification to an
    26
    /// [Expr]. See [SimplifyContext] for one concrete implementation.
    27
    ///
    28
    /// This trait exists so that other systems can plug schema
    29
    /// information in without having to create `DFSchema` objects. If you
    30
    /// have a [`DFSchemaRef`] you can use [`SimplifyContext`]
    31
    pub trait SimplifyInfo {
    32
        /// returns true if this Expr has boolean type
    33
        fn is_boolean_type(&self, expr: &Expr) -> Result<bool>;
    34
    35
        /// returns true of this expr is nullable (could possibly be NULL)
    36
        fn nullable(&self, expr: &Expr) -> Result<bool>;
    37
    38
        /// Returns details needed for partial expression evaluation
    39
        fn execution_props(&self) -> &ExecutionProps;
    40
    41
        /// Returns data type of this expr needed for determining optimized int type of a value
    42
        fn get_data_type(&self, expr: &Expr) -> Result<DataType>;
    43
    }
    44
    45
    /// Provides simplification information based on DFSchema and
    46
    /// [`ExecutionProps`]. This is the default implementation used by DataFusion
    47
    ///
    48
    /// # Example
    49
    /// See the `simplify_demo` in the [`expr_api` example]
    50
    ///
    51
    /// [`expr_api` example]: https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/expr_api.rs
    52
    #[derive(Debug, Clone)]
    53
    pub struct SimplifyContext<'a> {
    54
        schema: Option<DFSchemaRef>,
    55
        props: &'a ExecutionProps,
    56
    }
    57
    58
    impl<'a> SimplifyContext<'a> {
    59
        /// Create a new SimplifyContext
    60
        pub fn new(props: &'a ExecutionProps) -> Self {
    61
            Self {
    62
                schema: None,
    63
                props,
    64
            }
    65
        }
    66
    67
        /// Register a [`DFSchemaRef`] with this context
    68
        pub fn with_schema(mut self, schema: DFSchemaRef) -> Self {
    69
            self.schema = Some(schema);
    70
            self
    71
        }
    72
    }
    73
    74
    impl<'a> SimplifyInfo for SimplifyContext<'a> {
    75
        /// returns true if this Expr has boolean type
    76
        fn is_boolean_type(&self, expr: &Expr) -> Result<bool> {
    77
            if let Some(schema) = &self.schema {
    78
                if let Ok(DataType::Boolean) = expr.get_type(schema) {
    79
                    return Ok(true);
    80
                }
    81
            }
    82
    83
            Ok(false)
    84
        }
    85
    86
        /// Returns true if expr is nullable
    87
        fn nullable(&self, expr: &Expr) -> Result<bool> {
    88
    0
            let schema = self.schema.as_ref().ok_or_else(|| {
    89
    0
                DataFusionError::Internal(
    90
    0
                    "attempt to get nullability without schema".to_string(),
    91
    0
                )
    92
    0
            })?;
    93
            expr.nullable(schema.as_ref())
    94
        }
    95
    96
        /// Returns data type of this expr needed for determining optimized int type of a value
    97
        fn get_data_type(&self, expr: &Expr) -> Result<DataType> {
    98
    0
            let schema = self.schema.as_ref().ok_or_else(|| {
    99
    0
                DataFusionError::Internal(
    100
    0
                    "attempt to get data type without schema".to_string(),
    101
    0
                )
    102
    0
            })?;
    103
            expr.get_type(schema)
    104
        }
    105
    106
        fn execution_props(&self) -> &ExecutionProps {
    107
            self.props
    108
        }
    109
    }
    110
    111
    /// Was the expression simplified?
    112
    #[derive(Debug)]
    113
    pub enum ExprSimplifyResult {
    114
        /// The function call was simplified to an entirely new Expr
    115
        Simplified(Expr),
    116
        /// the function call could not be simplified, and the arguments
    117
        /// are return unmodified.
    118
        Original(Vec<Expr>),
    119
    }