1use diesel::query_builder::{BindCollector, MoveableBindCollector};
4use diesel::serialize::{IsNull, Output};
5use diesel::sql_types::HasSqlType;
6use diesel::sqlite::SqliteType;
7use diesel::QueryResult;
8
9use crate::backend::LibSql;
10
11#[derive(Debug)]
15pub struct LibSqlBindValue<'a> {
16 pub(crate) inner: InternalBindValue<'a>,
17}
18
19#[derive(Debug)]
20pub(crate) enum InternalBindValue<'a> {
21 Null,
22 I32(i32),
23 I64(i64),
24 F64(f64),
25 BorrowedString(&'a str),
26 String(Box<str>),
27 BorrowedBinary(&'a [u8]),
28 Binary(Box<[u8]>),
29}
30
31impl std::fmt::Display for InternalBindValue<'_> {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 let name = match self {
34 InternalBindValue::Null => "Null",
35 InternalBindValue::I32(_) | InternalBindValue::I64(_) => "Integer",
36 InternalBindValue::F64(_) => "Float",
37 InternalBindValue::BorrowedString(_) | InternalBindValue::String(_) => "Text",
38 InternalBindValue::BorrowedBinary(_) | InternalBindValue::Binary(_) => "Binary",
39 };
40 f.write_str(name)
41 }
42}
43
44impl InternalBindValue<'_> {
45 pub(crate) fn to_libsql_value(&self) -> libsql::Value {
47 match self {
48 InternalBindValue::Null => libsql::Value::Null,
49 InternalBindValue::I32(i) => libsql::Value::Integer(*i as i64),
50 InternalBindValue::I64(i) => libsql::Value::Integer(*i),
51 InternalBindValue::F64(f) => libsql::Value::Real(*f),
52 InternalBindValue::BorrowedString(s) => libsql::Value::Text((*s).to_string()),
53 InternalBindValue::String(s) => libsql::Value::Text(s.to_string()),
54 InternalBindValue::BorrowedBinary(b) => libsql::Value::Blob(b.to_vec()),
55 InternalBindValue::Binary(b) => libsql::Value::Blob(b.to_vec()),
56 }
57 }
58}
59
60impl From<i32> for LibSqlBindValue<'_> {
62 fn from(i: i32) -> Self {
63 Self {
64 inner: InternalBindValue::I32(i),
65 }
66 }
67}
68
69impl From<i64> for LibSqlBindValue<'_> {
70 fn from(i: i64) -> Self {
71 Self {
72 inner: InternalBindValue::I64(i),
73 }
74 }
75}
76
77impl From<f64> for LibSqlBindValue<'_> {
78 fn from(f: f64) -> Self {
79 Self {
80 inner: InternalBindValue::F64(f),
81 }
82 }
83}
84
85impl<'a> From<&'a str> for LibSqlBindValue<'a> {
86 fn from(s: &'a str) -> Self {
87 Self {
88 inner: InternalBindValue::BorrowedString(s),
89 }
90 }
91}
92
93impl From<String> for LibSqlBindValue<'_> {
94 fn from(s: String) -> Self {
95 Self {
96 inner: InternalBindValue::String(s.into_boxed_str()),
97 }
98 }
99}
100
101impl<'a> From<&'a [u8]> for LibSqlBindValue<'a> {
102 fn from(b: &'a [u8]) -> Self {
103 Self {
104 inner: InternalBindValue::BorrowedBinary(b),
105 }
106 }
107}
108
109impl From<Vec<u8>> for LibSqlBindValue<'_> {
110 fn from(b: Vec<u8>) -> Self {
111 Self {
112 inner: InternalBindValue::Binary(b.into_boxed_slice()),
113 }
114 }
115}
116
117impl<'a, T> From<Option<T>> for LibSqlBindValue<'a>
118where
119 T: Into<LibSqlBindValue<'a>>,
120{
121 fn from(o: Option<T>) -> Self {
122 match o {
123 Some(v) => v.into(),
124 None => Self {
125 inner: InternalBindValue::Null,
126 },
127 }
128 }
129}
130
131#[derive(Debug, Default)]
133pub struct LibSqlBindCollector<'a> {
134 pub(crate) binds: Vec<(InternalBindValue<'a>, SqliteType)>,
135}
136
137impl<'a> BindCollector<'a, LibSql> for LibSqlBindCollector<'a> {
138 type Buffer = LibSqlBindValue<'a>;
139
140 fn push_bound_value<T, U>(&mut self, bind: &'a U, metadata_lookup: &mut ()) -> QueryResult<()>
141 where
142 LibSql: HasSqlType<T>,
143 U: diesel::serialize::ToSql<T, LibSql> + ?Sized,
144 {
145 let value = LibSqlBindValue {
146 inner: InternalBindValue::Null,
147 };
148 let mut to_sql_output = Output::new(value, metadata_lookup);
149 let is_null = bind
150 .to_sql(&mut to_sql_output)
151 .map_err(diesel::result::Error::SerializationError)?;
152 let bind = to_sql_output.into_inner();
153 let metadata = <LibSql as HasSqlType<T>>::metadata(metadata_lookup);
154 self.binds.push((
155 match is_null {
156 IsNull::No => bind.inner,
157 IsNull::Yes => InternalBindValue::Null,
158 },
159 metadata,
160 ));
161 Ok(())
162 }
163
164 fn push_null_value(&mut self, metadata: SqliteType) -> QueryResult<()> {
165 self.binds.push((InternalBindValue::Null, metadata));
166 Ok(())
167 }
168}
169
170#[derive(Debug, Clone)]
172enum OwnedBindValue {
173 Null,
174 I32(i32),
175 I64(i64),
176 F64(f64),
177 String(Box<str>),
178 Binary(Box<[u8]>),
179}
180
181impl From<&InternalBindValue<'_>> for OwnedBindValue {
182 fn from(value: &InternalBindValue<'_>) -> Self {
183 match value {
184 InternalBindValue::Null => OwnedBindValue::Null,
185 InternalBindValue::I32(v) => OwnedBindValue::I32(*v),
186 InternalBindValue::I64(v) => OwnedBindValue::I64(*v),
187 InternalBindValue::F64(v) => OwnedBindValue::F64(*v),
188 InternalBindValue::BorrowedString(s) => {
189 OwnedBindValue::String(String::from(*s).into_boxed_str())
190 }
191 InternalBindValue::String(s) => OwnedBindValue::String(s.clone()),
192 InternalBindValue::BorrowedBinary(b) => {
193 OwnedBindValue::Binary(Vec::from(*b).into_boxed_slice())
194 }
195 InternalBindValue::Binary(b) => OwnedBindValue::Binary(b.clone()),
196 }
197 }
198}
199
200impl From<&OwnedBindValue> for InternalBindValue<'_> {
201 fn from(value: &OwnedBindValue) -> Self {
202 match value {
203 OwnedBindValue::Null => InternalBindValue::Null,
204 OwnedBindValue::I32(v) => InternalBindValue::I32(*v),
205 OwnedBindValue::I64(v) => InternalBindValue::I64(*v),
206 OwnedBindValue::F64(v) => InternalBindValue::F64(*v),
207 OwnedBindValue::String(s) => InternalBindValue::String(s.clone()),
208 OwnedBindValue::Binary(b) => InternalBindValue::Binary(b.clone()),
209 }
210 }
211}
212
213#[derive(Debug)]
217pub struct LibSqlBindCollectorData {
218 binds: Vec<(OwnedBindValue, SqliteType)>,
219}
220
221impl MoveableBindCollector<LibSql> for LibSqlBindCollector<'_> {
222 type BindData = LibSqlBindCollectorData;
223
224 fn moveable(&self) -> Self::BindData {
225 LibSqlBindCollectorData {
226 binds: self
227 .binds
228 .iter()
229 .map(|(bind, tpe)| (OwnedBindValue::from(bind), *tpe))
230 .collect(),
231 }
232 }
233
234 fn append_bind_data(&mut self, from: &Self::BindData) {
235 self.binds.reserve_exact(from.binds.len());
236 self.binds.extend(
237 from.binds
238 .iter()
239 .map(|(bind, tpe)| (InternalBindValue::from(bind), *tpe)),
240 );
241 }
242
243 fn push_debug_binds<'a, 'b>(
244 bind_data: &Self::BindData,
245 f: &'a mut Vec<Box<dyn std::fmt::Debug + 'b>>,
246 ) {
247 f.extend(
248 bind_data
249 .binds
250 .iter()
251 .map(|(b, _)| Box::new(b.clone()) as Box<dyn std::fmt::Debug>),
252 );
253 }
254}