Skip to main content

drizzle_core/expr/
primitives.rs

1//! [`Expr`] implementations for Rust values: integers, floats, `bool`, text,
2//! bytes, `Option`, references, and (with their features) UUID, decimal and
3//! date/time types.
4//!
5//! A Rust value used as an expression is sent as a bound parameter. Its SQL
6//! type is the type the dialect stores it as (for example `i32` is `INTEGER`
7//! on SQLite and `int4` on PostgreSQL), and it is never NULL, except
8//! `Option<T>`, which is nullable.
9
10use crate::bind::ValueTypeForDialect;
11use crate::dialect::DialectTypes;
12use crate::prelude::*;
13use crate::sql::SQL;
14use crate::traits::{SQLBytes, SQLParam};
15
16use super::{Expr, ExprSources, NonNull, Null, Nullability, Scalar};
17
18// =============================================================================
19// Integer Types
20// =============================================================================
21
22impl<'a, V> Expr<'a, V> for i8
23where
24    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
25    Self: ValueTypeForDialect<V::DialectMarker>,
26{
27    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
28    type Nullable = NonNull;
29    type Aggregate = Scalar;
30}
31
32impl<'a, V> Expr<'a, V> for i16
33where
34    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
35    Self: ValueTypeForDialect<V::DialectMarker>,
36{
37    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
38    type Nullable = NonNull;
39    type Aggregate = Scalar;
40}
41
42impl<'a, V> Expr<'a, V> for i32
43where
44    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
45    Self: ValueTypeForDialect<V::DialectMarker>,
46{
47    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
48    type Nullable = NonNull;
49    type Aggregate = Scalar;
50}
51
52impl<'a, V> Expr<'a, V> for i64
53where
54    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
55    Self: ValueTypeForDialect<V::DialectMarker>,
56{
57    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
58    type Nullable = NonNull;
59    type Aggregate = Scalar;
60}
61
62impl<'a, V> Expr<'a, V> for isize
63where
64    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
65    Self: ValueTypeForDialect<V::DialectMarker>,
66{
67    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
68    type Nullable = NonNull;
69    type Aggregate = Scalar;
70}
71
72// =============================================================================
73// Unsigned Integer Types
74// =============================================================================
75
76impl<'a, V> Expr<'a, V> for u8
77where
78    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
79    Self: ValueTypeForDialect<V::DialectMarker>,
80{
81    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
82    type Nullable = NonNull;
83    type Aggregate = Scalar;
84}
85
86impl<'a, V> Expr<'a, V> for u16
87where
88    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
89    Self: ValueTypeForDialect<V::DialectMarker>,
90{
91    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
92    type Nullable = NonNull;
93    type Aggregate = Scalar;
94}
95
96impl<'a, V> Expr<'a, V> for u32
97where
98    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
99    Self: ValueTypeForDialect<V::DialectMarker>,
100{
101    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
102    type Nullable = NonNull;
103    type Aggregate = Scalar;
104}
105
106impl<'a, V> Expr<'a, V> for u64
107where
108    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
109    Self: ValueTypeForDialect<V::DialectMarker>,
110{
111    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
112    type Nullable = NonNull;
113    type Aggregate = Scalar;
114}
115
116impl<'a, V> Expr<'a, V> for usize
117where
118    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
119    Self: ValueTypeForDialect<V::DialectMarker>,
120{
121    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
122    type Nullable = NonNull;
123    type Aggregate = Scalar;
124}
125
126// =============================================================================
127// Floating-Point Types
128// =============================================================================
129
130impl<'a, V> Expr<'a, V> for f32
131where
132    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
133    Self: ValueTypeForDialect<V::DialectMarker>,
134{
135    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
136    type Nullable = NonNull;
137    type Aggregate = Scalar;
138}
139
140impl<'a, V> Expr<'a, V> for f64
141where
142    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
143    Self: ValueTypeForDialect<V::DialectMarker>,
144{
145    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
146    type Nullable = NonNull;
147    type Aggregate = Scalar;
148}
149
150// =============================================================================
151// Boolean Type
152// =============================================================================
153
154impl<'a, V> Expr<'a, V> for bool
155where
156    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
157    Self: ValueTypeForDialect<V::DialectMarker>,
158{
159    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
160    type Nullable = NonNull;
161    type Aggregate = Scalar;
162}
163
164// =============================================================================
165// String Types
166// =============================================================================
167
168impl<'a, V> Expr<'a, V> for &'a str
169where
170    V: SQLParam + 'a + From<&'a str> + Into<Cow<'a, V>>,
171    Self: ValueTypeForDialect<V::DialectMarker>,
172{
173    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
174    type Nullable = NonNull;
175    type Aggregate = Scalar;
176}
177
178impl<'a, V> Expr<'a, V> for String
179where
180    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
181    Self: ValueTypeForDialect<V::DialectMarker>,
182{
183    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
184    type Nullable = NonNull;
185    type Aggregate = Scalar;
186}
187
188#[cfg(feature = "compact-str")]
189impl<'a, V> Expr<'a, V> for compact_str::CompactString
190where
191    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
192    Self: ValueTypeForDialect<V::DialectMarker>,
193{
194    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
195    type Nullable = NonNull;
196    type Aggregate = Scalar;
197}
198
199#[cfg(feature = "bytes")]
200impl<'a, V> Expr<'a, V> for bytes::Bytes
201where
202    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
203    Self: ValueTypeForDialect<V::DialectMarker>,
204{
205    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
206    type Nullable = NonNull;
207    type Aggregate = Scalar;
208}
209
210#[cfg(feature = "bytes")]
211impl<'a, V> Expr<'a, V> for bytes::BytesMut
212where
213    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
214    Self: ValueTypeForDialect<V::DialectMarker>,
215{
216    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
217    type Nullable = NonNull;
218    type Aggregate = Scalar;
219}
220
221#[cfg(feature = "arrayvec")]
222impl<'a, V, const N: usize> Expr<'a, V> for arrayvec::ArrayString<N>
223where
224    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
225    Self: ValueTypeForDialect<V::DialectMarker>,
226{
227    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
228    type Nullable = NonNull;
229    type Aggregate = Scalar;
230}
231
232#[cfg(feature = "arrayvec")]
233impl<'a, V, const N: usize> Expr<'a, V> for arrayvec::ArrayVec<u8, N>
234where
235    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
236    Self: ValueTypeForDialect<V::DialectMarker>,
237{
238    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
239    type Nullable = NonNull;
240    type Aggregate = Scalar;
241}
242
243#[cfg(feature = "smallvec-types")]
244impl<'a, V, const N: usize> Expr<'a, V> for smallvec::SmallVec<[u8; N]>
245where
246    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
247    Self: ValueTypeForDialect<V::DialectMarker>,
248{
249    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
250    type Nullable = NonNull;
251    type Aggregate = Scalar;
252}
253
254impl<'a, V, const N: usize> Expr<'a, V> for [char; N]
255where
256    V: SQLParam + 'a + From<Self> + From<char> + Into<Cow<'a, V>>,
257    Self: ValueTypeForDialect<V::DialectMarker>,
258{
259    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
260    type Nullable = NonNull;
261    type Aggregate = Scalar;
262
263    fn to_expr_sql(&self) -> SQL<'a, V> {
264        SQL::param(V::from(*self))
265    }
266
267    fn into_expr_sql(self) -> SQL<'a, V> {
268        SQL::param(V::from(self))
269    }
270}
271
272// =============================================================================
273// Binary Types
274// =============================================================================
275
276impl<'a, V> Expr<'a, V> for &'a [u8]
277where
278    V: SQLParam + 'a + From<&'a [u8]> + From<Vec<u8>> + From<u8> + Into<Cow<'a, V>>,
279{
280    type SQLType = <V::DialectMarker as DialectTypes>::Bytes;
281    type Nullable = NonNull;
282    type Aggregate = Scalar;
283
284    fn to_expr_sql(&self) -> SQL<'a, V> {
285        SQL::bytes(*self)
286    }
287
288    fn into_expr_sql(self) -> SQL<'a, V> {
289        SQL::bytes(self)
290    }
291}
292
293impl<'a, V, const N: usize> Expr<'a, V> for [u8; N]
294where
295    V: SQLParam + 'a + From<&'a [u8]> + From<Vec<u8>> + From<u8> + Into<Cow<'a, V>>,
296{
297    type SQLType = <V::DialectMarker as DialectTypes>::Bytes;
298    type Nullable = NonNull;
299    type Aggregate = Scalar;
300
301    fn to_expr_sql(&self) -> SQL<'a, V> {
302        SQL::bytes(self.to_vec())
303    }
304
305    fn into_expr_sql(self) -> SQL<'a, V> {
306        SQL::bytes(self.to_vec())
307    }
308}
309
310impl<'a, V> Expr<'a, V> for Vec<u8>
311where
312    V: SQLParam + 'a + From<&'a [u8]> + From<Vec<u8>> + From<u8> + Into<Cow<'a, V>>,
313{
314    type SQLType = <V::DialectMarker as DialectTypes>::Bytes;
315    type Nullable = NonNull;
316    type Aggregate = Scalar;
317
318    fn to_expr_sql(&self) -> SQL<'a, V> {
319        SQL::bytes(self.clone())
320    }
321
322    fn into_expr_sql(self) -> SQL<'a, V> {
323        SQL::bytes(self)
324    }
325}
326
327impl<'a, V> Expr<'a, V> for Cow<'a, [u8]>
328where
329    V: SQLParam + 'a + From<&'a [u8]> + From<Vec<u8>> + Into<Cow<'a, V>>,
330{
331    type SQLType = <V::DialectMarker as DialectTypes>::Bytes;
332    type Nullable = NonNull;
333    type Aggregate = Scalar;
334
335    fn to_expr_sql(&self) -> SQL<'a, V> {
336        match self {
337            Cow::Borrowed(value) => SQL::bytes(*value),
338            Cow::Owned(value) => SQL::bytes(value.clone()),
339        }
340    }
341
342    fn into_expr_sql(self) -> SQL<'a, V> {
343        SQL::bytes(self)
344    }
345}
346
347impl<'a, V> Expr<'a, V> for SQLBytes<'a>
348where
349    V: SQLParam + 'a + From<&'a [u8]> + From<Vec<u8>> + Into<Cow<'a, V>>,
350{
351    type SQLType = <V::DialectMarker as DialectTypes>::Bytes;
352    type Nullable = NonNull;
353    type Aggregate = Scalar;
354
355    fn to_expr_sql(&self) -> SQL<'a, V> {
356        match &self.0 {
357            Cow::Borrowed(value) => SQL::bytes(*value),
358            Cow::Owned(value) => SQL::bytes(value.clone()),
359        }
360    }
361
362    fn into_expr_sql(self) -> SQL<'a, V> {
363        SQL::bytes(self.0)
364    }
365}
366
367// =============================================================================
368// Option<T> - Makes Any Expression Nullable
369// =============================================================================
370
371impl<T: ExprSources> ExprSources for Option<T> {
372    type Sources = T::Sources;
373}
374
375impl<'a, V, T> Expr<'a, V> for Option<T>
376where
377    V: SQLParam + 'a,
378    T: Expr<'a, V>,
379    T::Nullable: Nullability,
380{
381    type SQLType = T::SQLType;
382    type Nullable = Null;
383    type Aggregate = T::Aggregate;
384
385    /// A missing optional condition contributes nothing to a condition list.
386    fn to_condition_sql(&self) -> Option<SQL<'a, V>> {
387        self.as_ref().map(<T as Expr<'a, V>>::to_expr_sql)
388    }
389
390    /// A missing optional condition contributes nothing to a condition list.
391    fn into_condition_sql(self) -> Option<SQL<'a, V>> {
392        self.map(<T as Expr<'a, V>>::into_expr_sql)
393    }
394}
395
396// =============================================================================
397// Reference Types - Delegate to Inner
398// =============================================================================
399
400impl<'a, V, T> Expr<'a, V> for &T
401where
402    V: SQLParam + 'a,
403    T: Expr<'a, V>,
404    T::Nullable: Nullability,
405{
406    type SQLType = T::SQLType;
407    type Nullable = T::Nullable;
408    type Aggregate = T::Aggregate;
409
410    fn to_expr_sql(&self) -> SQL<'a, V> {
411        (**self).to_expr_sql()
412    }
413
414    fn into_expr_sql(self) -> SQL<'a, V> {
415        (*self).to_expr_sql()
416    }
417
418    fn to_condition_sql(&self) -> Option<SQL<'a, V>> {
419        (**self).to_condition_sql()
420    }
421
422    fn into_condition_sql(self) -> Option<SQL<'a, V>> {
423        (*self).to_condition_sql()
424    }
425}
426
427// =============================================================================
428// UUID (Feature-Gated)
429// =============================================================================
430
431#[cfg(feature = "uuid")]
432impl<'a, V> Expr<'a, V> for uuid::Uuid
433where
434    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
435{
436    type SQLType = <V::DialectMarker as DialectTypes>::Uuid;
437    type Nullable = NonNull;
438    type Aggregate = Scalar;
439}
440
441#[cfg(feature = "rust-decimal")]
442impl<'a, V> Expr<'a, V> for rust_decimal::Decimal
443where
444    V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
445    Self: ValueTypeForDialect<V::DialectMarker>,
446{
447    type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
448    type Nullable = NonNull;
449    type Aggregate = Scalar;
450}
451
452// =============================================================================
453// Date and Time Values (Feature-Gated)
454// =============================================================================
455
456// Lets a date or time value stand where an expression goes (`eq(col, value)`,
457// `gt(col, value)`), typed as the SQL type its dialect stores it as.
458#[cfg(any(feature = "chrono", feature = "time", feature = "jiff"))]
459macro_rules! impl_value_expr {
460    ($($ty:ty),+ $(,)?) => {$(
461        impl<'a, V> Expr<'a, V> for $ty
462        where
463            V: SQLParam + 'a + From<Self> + Into<Cow<'a, V>>,
464            Self: ValueTypeForDialect<V::DialectMarker>,
465        {
466            type SQLType = <Self as ValueTypeForDialect<V::DialectMarker>>::SQLType;
467            type Nullable = NonNull;
468            type Aggregate = Scalar;
469        }
470
471        impl ExprSources for $ty {
472            type Sources = ();
473        }
474    )+};
475}
476
477#[cfg(feature = "chrono")]
478impl_value_expr!(
479    chrono::NaiveDate,
480    chrono::NaiveTime,
481    chrono::NaiveDateTime,
482    chrono::DateTime<chrono::Utc>,
483    chrono::DateTime<chrono::FixedOffset>,
484    chrono::Duration,
485);
486
487#[cfg(feature = "time")]
488impl_value_expr!(
489    time::Date,
490    time::Time,
491    time::PrimitiveDateTime,
492    time::OffsetDateTime,
493    time::Duration,
494);
495
496#[cfg(feature = "jiff")]
497impl_value_expr!(
498    jiff::civil::Date,
499    jiff::civil::Time,
500    jiff::civil::DateTime,
501    jiff::Timestamp,
502);
503
504// =============================================================================
505// SQL Type - Backward Compatibility
506// Allows untyped columns (which return SQL) to work with typed functions.
507// =============================================================================
508
509impl<'a, V> Expr<'a, V> for crate::sql::SQL<'a, V>
510where
511    V: SQLParam + 'a,
512{
513    type SQLType = <V::DialectMarker as DialectTypes>::Any;
514    type Nullable = Null;
515    type Aggregate = Scalar;
516}
517
518// Literals and raw SQL read no source.
519impl ExprSources for i8 {
520    type Sources = ();
521}
522
523impl ExprSources for i16 {
524    type Sources = ();
525}
526
527impl ExprSources for i32 {
528    type Sources = ();
529}
530
531impl ExprSources for i64 {
532    type Sources = ();
533}
534
535impl ExprSources for isize {
536    type Sources = ();
537}
538
539impl ExprSources for u8 {
540    type Sources = ();
541}
542
543impl ExprSources for u16 {
544    type Sources = ();
545}
546
547impl ExprSources for u32 {
548    type Sources = ();
549}
550
551impl ExprSources for u64 {
552    type Sources = ();
553}
554
555impl ExprSources for usize {
556    type Sources = ();
557}
558
559impl ExprSources for f32 {
560    type Sources = ();
561}
562
563impl ExprSources for f64 {
564    type Sources = ();
565}
566
567impl ExprSources for bool {
568    type Sources = ();
569}
570
571impl ExprSources for &str {
572    type Sources = ();
573}
574
575impl ExprSources for String {
576    type Sources = ();
577}
578
579#[cfg(feature = "compact-str")]
580impl ExprSources for compact_str::CompactString {
581    type Sources = ();
582}
583
584#[cfg(feature = "bytes")]
585impl ExprSources for bytes::Bytes {
586    type Sources = ();
587}
588
589#[cfg(feature = "bytes")]
590impl ExprSources for bytes::BytesMut {
591    type Sources = ();
592}
593
594#[cfg(feature = "arrayvec")]
595impl<const N: usize> ExprSources for arrayvec::ArrayString<N> {
596    type Sources = ();
597}
598
599#[cfg(feature = "arrayvec")]
600impl<const N: usize> ExprSources for arrayvec::ArrayVec<u8, N> {
601    type Sources = ();
602}
603
604#[cfg(feature = "smallvec-types")]
605impl<const N: usize> ExprSources for smallvec::SmallVec<[u8; N]> {
606    type Sources = ();
607}
608
609impl<const N: usize> ExprSources for [char; N] {
610    type Sources = ();
611}
612
613impl ExprSources for &[u8] {
614    type Sources = ();
615}
616
617impl<const N: usize> ExprSources for [u8; N] {
618    type Sources = ();
619}
620
621impl ExprSources for Vec<u8> {
622    type Sources = ();
623}
624
625impl ExprSources for Cow<'_, [u8]> {
626    type Sources = ();
627}
628
629impl ExprSources for SQLBytes<'_> {
630    type Sources = ();
631}
632
633#[cfg(feature = "uuid")]
634impl ExprSources for uuid::Uuid {
635    type Sources = ();
636}
637
638#[cfg(feature = "rust-decimal")]
639impl ExprSources for rust_decimal::Decimal {
640    type Sources = ();
641}
642
643impl<V: SQLParam> ExprSources for crate::sql::SQL<'_, V> {
644    type Sources = ();
645}