Skip to main content

drizzle_sqlite/values/
mod.rs

1//! `SQLite` value types and conversions
2//!
3//! This module contains the core `SQLiteValue` type and all its conversions.
4
5mod conversions;
6mod drivers;
7mod insert;
8pub mod owned;
9mod update;
10
11pub use insert::*;
12pub use owned::*;
13pub use update::*;
14
15use crate::prelude::*;
16use crate::traits::FromSQLiteValue;
17use drizzle_core::{dialect::Dialect, error::DrizzleError, sql::SQL, traits::SQLParam};
18
19//------------------------------------------------------------------------------
20// SQLiteValue Definition
21//------------------------------------------------------------------------------
22
23/// Represents a `SQLite` value
24#[derive(Debug, Clone, PartialEq, PartialOrd, Default)]
25pub enum SQLiteValue<'a> {
26    /// Integer value (i64)
27    Integer(i64),
28    /// Real value (f64)
29    Real(f64),
30    /// Text value (borrowed or owned string)
31    Text(Cow<'a, str>),
32    /// Blob value (borrowed or owned binary data)
33    Blob(Cow<'a, [u8]>),
34    /// NULL value
35    #[default]
36    Null,
37}
38
39impl SQLiteValue<'_> {
40    /// Returns true if this value is NULL.
41    #[inline]
42    #[must_use]
43    pub const fn is_null(&self) -> bool {
44        matches!(self, SQLiteValue::Null)
45    }
46
47    /// Returns the integer value if this is an INTEGER.
48    #[inline]
49    #[must_use]
50    pub const fn as_i64(&self) -> Option<i64> {
51        match self {
52            SQLiteValue::Integer(value) => Some(*value),
53            _ => None,
54        }
55    }
56
57    /// Returns the real value if this is a REAL.
58    #[inline]
59    #[must_use]
60    pub const fn as_f64(&self) -> Option<f64> {
61        match self {
62            SQLiteValue::Real(value) => Some(*value),
63            _ => None,
64        }
65    }
66
67    /// Returns the text value if this is TEXT.
68    #[inline]
69    #[must_use]
70    pub fn as_str(&self) -> Option<&str> {
71        match self {
72            SQLiteValue::Text(value) => Some(value.as_ref()),
73            _ => None,
74        }
75    }
76
77    /// Returns the blob value if this is BLOB.
78    #[inline]
79    #[must_use]
80    pub fn as_bytes(&self) -> Option<&[u8]> {
81        match self {
82            SQLiteValue::Blob(value) => Some(value.as_ref()),
83            _ => None,
84        }
85    }
86
87    /// Converts this value into an owned representation.
88    #[inline]
89    #[must_use]
90    pub fn into_owned(self) -> OwnedSQLiteValue {
91        self.into()
92    }
93
94    /// Convert this `SQLite` value to a Rust type using the `FromSQLiteValue` trait.
95    ///
96    /// This provides a unified conversion interface for all types that implement
97    /// `FromSQLiteValue`, including primitives and enum types.
98    ///
99    /// # Errors
100    ///
101    /// Returns [`DrizzleError::ConversionError`] when the stored variant cannot
102    /// be decoded into `T`.
103    ///
104    /// # Example
105    /// ```rust
106    /// # let _ = r####"
107    /// let value = SQLiteValue::Integer(42);
108    /// let num: i64 = value.convert()?;
109    /// # "####;
110    /// ```
111    pub fn convert<T: FromSQLiteValue>(self) -> Result<T, DrizzleError> {
112        match self {
113            SQLiteValue::Integer(i) => T::from_sqlite_integer(i),
114            SQLiteValue::Text(s) => T::from_sqlite_text(&s),
115            SQLiteValue::Real(r) => T::from_sqlite_real(r),
116            SQLiteValue::Blob(b) => T::from_sqlite_blob(&b),
117            SQLiteValue::Null => T::from_sqlite_null(),
118        }
119    }
120
121    /// Convert a reference to this `SQLite` value to a Rust type.
122    ///
123    /// # Errors
124    ///
125    /// Returns [`DrizzleError::ConversionError`] when the stored variant cannot
126    /// be decoded into `T`.
127    pub fn convert_ref<T: FromSQLiteValue>(&self) -> Result<T, DrizzleError> {
128        match self {
129            SQLiteValue::Integer(i) => T::from_sqlite_integer(*i),
130            SQLiteValue::Text(s) => T::from_sqlite_text(s),
131            SQLiteValue::Real(r) => T::from_sqlite_real(*r),
132            SQLiteValue::Blob(b) => T::from_sqlite_blob(b),
133            SQLiteValue::Null => T::from_sqlite_null(),
134        }
135    }
136}
137
138impl core::fmt::Display for SQLiteValue<'_> {
139    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
140        let value = match self {
141            SQLiteValue::Integer(i) => i.to_string(),
142            SQLiteValue::Real(r) => r.to_string(),
143            SQLiteValue::Text(cow) => cow.to_string(),
144            SQLiteValue::Blob(cow) => String::from_utf8_lossy(cow).to_string(),
145            SQLiteValue::Null => String::new(),
146        };
147        write!(f, "{value}")
148    }
149}
150
151// Implement core traits required by Drizzle
152impl SQLParam for SQLiteValue<'_> {
153    const DIALECT: Dialect = Dialect::SQLite;
154    type DialectMarker = drizzle_core::dialect::SQLiteDialect;
155}
156
157impl<'a> From<SQLiteValue<'a>> for SQL<'a, SQLiteValue<'a>> {
158    fn from(value: SQLiteValue<'a>) -> Self {
159        SQL::param(value)
160    }
161}
162
163impl FromIterator<OwnedSQLiteValue> for Vec<SQLiteValue<'_>> {
164    fn from_iter<T: IntoIterator<Item = OwnedSQLiteValue>>(iter: T) -> Self {
165        iter.into_iter().map(SQLiteValue::from).collect()
166    }
167}
168
169impl<'a> FromIterator<&'a OwnedSQLiteValue> for Vec<SQLiteValue<'a>> {
170    fn from_iter<T: IntoIterator<Item = &'a OwnedSQLiteValue>>(iter: T) -> Self {
171        iter.into_iter().map(SQLiteValue::from).collect()
172    }
173}