sqlx_build_trust_sqlite/
arguments.rs1use crate::encode::{Encode, IsNull};
2use crate::error::Error;
3use crate::statement::StatementHandle;
4use crate::Sqlite;
5use atoi::atoi;
6use libsqlite3_sys::SQLITE_OK;
7use std::borrow::Cow;
8
9pub(crate) use sqlx_core::arguments::*;
10
11#[derive(Debug, Clone)]
12pub enum SqliteArgumentValue<'q> {
13 Null,
14 Text(Cow<'q, str>),
15 Blob(Cow<'q, [u8]>),
16 Double(f64),
17 Int(i32),
18 Int64(i64),
19}
20
21#[derive(Default, Debug, Clone)]
22pub struct SqliteArguments<'q> {
23 pub(crate) values: Vec<SqliteArgumentValue<'q>>,
24}
25
26impl<'q> SqliteArguments<'q> {
27 pub(crate) fn add<T>(&mut self, value: T)
28 where
29 T: Encode<'q, Sqlite>,
30 {
31 if let IsNull::Yes = value.encode(&mut self.values) {
32 self.values.push(SqliteArgumentValue::Null);
33 }
34 }
35
36 pub(crate) fn into_static(self) -> SqliteArguments<'static> {
37 SqliteArguments {
38 values: self
39 .values
40 .into_iter()
41 .map(SqliteArgumentValue::into_static)
42 .collect(),
43 }
44 }
45}
46
47impl<'q> Arguments<'q> for SqliteArguments<'q> {
48 type Database = Sqlite;
49
50 fn reserve(&mut self, len: usize, _size_hint: usize) {
51 self.values.reserve(len);
52 }
53
54 fn add<T>(&mut self, value: T)
55 where
56 T: Encode<'q, Self::Database>,
57 {
58 self.add(value)
59 }
60}
61
62impl SqliteArguments<'_> {
63 pub(super) fn bind(&self, handle: &mut StatementHandle, offset: usize) -> Result<usize, Error> {
64 let mut arg_i = offset;
65 let cnt = handle.bind_parameter_count();
68
69 for param_i in 1..=cnt {
70 let n: usize = if let Some(name) = handle.bind_parameter_name(param_i) {
72 if let Some(name) = name.strip_prefix('?') {
73 atoi(name.as_bytes()).expect("parameter of the form ?NNN")
75 } else if let Some(name) = name.strip_prefix('$') {
76 atoi(name.as_bytes()).ok_or_else(|| {
78 err_protocol!(
79 "parameters with non-integer names are not currently supported: {}",
80 name
81 )
82 })?
83 } else {
84 return Err(err_protocol!("unsupported SQL parameter format: {}", name));
85 }
86 } else {
87 arg_i += 1;
88 arg_i
89 };
90
91 if n > self.values.len() {
92 break;
99 }
100
101 self.values[n - 1].bind(handle, param_i)?;
102 }
103
104 Ok(arg_i - offset)
105 }
106}
107
108impl SqliteArgumentValue<'_> {
109 fn into_static(self) -> SqliteArgumentValue<'static> {
110 use SqliteArgumentValue::*;
111
112 match self {
113 Null => Null,
114 Text(text) => Text(text.into_owned().into()),
115 Blob(blob) => Blob(blob.into_owned().into()),
116 Int(v) => Int(v),
117 Int64(v) => Int64(v),
118 Double(v) => Double(v),
119 }
120 }
121
122 fn bind(&self, handle: &mut StatementHandle, i: usize) -> Result<(), Error> {
123 use SqliteArgumentValue::*;
124
125 let status = match self {
126 Text(v) => handle.bind_text(i, v),
127 Blob(v) => handle.bind_blob(i, v),
128 Int(v) => handle.bind_int(i, *v),
129 Int64(v) => handle.bind_int64(i, *v),
130 Double(v) => handle.bind_double(i, *v),
131 Null => handle.bind_null(i),
132 };
133
134 if status != SQLITE_OK {
135 return Err(handle.last_error().into());
136 }
137
138 Ok(())
139 }
140}