1use serde::Serialize;
2use serde_json;
3
4pub mod arguments;
5use crate::error::QueryBuilderError;
6pub(crate) use arguments::RqliteArgument;
7
8#[derive(Debug)]
10pub struct RqliteQuery {
11 pub query: String,
12 pub args: Vec<RqliteArgument>,
13 pub op: Operation,
14}
15
16impl TryInto<RqliteQuery> for String {
17 type Error = QueryBuilderError;
18
19 fn try_into(self) -> Result<RqliteQuery, Self::Error> {
24 let op = Operation::from_query_string(self.as_str())?;
25
26 Ok(RqliteQuery {
27 query: self,
28 args: vec![],
29 op,
30 })
31 }
32}
33
34impl TryInto<RqliteQuery> for &str {
35 type Error = QueryBuilderError;
36
37 fn try_into(self) -> Result<RqliteQuery, Self::Error> {
42 let op = Operation::from_query_string(self)?;
43
44 Ok(RqliteQuery {
45 query: self.to_string(),
46 args: vec![],
47 op,
48 })
49 }
50}
51
52impl TryInto<RqliteQuery> for Result<RqliteQuery, QueryBuilderError> {
53 type Error = QueryBuilderError;
54
55 fn try_into(self) -> Result<RqliteQuery, Self::Error> {
60 self
61 }
62}
63
64#[derive(Serialize, Debug)]
65struct QueryComponent(RqliteArgument);
66
67#[derive(Serialize, Debug)]
69pub(crate) struct QueryArgs(Vec<Vec<QueryComponent>>);
70
71impl From<RqliteQuery> for QueryArgs {
74 fn from(query: RqliteQuery) -> Self {
75 let mut args = Vec::new();
76
77 let mut components = Vec::new();
78
79 components.push(QueryComponent(RqliteArgument::String(query.query)));
80
81 for arg in query.args {
82 components.push(QueryComponent(arg));
83 }
84
85 args.push(components);
86
87 Self(args)
88 }
89}
90
91impl From<Vec<RqliteQuery>> for QueryArgs {
94 fn from(queries: Vec<RqliteQuery>) -> Self {
95 let mut args = Vec::new();
96
97 for query in queries {
98 let mut components = Vec::new();
99
100 components.push(QueryComponent(RqliteArgument::String(query.query)));
101
102 for arg in query.args {
103 components.push(QueryComponent(arg));
104 }
105
106 args.push(components);
107 }
108
109 Self(args)
110 }
111}
112
113impl RqliteQuery {
114 pub(crate) fn into_json(self) -> Result<String, serde_json::Error> {
115 let args = QueryArgs::from(self);
116
117 serde_json::to_string(&args)
118 }
119
120 pub(crate) fn endpoint(&self) -> String {
121 let resource = match self.op {
122 Operation::Create
123 | Operation::Update
124 | Operation::Delete
125 | Operation::Insert
126 | Operation::Drop => "execute",
127 Operation::Select | Operation::Pragma => "query",
128 };
129
130 format!("db/{resource}")
131 }
132}
133
134#[derive(Debug, PartialEq, Eq)]
136pub enum Operation {
137 Create,
138 Select,
139 Update,
140 Delete,
141 Insert,
142 Pragma,
143 Drop,
144}
145
146impl Operation {
147 pub fn from_query_string(query: &str) -> Result<Self, QueryBuilderError> {
152 match query.to_lowercase() {
153 q if q.starts_with("create") => Ok(Self::Create),
154 q if q.starts_with("select") => Ok(Self::Select),
155 q if q.starts_with("update") => Ok(Self::Update),
156 q if q.starts_with("delete") => Ok(Self::Delete),
157 q if q.starts_with("insert") => Ok(Self::Insert),
158 q if q.starts_with("pragma") => Ok(Self::Pragma),
159 q if q.starts_with("drop") => Ok(Self::Drop),
160 _ => Err(QueryBuilderError::InvalidOperation(query.to_string())),
161 }
162 }
163}
164
165#[macro_export]
181macro_rules! query {
182 ( $query:expr ) => {{
185 'blk: {
186 let Ok(op) = $crate::query::Operation::from_query_string($query) else { break 'blk Err($crate::error::QueryBuilderError::InvalidQuery($query.to_string())) };
187
188 Ok($crate::query::RqliteQuery {
189 query: $query.to_string(),
190 args: vec![],
191 op,
192 })
193 }
194 }};
195 ( $query:expr, $( $args:expr ),* ) => {{
196 'blk: {
197 let Ok(query) = ($crate::query!($query)) else {
198 break 'blk Err($crate::error::QueryBuilderError::InvalidQuery($query.to_string()));
199 };
200
201 let param_count = $query.matches("?").count();
202
203 let mut args = vec![];
204
205 $(
206 let arg = $crate::arg!($args);
207 args.push(arg);
208 )*
209
210 let argc = args.len();
211
212 if argc != param_count {
213 break 'blk Err($crate::error::QueryBuilderError::InvalidArgumentCount(param_count, argc));
214 }
215
216 Ok($crate::query::RqliteQuery {
217 query: query.query,
218 args,
219 op: query.op,
220 })
221 }
222 }};
223}
224
225#[cfg(test)]
226mod tests {
227 use crate::query::QueryArgs;
228
229 #[test]
231 fn unit_query_macro_correct_query_types() {
232 let query = query!("CREATE TABLE foo (id INTEGER PRIMARY KEY)");
233 assert!(query.is_ok());
234 assert_eq!(query.unwrap().op, crate::query::Operation::Create);
235
236 let query = query!("SELECT * FROM foo");
237 assert!(query.is_ok());
238 assert_eq!(query.unwrap().op, crate::query::Operation::Select);
239
240 let query = query!("UPDATE foo SET name = 'bar' WHERE id = 1");
241 assert!(query.is_ok());
242 assert_eq!(query.unwrap().op, crate::query::Operation::Update);
243
244 let query = query!("DELETE FROM foo WHERE id = 1");
245 assert!(query.is_ok());
246 assert_eq!(query.unwrap().op, crate::query::Operation::Delete);
247
248 let query = query!("INSERT INTO foo (name) VALUES ('bar')");
249 assert!(query.is_ok());
250 assert_eq!(query.unwrap().op, crate::query::Operation::Insert);
251
252 let query = query!("PRAGMA table_info(foo)");
253 assert!(query.is_ok());
254 assert_eq!(query.unwrap().op, crate::query::Operation::Pragma);
255
256 let query = query!("DROP TABLE foo");
257 assert!(query.is_ok());
258 assert_eq!(query.unwrap().op, crate::query::Operation::Drop);
259 }
260
261 #[test]
262 fn unit_query_macro_incorrect_query_types() {
263 let query = query!("TEST * FROM foo");
264 assert!(query.is_err());
265 }
266
267 #[test]
268 fn unit_query_macro_query_args() {
269 let query = query!("SELECT * FROM foo WHERE id = ?", 1i64);
270 assert!(query.is_ok());
271 assert_eq!(query.unwrap().args.len(), 1);
272
273 let query = query!("SELECT * FROM foo WHERE id = ?", 1i64, "foo");
274 assert!(query.is_err());
275 assert!(matches!(
276 query.unwrap_err(),
277 crate::error::QueryBuilderError::InvalidArgumentCount(1, 2)
278 ));
279 }
280
281 #[test]
282 fn unit_query_macro_try_into_from_string_slice() {
283 let query: Result<crate::query::RqliteQuery, crate::error::QueryBuilderError> =
284 "SELECT * FROM foo".try_into();
285 assert!(query.is_ok());
286 assert_eq!(query.unwrap().op, crate::query::Operation::Select);
287 }
288
289 #[test]
290 fn unit_query_macro_try_into_from_string() {
291 let query: Result<crate::query::RqliteQuery, crate::error::QueryBuilderError> =
292 "SELECT * FROM foo".to_string().try_into();
293 assert!(query.is_ok());
294 assert_eq!(query.unwrap().op, crate::query::Operation::Select);
295 }
296
297 #[test]
298 fn unit_query_macro_try_into_from_result_err() {
299 let query: Result<crate::query::RqliteQuery, crate::error::QueryBuilderError> = Err(
300 crate::error::QueryBuilderError::InvalidQuery("TEST * FROM foo".to_string()),
301 )
302 .try_into();
303 assert!(query.is_err());
304 }
305
306 #[test]
307 fn unit_query_macro_query_args_from_query() {
308 let query = query!("SELECT * FROM foo WHERE id = ?", 1i64);
309 assert!(query.is_ok());
310
311 let query_args = QueryArgs::from(query.unwrap());
312 assert_eq!(query_args.0.len(), 1);
313 assert_eq!(query_args.0[0].len(), 2);
314 }
315
316 #[test]
317 fn unit_query_macro_query_args_from_query_vec() {
318 let query_1 = query!("SELECT * FROM foo WHERE id = ?", 1i64);
319 let query_2 = query!("SELECT * FROM foo WHERE id = ?", 2i64);
320 assert!(query_1.is_ok());
321 assert!(query_2.is_ok());
322
323 let query_args = QueryArgs::from(vec![query_1.unwrap(), query_2.unwrap()]);
324 assert_eq!(query_args.0.len(), 2);
325 assert_eq!(query_args.0[0].len(), 2);
326 assert_eq!(query_args.0[1].len(), 2);
327 }
328
329 #[test]
330 fn unit_query_macro_query_to_json() {
331 let query = query!("SELECT * FROM foo WHERE id = ?", 1i64);
332 assert!(query.is_ok());
333
334 let json = query.unwrap().into_json();
335 assert_eq!(json.unwrap(), r#"[["SELECT * FROM foo WHERE id = ?",1]]"#);
336 }
337
338 #[test]
339 fn unit_query_macro_query_endpoint() {
340 let query = query!("SELECT * FROM foo WHERE id = ?", 1i64);
341 assert!(query.is_ok());
342
343 let endpoint = query.unwrap().endpoint();
344 assert_eq!(endpoint, "db/query");
345 }
346}