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