sql_middleware/sqlite/
params.rs1use std::fmt::Write;
2
3use rusqlite;
4
5use crate::middleware::{ConversionMode, ParamConverter, RowValues, SqlMiddlewareDbError};
6
7thread_local! {
9 static TIMESTAMP_BUF: std::cell::RefCell<String> = std::cell::RefCell::new(String::with_capacity(32));
10}
11
12#[must_use]
14pub fn row_value_to_sqlite_value(value: &RowValues, for_execute: bool) -> rusqlite::types::Value {
15 match value {
16 RowValues::Int(i) => rusqlite::types::Value::Integer(*i),
17 RowValues::Float(f) => rusqlite::types::Value::Real(*f),
18 RowValues::Text(s) => {
19 if for_execute {
20 rusqlite::types::Value::Text(s.clone())
22 } else {
23 rusqlite::types::Value::Text(s.clone())
25 }
26 }
27 RowValues::Bool(b) => rusqlite::types::Value::Integer(i64::from(*b)),
28 RowValues::Timestamp(dt) => {
30 TIMESTAMP_BUF.with(|buf| {
32 let mut borrow = buf.borrow_mut();
33 borrow.clear();
34 write!(borrow, "{}", dt.format("%F %T%.f")).unwrap();
36 rusqlite::types::Value::Text(borrow.clone())
37 })
38 }
39 RowValues::Null => rusqlite::types::Value::Null,
40 RowValues::JSON(jval) => {
41 let json_str = jval.to_string();
43 rusqlite::types::Value::Text(json_str)
44 }
45 RowValues::Blob(bytes) => {
46 if for_execute {
47 rusqlite::types::Value::Blob(bytes.clone())
49 } else {
50 rusqlite::types::Value::Blob(bytes.clone())
51 }
52 }
53 }
54}
55
56pub struct Params(pub Vec<rusqlite::types::Value>);
58
59impl Params {
60 pub fn convert(params: &[RowValues]) -> Result<Self, SqlMiddlewareDbError> {
66 let mut vec_values = Vec::with_capacity(params.len());
67 for p in params {
68 vec_values.push(row_value_to_sqlite_value(p, true));
69 }
70 Ok(Params(vec_values))
71 }
72
73 #[must_use]
75 pub fn as_values(&self) -> &[rusqlite::types::Value] {
76 &self.0
77 }
78
79 #[must_use]
81 pub fn as_refs(&self) -> Vec<&dyn rusqlite::ToSql> {
82 self.0.iter().map(|v| v as &dyn rusqlite::ToSql).collect()
83 }
84}
85
86#[derive(Debug, Clone, Default)]
92pub struct SqliteParamsBuf {
93 values: Vec<rusqlite::types::Value>,
94}
95
96impl SqliteParamsBuf {
97 #[must_use]
99 pub fn with_capacity(capacity: usize) -> Self {
100 Self {
101 values: Vec::with_capacity(capacity),
102 }
103 }
104
105 pub fn clear(&mut self) {
107 self.values.clear();
108 }
109
110 #[must_use]
112 pub fn len(&self) -> usize {
113 self.values.len()
114 }
115
116 #[must_use]
118 pub fn is_empty(&self) -> bool {
119 self.values.is_empty()
120 }
121
122 #[must_use]
124 pub fn as_values(&self) -> &[rusqlite::types::Value] {
125 &self.values
126 }
127
128 pub fn set_int(&mut self, index: usize, value: i64) {
130 self.set_value(index, rusqlite::types::Value::Integer(value));
131 }
132
133 pub fn set_float(&mut self, index: usize, value: f64) {
135 self.set_value(index, rusqlite::types::Value::Real(value));
136 }
137
138 pub fn set_text(&mut self, index: usize, value: impl Into<String>) {
140 self.set_value(index, rusqlite::types::Value::Text(value.into()));
141 }
142
143 pub fn set_bool(&mut self, index: usize, value: bool) {
145 self.set_value(index, rusqlite::types::Value::Integer(i64::from(value)));
146 }
147
148 pub fn set_timestamp(&mut self, index: usize, value: chrono::NaiveDateTime) {
150 self.set_value(
151 index,
152 row_value_to_sqlite_value(&RowValues::Timestamp(value), true),
153 );
154 }
155
156 pub fn set_json(&mut self, index: usize, value: serde_json::Value) {
158 self.set_value(index, rusqlite::types::Value::Text(value.to_string()));
159 }
160
161 pub fn set_blob(&mut self, index: usize, value: impl Into<Vec<u8>>) {
163 self.set_value(index, rusqlite::types::Value::Blob(value.into()));
164 }
165
166 pub fn set_null(&mut self, index: usize) {
168 self.set_value(index, rusqlite::types::Value::Null);
169 }
170
171 fn set_value(&mut self, index: usize, value: rusqlite::types::Value) {
172 if self.values.len() <= index {
173 self.values
174 .resize_with(index + 1, || rusqlite::types::Value::Null);
175 }
176 self.values[index] = value;
177 }
178}
179
180impl ParamConverter<'_> for Params {
181 type Converted = Params;
182
183 fn convert_sql_params(
184 params: &[RowValues],
185 _mode: ConversionMode,
186 ) -> Result<Self::Converted, SqlMiddlewareDbError> {
187 Self::convert(params)
188 }
189
190 fn supports_mode(mode: ConversionMode) -> bool {
191 matches!(mode, ConversionMode::Query | ConversionMode::Execute)
193 }
194}