datafusion_expr/
literal.rs1use crate::Expr;
21use datafusion_common::{ScalarValue, metadata::FieldMetadata};
22
23#[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#[expect(clippy::needless_pass_by_value)]
51pub fn lit_timestamp_nano<T: TimestampLiteral>(n: T) -> Expr {
52 n.lit_timestamp_nano()
53}
54
55pub trait Literal {
57 fn lit(&self) -> Expr;
59}
60
61pub 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)); 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}