## Coverage Report

#### Created: 2025-11-22 06:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

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

    Line
    Count
    Source
    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
    //! Literal module contains foundational types that are used to represent literals in DataFusion.
    19
    20
    use crate::Expr;
    21
    use datafusion_common::{metadata::FieldMetadata, ScalarValue};
    22
    23
    /// Create a literal expression
    24
    #[expect(clippy::needless_pass_by_value)]
    25
    0
    pub fn lit<T: Literal>(n: T) -> Expr {
    26
    0
        n.lit()
    27
    0
    }
    28
    29
    #[expect(clippy::needless_pass_by_value)]
    30
    0
    pub fn lit_with_metadata<T: Literal>(n: T, metadata: Option<FieldMetadata>) -> Expr {
    31
    0
        let Some(metadata) = metadata else {
    32
    0
            return n.lit();
    33
        };
    34
    35
    0
        let Expr::Literal(sv, prior_metadata) = n.lit() else {
    36
    0
            unreachable!();
    37
        };
    38
    0
        let new_metadata = match prior_metadata {
    39
    0
            Some(mut prior) => {
    40
    0
                prior.extend(metadata);
    41
    0
                prior
    42
            }
    43
    0
            None => metadata,
    44
        };
    45
    46
    0
        Expr::Literal(sv, Some(new_metadata))
    47
    0
    }
    48
    49
    /// Create a literal timestamp expression
    50
    #[expect(clippy::needless_pass_by_value)]
    51
    0
    pub fn lit_timestamp_nano<T: TimestampLiteral>(n: T) -> Expr {
    52
    0
        n.lit_timestamp_nano()
    53
    0
    }
    54
    55
    /// Trait for converting a type to a [`Literal`] literal expression.
    56
    pub trait Literal {
    57
        /// convert the value to a Literal expression
    58
        fn lit(&self) -> Expr;
    59
    }
    60
    61
    /// Trait for converting a type to a literal timestamp
    62
    pub trait TimestampLiteral {
    63
        fn lit_timestamp_nano(&self) -> Expr;
    64
    }
    65
    66
    impl Literal for &str {
    67
    48
        fn lit(&self) -> Expr {
    68
    48
            Expr::Literal(ScalarValue::from(*self), None)
    69
    48
        }
    70
    }
    71
    72
    impl Literal for String {
    73
    0
        fn lit(&self) -> Expr {
    74
    0
            Expr::Literal(ScalarValue::from(self.as_ref()), None)
    75
    0
        }
    76
    }
    77
    78
    impl Literal for &String {
    79
    0
        fn lit(&self) -> Expr {
    80
    0
            Expr::Literal(ScalarValue::from(self.as_ref()), None)
    81
    0
        }
    82
    }
    83
    84
    impl Literal for Vec<u8> {
    85
    0
        fn lit(&self) -> Expr {
    86
    0
            Expr::Literal(ScalarValue::Binary(Some((*self).to_owned())), None)
    87
    0
        }
    88
    }
    89
    90
    impl Literal for &[u8] {
    91
    12
        fn lit(&self) -> Expr {
    92
    12
            Expr::Literal(ScalarValue::Binary(Some((*self).to_owned())), None)
    93
    12
        }
    94
    }
    95
    96
    impl Literal for ScalarValue {
    97
    137
        fn lit(&self) -> Expr {
    98
    137
            Expr::Literal(self.clone(), None)
    99
    137
        }
    100
    }
    101
    102
    macro_rules! make_literal {
    103
        ($TYPE:ty, $SCALAR:ident, $DOC: expr) => {
    104
            #[doc = $DOC]
    105
            impl Literal for $TYPE {
    106
    355
                fn lit(&self) -> Expr {
    107
    355
                    Expr::Literal(ScalarValue::$SCALAR(Some(self.clone())), None)
    108
    355
                }
    109
            }
    110
        };
    111
    }
    112
    113
    macro_rules! make_nonzero_literal {
    114
        ($TYPE:ty, $SCALAR:ident, $DOC: expr) => {
    115
            #[doc = $DOC]
    116
            impl Literal for $TYPE {
    117
    0
                fn lit(&self) -> Expr {
    118
    0
                    Expr::Literal(ScalarValue::$SCALAR(Some(self.get())), None)
    119
    0
                }
    120
            }
    121
        };
    122
    }
    123
    124
    macro_rules! make_timestamp_literal {
    125
        ($TYPE:ty, $SCALAR:ident, $DOC: expr) => {
    126
            #[doc = $DOC]
    127
            impl TimestampLiteral for $TYPE {
    128
    0
                fn lit_timestamp_nano(&self) -> Expr {
    129
    0
                    Expr::Literal(
    130
    0
                        ScalarValue::TimestampNanosecond(Some((self.clone()).into()), None),
    131
    0
                        None,
    132
    0
                    )
    133
    0
                }
    134
            }
    135
        };
    136
    }
    137
    138
    make_literal!(bool, Boolean, "literal expression containing a bool");
    139
    make_literal!(f32, Float32, "literal expression containing an f32");
    140
    make_literal!(f64, Float64, "literal expression containing an f64");
    141
    make_literal!(i8, Int8, "literal expression containing an i8");
    142
    make_literal!(i16, Int16, "literal expression containing an i16");
    143
    make_literal!(i32, Int32, "literal expression containing an i32");
    144
    make_literal!(i64, Int64, "literal expression containing an i64");
    145
    make_literal!(u8, UInt8, "literal expression containing a u8");
    146
    make_literal!(u16, UInt16, "literal expression containing a u16");
    147
    make_literal!(u32, UInt32, "literal expression containing a u32");
    148
    make_literal!(u64, UInt64, "literal expression containing a u64");
    149
    150
    make_nonzero_literal!(
    151
        std::num::NonZeroI8,
    152
        Int8,
    153
        "literal expression containing an i8"
    154
    );
    155
    make_nonzero_literal!(
    156
        std::num::NonZeroI16,
    157
        Int16,
    158
        "literal expression containing an i16"
    159
    );
    160
    make_nonzero_literal!(
    161
        std::num::NonZeroI32,
    162
        Int32,
    163
        "literal expression containing an i32"
    164
    );
    165
    make_nonzero_literal!(
    166
        std::num::NonZeroI64,
    167
        Int64,
    168
        "literal expression containing an i64"
    169
    );
    170
    make_nonzero_literal!(
    171
        std::num::NonZeroU8,
    172
        UInt8,
    173
        "literal expression containing a u8"
    174
    );
    175
    make_nonzero_literal!(
    176
        std::num::NonZeroU16,
    177
        UInt16,
    178
        "literal expression containing a u16"
    179
    );
    180
    make_nonzero_literal!(
    181
        std::num::NonZeroU32,
    182
        UInt32,
    183
        "literal expression containing a u32"
    184
    );
    185
    make_nonzero_literal!(
    186
        std::num::NonZeroU64,
    187
        UInt64,
    188
        "literal expression containing a u64"
    189
    );
    190
    191
    make_timestamp_literal!(i8, Int8, "literal expression containing an i8");
    192
    make_timestamp_literal!(i16, Int16, "literal expression containing an i16");
    193
    make_timestamp_literal!(i32, Int32, "literal expression containing an i32");
    194
    make_timestamp_literal!(i64, Int64, "literal expression containing an i64");
    195
    make_timestamp_literal!(u8, UInt8, "literal expression containing a u8");
    196
    make_timestamp_literal!(u16, UInt16, "literal expression containing a u16");
    197
    make_timestamp_literal!(u32, UInt32, "literal expression containing a u32");
    198
    199
    #[cfg(test)]
    200
    mod test {
    201
        use std::num::NonZeroU32;
    202
    203
        use super::*;
    204
        use crate::expr_fn::col;
    205
    206
        #[test]
    207
        fn test_lit_nonzero() {
    208
            let expr = col("id").eq(lit(NonZeroU32::new(1).unwrap()));
    209
            let expected = col("id").eq(lit(ScalarValue::UInt32(Some(1))));
    210
            assert_eq!(expr, expected);
    211
        }
    212
    213
        #[test]
    214
        fn test_lit_timestamp_nano() {
    215
            let expr = col("time").eq(lit_timestamp_nano(10)); // 10 is an implicit i32
    216
            let expected =
    217
                col("time").eq(lit(ScalarValue::TimestampNanosecond(Some(10), None)));
    218
            assert_eq!(expr, expected);
    219
    220
            let i: i64 = 10;
    221
            let expr = col("time").eq(lit_timestamp_nano(i));
    222
            assert_eq!(expr, expected);
    223
    224
            let i: u32 = 10;
    225
            let expr = col("time").eq(lit_timestamp_nano(i));
    226
            assert_eq!(expr, expected);
    227
        }
    228
    }