Skip to main content

drizzle_sqlite/values/
drivers.rs

1//! Database driver implementations for `SQLiteValue`
2//!
3//! Contains implementations for rusqlite, turso, and libsql drivers.
4
5#[cfg(any(feature = "rusqlite", feature = "turso", feature = "libsql"))]
6use super::SQLiteValue;
7#[cfg(feature = "rusqlite")]
8use std::borrow::Cow;
9
10#[cfg(feature = "rusqlite")]
11use rusqlite::types::FromSql;
12#[cfg(feature = "turso")]
13use turso::IntoValue;
14
15//------------------------------------------------------------------------------
16// rusqlite implementations
17//------------------------------------------------------------------------------
18
19#[cfg(feature = "rusqlite")]
20impl rusqlite::ToSql for SQLiteValue<'_> {
21    fn to_sql(&self) -> ::rusqlite::Result<::rusqlite::types::ToSqlOutput<'_>> {
22        match self {
23            SQLiteValue::Null => Ok(rusqlite::types::ToSqlOutput::Owned(
24                rusqlite::types::Value::Null,
25            )),
26            SQLiteValue::Integer(i) => Ok(rusqlite::types::ToSqlOutput::Owned(
27                rusqlite::types::Value::Integer(*i),
28            )),
29            SQLiteValue::Real(f) => Ok(rusqlite::types::ToSqlOutput::Owned(
30                rusqlite::types::Value::Real(*f),
31            )),
32            SQLiteValue::Text(s) => Ok(rusqlite::types::ToSqlOutput::Borrowed(
33                rusqlite::types::ValueRef::Text(s.as_bytes()),
34            )),
35            SQLiteValue::Blob(b) => Ok(rusqlite::types::ToSqlOutput::Borrowed(
36                rusqlite::types::ValueRef::Blob(b.as_ref()),
37            )),
38        }
39    }
40}
41
42#[cfg(feature = "rusqlite")]
43impl FromSql for SQLiteValue<'_> {
44    fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
45        let result = match value {
46            rusqlite::types::ValueRef::Null => SQLiteValue::Null,
47            rusqlite::types::ValueRef::Integer(i) => SQLiteValue::Integer(i),
48            rusqlite::types::ValueRef::Real(r) => SQLiteValue::Real(r),
49            rusqlite::types::ValueRef::Text(items) => {
50                SQLiteValue::Text(String::from_utf8_lossy(items).into_owned().into())
51            }
52            rusqlite::types::ValueRef::Blob(items) => SQLiteValue::Blob(items.to_vec().into()),
53        };
54        Ok(result)
55    }
56}
57
58#[cfg(feature = "rusqlite")]
59impl From<rusqlite::types::Value> for SQLiteValue<'_> {
60    fn from(value: rusqlite::types::Value) -> Self {
61        match value {
62            rusqlite::types::Value::Null => SQLiteValue::Null,
63            rusqlite::types::Value::Integer(i) => SQLiteValue::Integer(i),
64            rusqlite::types::Value::Real(r) => SQLiteValue::Real(r),
65            rusqlite::types::Value::Text(s) => SQLiteValue::Text(s.into()),
66            rusqlite::types::Value::Blob(b) => SQLiteValue::Blob(b.into()),
67        }
68    }
69}
70
71#[cfg(feature = "rusqlite")]
72impl<'a> From<rusqlite::types::ValueRef<'a>> for SQLiteValue<'a> {
73    fn from(value: rusqlite::types::ValueRef<'a>) -> Self {
74        match value {
75            rusqlite::types::ValueRef::Null => SQLiteValue::Null,
76            rusqlite::types::ValueRef::Integer(i) => SQLiteValue::Integer(i),
77            rusqlite::types::ValueRef::Real(r) => SQLiteValue::Real(r),
78            // Zero-copy: borrow if valid UTF-8, otherwise allocate for lossy conversion
79            rusqlite::types::ValueRef::Text(items) => std::str::from_utf8(items).map_or_else(
80                |_| SQLiteValue::Text(String::from_utf8_lossy(items).into_owned().into()),
81                |s| SQLiteValue::Text(Cow::Borrowed(s)),
82            ),
83            // Zero-copy: borrow the blob slice directly
84            rusqlite::types::ValueRef::Blob(items) => SQLiteValue::Blob(Cow::Borrowed(items)),
85        }
86    }
87}
88
89//------------------------------------------------------------------------------
90// turso implementations
91//------------------------------------------------------------------------------
92
93#[cfg(feature = "turso")]
94impl IntoValue for SQLiteValue<'_> {
95    fn into_value(self) -> turso::Result<turso::Value> {
96        Ok(turso::Value::from(self))
97    }
98}
99
100#[cfg(feature = "turso")]
101impl IntoValue for &SQLiteValue<'_> {
102    fn into_value(self) -> turso::Result<turso::Value> {
103        Ok(turso::Value::from(self))
104    }
105}
106
107#[cfg(feature = "turso")]
108impl<'a> From<SQLiteValue<'a>> for turso::Value {
109    fn from(value: SQLiteValue<'a>) -> Self {
110        match value {
111            SQLiteValue::Integer(i) => Self::Integer(i),
112            SQLiteValue::Real(r) => Self::Real(r),
113            SQLiteValue::Text(cow) => Self::Text(cow.into_owned()),
114            SQLiteValue::Blob(cow) => Self::Blob(cow.into_owned()),
115            SQLiteValue::Null => Self::Null,
116        }
117    }
118}
119
120#[cfg(feature = "turso")]
121impl<'a> From<&SQLiteValue<'a>> for turso::Value {
122    fn from(value: &SQLiteValue<'a>) -> Self {
123        match value {
124            SQLiteValue::Integer(i) => Self::Integer(*i),
125            SQLiteValue::Real(r) => Self::Real(*r),
126            SQLiteValue::Text(cow) => Self::Text(cow.clone().into_owned()),
127            SQLiteValue::Blob(cow) => Self::Blob(cow.clone().into_owned()),
128            SQLiteValue::Null => Self::Null,
129        }
130    }
131}
132
133//------------------------------------------------------------------------------
134// libsql implementations
135//------------------------------------------------------------------------------
136
137#[cfg(feature = "libsql")]
138impl<'a> From<SQLiteValue<'a>> for libsql::Value {
139    fn from(value: SQLiteValue<'a>) -> Self {
140        match value {
141            SQLiteValue::Integer(i) => Self::Integer(i),
142            SQLiteValue::Real(r) => Self::Real(r),
143            SQLiteValue::Text(cow) => Self::Text(cow.into_owned()),
144            SQLiteValue::Blob(cow) => Self::Blob(cow.into_owned()),
145            SQLiteValue::Null => Self::Null,
146        }
147    }
148}
149
150#[cfg(feature = "libsql")]
151impl<'a> From<&SQLiteValue<'a>> for libsql::Value {
152    fn from(value: &SQLiteValue<'a>) -> Self {
153        match value {
154            SQLiteValue::Integer(i) => Self::Integer(*i),
155            SQLiteValue::Real(r) => Self::Real(*r),
156            SQLiteValue::Text(cow) => Self::Text(cow.clone().into_owned()),
157            SQLiteValue::Blob(cow) => Self::Blob(cow.clone().into_owned()),
158            SQLiteValue::Null => Self::Null,
159        }
160    }
161}