datafusion_expr/
literal.rs

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