drizzle_sqlite/values/
mod.rs1mod conversions;
6mod drivers;
7mod insert;
8#[cfg(feature = "serde")]
9mod json;
10pub mod owned;
11mod update;
12
13pub use insert::*;
14pub use owned::*;
15pub use update::*;
16
17use crate::prelude::*;
18use crate::traits::FromSQLiteValue;
19use drizzle_core::{dialect::Dialect, error::DrizzleError, sql::SQL, traits::SQLParam};
20
21#[derive(Debug, Clone, PartialEq, PartialOrd, Default)]
27pub enum SQLiteValue<'a> {
28 Integer(i64),
30 Real(f64),
32 Text(Cow<'a, str>),
34 Blob(Cow<'a, [u8]>),
36 #[default]
38 Null,
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
47pub enum SQLiteValueRef<'a> {
48 Integer(i64),
50 Real(f64),
52 Text(&'a str),
54 Blob(&'a [u8]),
56 #[default]
58 Null,
59}
60
61impl<'a> SQLiteValueRef<'a> {
62 #[inline]
64 #[must_use]
65 pub const fn into_value(self) -> SQLiteValue<'a> {
66 match self {
67 Self::Integer(value) => SQLiteValue::Integer(value),
68 Self::Real(value) => SQLiteValue::Real(value),
69 Self::Text(value) => SQLiteValue::Text(Cow::Borrowed(value)),
70 Self::Blob(value) => SQLiteValue::Blob(Cow::Borrowed(value)),
71 Self::Null => SQLiteValue::Null,
72 }
73 }
74
75 #[cfg(feature = "rusqlite")]
83 #[inline]
84 pub fn try_from_rusqlite_value_ref(
85 value: ::rusqlite::types::ValueRef<'a>,
86 ) -> Result<Self, DrizzleError> {
87 match value {
88 ::rusqlite::types::ValueRef::Null => Ok(Self::Null),
89 ::rusqlite::types::ValueRef::Integer(value) => Ok(Self::Integer(value)),
90 ::rusqlite::types::ValueRef::Real(value) => Ok(Self::Real(value)),
91 ::rusqlite::types::ValueRef::Text(value) => {
92 let value = core::str::from_utf8(value).map_err(|e| {
93 DrizzleError::ConversionError(format!("invalid UTF-8: {e}").into())
94 })?;
95 Ok(Self::Text(value))
96 }
97 ::rusqlite::types::ValueRef::Blob(value) => Ok(Self::Blob(value)),
98 }
99 }
100}
101
102impl<'a> From<SQLiteValueRef<'a>> for SQLiteValue<'a> {
103 #[inline]
104 fn from(value: SQLiteValueRef<'a>) -> Self {
105 value.into_value()
106 }
107}
108
109impl<'a> From<&'a SQLiteValue<'_>> for SQLiteValueRef<'a> {
110 #[inline]
111 fn from(value: &'a SQLiteValue<'_>) -> Self {
112 value.as_ref()
113 }
114}
115
116impl SQLiteValue<'_> {
117 #[inline]
119 #[must_use]
120 pub const fn is_null(&self) -> bool {
121 matches!(self, SQLiteValue::Null)
122 }
123
124 #[inline]
126 #[must_use]
127 pub const fn as_i64(&self) -> Option<i64> {
128 match self {
129 SQLiteValue::Integer(value) => Some(*value),
130 _ => None,
131 }
132 }
133
134 #[inline]
136 #[must_use]
137 pub const fn as_f64(&self) -> Option<f64> {
138 match self {
139 SQLiteValue::Real(value) => Some(*value),
140 _ => None,
141 }
142 }
143
144 #[inline]
146 #[must_use]
147 pub fn as_str(&self) -> Option<&str> {
148 match self {
149 SQLiteValue::Text(value) => Some(value.as_ref()),
150 _ => None,
151 }
152 }
153
154 #[inline]
156 #[must_use]
157 pub fn as_bytes(&self) -> Option<&[u8]> {
158 match self {
159 SQLiteValue::Blob(value) => Some(value.as_ref()),
160 _ => None,
161 }
162 }
163
164 #[inline]
166 #[must_use]
167 pub fn as_ref(&self) -> SQLiteValueRef<'_> {
168 match self {
169 SQLiteValue::Integer(value) => SQLiteValueRef::Integer(*value),
170 SQLiteValue::Real(value) => SQLiteValueRef::Real(*value),
171 SQLiteValue::Text(value) => SQLiteValueRef::Text(value.as_ref()),
172 SQLiteValue::Blob(value) => SQLiteValueRef::Blob(value.as_ref()),
173 SQLiteValue::Null => SQLiteValueRef::Null,
174 }
175 }
176
177 #[inline]
179 #[must_use]
180 pub fn into_owned(self) -> OwnedSQLiteValue {
181 self.into()
182 }
183
184 pub fn convert<T: FromSQLiteValue>(self) -> Result<T, DrizzleError> {
202 T::from_sqlite_ref(self.as_ref())
203 }
204
205 pub fn convert_ref<T: FromSQLiteValue>(&self) -> Result<T, DrizzleError> {
212 T::from_sqlite_ref(self.as_ref())
213 }
214}
215
216impl core::fmt::Display for SQLiteValue<'_> {
217 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
218 let value = match self {
219 SQLiteValue::Integer(i) => i.to_string(),
220 SQLiteValue::Real(r) => r.to_string(),
221 SQLiteValue::Text(cow) => cow.to_string(),
222 SQLiteValue::Blob(cow) => String::from_utf8_lossy(cow).to_string(),
223 SQLiteValue::Null => String::new(),
224 };
225 write!(f, "{value}")
226 }
227}
228
229impl SQLParam for SQLiteValue<'_> {
231 const DIALECT: Dialect = Dialect::SQLite;
232 type DialectMarker = drizzle_core::dialect::SQLiteDialect;
233
234 fn write_literal(&self, buf: &mut String) -> bool {
235 use core::fmt::Write;
236 match self {
237 SQLiteValue::Null => buf.push_str("NULL"),
238 SQLiteValue::Integer(value) => {
239 let _ = write!(buf, "{value}");
240 }
241 SQLiteValue::Real(value) if value.is_nan() => return false,
245 SQLiteValue::Real(value) if value.is_infinite() => {
246 buf.push_str(if value.is_sign_positive() {
247 "9e999"
248 } else {
249 "-9e999"
250 });
251 }
252 SQLiteValue::Real(value) => {
253 let _ = write!(buf, "{value:?}");
254 }
255 SQLiteValue::Text(text) if text.contains('\0') => return false,
256 SQLiteValue::Text(text) => {
257 buf.push('\'');
258 buf.push_str(&text.replace('\'', "''"));
259 buf.push('\'');
260 }
261 SQLiteValue::Blob(bytes) => {
262 buf.push_str("X'");
263 for byte in bytes.iter() {
264 let _ = write!(buf, "{byte:02X}");
265 }
266 buf.push('\'');
267 }
268 }
269 true
270 }
271}
272
273impl<'a> From<SQLiteValue<'a>> for SQL<'a, SQLiteValue<'a>> {
274 fn from(value: SQLiteValue<'a>) -> Self {
275 SQL::param(value)
276 }
277}
278
279impl FromIterator<OwnedSQLiteValue> for Vec<SQLiteValue<'_>> {
280 fn from_iter<T: IntoIterator<Item = OwnedSQLiteValue>>(iter: T) -> Self {
281 iter.into_iter().map(SQLiteValue::from).collect()
282 }
283}
284
285impl<'a> FromIterator<&'a OwnedSQLiteValue> for Vec<SQLiteValue<'a>> {
286 fn from_iter<T: IntoIterator<Item = &'a OwnedSQLiteValue>>(iter: T) -> Self {
287 iter.into_iter().map(SQLiteValue::from).collect()
288 }
289}