1use std::{
2 ffi::OsStr,
3 os::unix::prelude::OsStrExt,
4 path::{Path, PathBuf},
5 sync::Arc,
6};
7
8use anyhow::{Context, Result};
9
10use crate::statement::{SqlType, Statement};
11
12pub trait StaticColumnCount {
13 fn column_count() -> usize {
14 1
15 }
16}
17
18pub trait Bind {
19 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32>;
20}
21
22pub trait Column: Sized {
23 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)>;
24}
25
26impl StaticColumnCount for bool {}
27impl Bind for bool {
28 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
29 statement
30 .bind(&self.then_some(1).unwrap_or(0), start_index)
31 .with_context(|| format!("Failed to bind bool at index {start_index}"))
32 }
33}
34
35impl Column for bool {
36 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
37 i32::column(statement, start_index)
38 .map(|(i, next_index)| (i != 0, next_index))
39 .with_context(|| format!("Failed to read bool at index {start_index}"))
40 }
41}
42
43impl StaticColumnCount for &[u8] {}
44impl Bind for &[u8] {
45 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
46 statement
47 .bind_blob(start_index, self)
48 .with_context(|| format!("Failed to bind &[u8] at index {start_index}"))?;
49 Ok(start_index + 1)
50 }
51}
52
53impl<const C: usize> StaticColumnCount for &[u8; C] {}
54impl<const C: usize> Bind for &[u8; C] {
55 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
56 statement
57 .bind_blob(start_index, self.as_slice())
58 .with_context(|| format!("Failed to bind &[u8; C] at index {start_index}"))?;
59 Ok(start_index + 1)
60 }
61}
62
63impl<const C: usize> Column for [u8; C] {
64 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
65 let bytes_slice = statement.column_blob(start_index)?;
66 let array = bytes_slice.try_into()?;
67 Ok((array, start_index + 1))
68 }
69}
70
71impl StaticColumnCount for Vec<u8> {}
72impl Bind for Vec<u8> {
73 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
74 statement
75 .bind_blob(start_index, self)
76 .with_context(|| format!("Failed to bind Vec<u8> at index {start_index}"))?;
77 Ok(start_index + 1)
78 }
79}
80
81impl Column for Vec<u8> {
82 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
83 let result = statement
84 .column_blob(start_index)
85 .with_context(|| format!("Failed to read Vec<u8> at index {start_index}"))?;
86
87 Ok((Vec::from(result), start_index + 1))
88 }
89}
90
91impl StaticColumnCount for f64 {}
92impl Bind for f64 {
93 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
94 statement
95 .bind_double(start_index, *self)
96 .with_context(|| format!("Failed to bind f64 at index {start_index}"))?;
97 Ok(start_index + 1)
98 }
99}
100
101impl Column for f64 {
102 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
103 let result = statement
104 .column_double(start_index)
105 .with_context(|| format!("Failed to parse f64 at index {start_index}"))?;
106
107 Ok((result, start_index + 1))
108 }
109}
110
111impl StaticColumnCount for f32 {}
112impl Bind for f32 {
113 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
114 statement
115 .bind_double(start_index, *self as f64)
116 .with_context(|| format!("Failed to bind f64 at index {start_index}"))?;
117 Ok(start_index + 1)
118 }
119}
120
121impl Column for f32 {
122 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
123 let result = statement
124 .column_double(start_index)
125 .with_context(|| format!("Failed to parse f32 at index {start_index}"))?
126 as f32;
127
128 Ok((result, start_index + 1))
129 }
130}
131
132impl StaticColumnCount for i32 {}
133impl Bind for i32 {
134 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
135 statement
136 .bind_int(start_index, *self)
137 .with_context(|| format!("Failed to bind i32 at index {start_index}"))?;
138
139 Ok(start_index + 1)
140 }
141}
142
143impl Column for i32 {
144 fn column<'a>(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
145 let result = statement.column_int(start_index)?;
146 Ok((result, start_index + 1))
147 }
148}
149
150impl StaticColumnCount for i64 {}
151impl Bind for i64 {
152 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
153 statement
154 .bind_int64(start_index, *self)
155 .with_context(|| format!("Failed to bind i64 at index {start_index}"))?;
156 Ok(start_index + 1)
157 }
158}
159
160impl Column for i64 {
161 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
162 let result = statement.column_int64(start_index)?;
163 Ok((result, start_index + 1))
164 }
165}
166
167impl StaticColumnCount for u32 {}
168impl Bind for u32 {
169 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
170 (*self as i64)
171 .bind(statement, start_index)
172 .with_context(|| format!("Failed to bind usize at index {start_index}"))
173 }
174}
175
176impl Column for u32 {
177 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
178 let result = statement.column_int64(start_index)?;
179 Ok((result as u32, start_index + 1))
180 }
181}
182
183impl StaticColumnCount for usize {}
184impl Bind for usize {
185 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
186 (*self as i64)
187 .bind(statement, start_index)
188 .with_context(|| format!("Failed to bind usize at index {start_index}"))
189 }
190}
191
192impl Column for usize {
193 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
194 let result = statement.column_int64(start_index)?;
195 Ok((result as usize, start_index + 1))
196 }
197}
198
199impl StaticColumnCount for &str {}
200impl Bind for &str {
201 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
202 statement.bind_text(start_index, self)?;
203 Ok(start_index + 1)
204 }
205}
206
207impl StaticColumnCount for Arc<str> {}
208impl Bind for Arc<str> {
209 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
210 statement.bind_text(start_index, self.as_ref())?;
211 Ok(start_index + 1)
212 }
213}
214
215impl StaticColumnCount for String {}
216impl Bind for String {
217 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
218 statement.bind_text(start_index, self)?;
219 Ok(start_index + 1)
220 }
221}
222
223impl Column for Arc<str> {
224 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
225 let result = statement.column_text(start_index)?;
226 Ok((Arc::from(result), start_index + 1))
227 }
228}
229
230impl Column for String {
231 fn column<'a>(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
232 let result = statement.column_text(start_index)?;
233 Ok((result.to_owned(), start_index + 1))
234 }
235}
236
237impl<T: StaticColumnCount> StaticColumnCount for Option<T> {
238 fn column_count() -> usize {
239 T::column_count()
240 }
241}
242impl<T: Bind + StaticColumnCount> Bind for Option<T> {
243 fn bind(&self, statement: &Statement, mut start_index: i32) -> Result<i32> {
244 if let Some(this) = self {
245 this.bind(statement, start_index)
246 } else {
247 for _ in 0..T::column_count() {
248 statement.bind_null(start_index)?;
249 start_index += 1;
250 }
251 Ok(start_index)
252 }
253 }
254}
255
256impl<T: Column + StaticColumnCount> Column for Option<T> {
257 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
258 if let SqlType::Null = statement.column_type(start_index)? {
259 Ok((None, start_index + T::column_count() as i32))
260 } else {
261 T::column(statement, start_index).map(|(result, next_index)| (Some(result), next_index))
262 }
263 }
264}
265
266impl<T: StaticColumnCount, const COUNT: usize> StaticColumnCount for [T; COUNT] {
267 fn column_count() -> usize {
268 T::column_count() * COUNT
269 }
270}
271impl<T: Bind, const COUNT: usize> Bind for [T; COUNT] {
272 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
273 let mut current_index = start_index;
274 for binding in self {
275 current_index = binding.bind(statement, current_index)?
276 }
277
278 Ok(current_index)
279 }
280}
281
282impl StaticColumnCount for &Path {}
283impl Bind for &Path {
284 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
285 self.as_os_str().as_bytes().bind(statement, start_index)
286 }
287}
288
289impl StaticColumnCount for Arc<Path> {}
290impl Bind for Arc<Path> {
291 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
292 self.as_ref().bind(statement, start_index)
293 }
294}
295
296impl StaticColumnCount for PathBuf {}
297impl Bind for PathBuf {
298 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
299 (self.as_ref() as &Path).bind(statement, start_index)
300 }
301}
302
303impl Column for PathBuf {
304 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
305 let blob = statement.column_blob(start_index)?;
306
307 Ok((
308 PathBuf::from(OsStr::from_bytes(blob).to_owned()),
309 start_index + 1,
310 ))
311 }
312}
313
314impl StaticColumnCount for uuid::Uuid {
315 fn column_count() -> usize {
316 1
317 }
318}
319
320impl Bind for uuid::Uuid {
321 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
322 self.as_bytes().bind(statement, start_index)
323 }
324}
325
326impl Column for uuid::Uuid {
327 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
328 let (bytes, next_index) = Column::column(statement, start_index)?;
329 Ok((uuid::Uuid::from_bytes(bytes), next_index))
330 }
331}
332
333impl StaticColumnCount for () {
334 fn column_count() -> usize {
335 0
336 }
337}
338/// Unit impls do nothing. This simplifies query macros
339impl Bind for () {
340 fn bind(&self, _statement: &Statement, start_index: i32) -> Result<i32> {
341 Ok(start_index)
342 }
343}
344
345impl Column for () {
346 fn column(_statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
347 Ok(((), start_index))
348 }
349}
350
351macro_rules! impl_tuple_row_traits {
352 ( $($local:ident: $type:ident),+ ) => {
353 impl<$($type: StaticColumnCount),+> StaticColumnCount for ($($type,)+) {
354 fn column_count() -> usize {
355 let mut count = 0;
356 $(count += $type::column_count();)+
357 count
358 }
359 }
360
361 impl<$($type: Bind),+> Bind for ($($type,)+) {
362 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
363 let mut next_index = start_index;
364 let ($($local,)+) = self;
365 $(next_index = $local.bind(statement, next_index)?;)+
366 Ok(next_index)
367 }
368 }
369
370 impl<$($type: Column),+> Column for ($($type,)+) {
371 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
372 let mut next_index = start_index;
373 Ok((
374 (
375 $({
376 let value;
377 (value, next_index) = $type::column(statement, next_index)?;
378 value
379 },)+
380 ),
381 next_index,
382 ))
383 }
384 }
385 }
386}
387
388impl_tuple_row_traits!(t1: T1, t2: T2);
389impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3);
390impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4);
391impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5);
392impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6);
393impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7);
394impl_tuple_row_traits!(
395 t1: T1,
396 t2: T2,
397 t3: T3,
398 t4: T4,
399 t5: T5,
400 t6: T6,
401 t7: T7,
402 t8: T8
403);
404impl_tuple_row_traits!(
405 t1: T1,
406 t2: T2,
407 t3: T3,
408 t4: T4,
409 t5: T5,
410 t6: T6,
411 t7: T7,
412 t8: T8,
413 t9: T9
414);
415impl_tuple_row_traits!(
416 t1: T1,
417 t2: T2,
418 t3: T3,
419 t4: T4,
420 t5: T5,
421 t6: T6,
422 t7: T7,
423 t8: T8,
424 t9: T9,
425 t10: T10
426);