1use crate::error::{QueryError, Result};
6use chrono::{DateTime, Utc};
7use std::collections::HashMap;
8use uuid::Uuid;
9
10#[derive(Debug, Clone)]
14pub struct QueryResult {
15 pub rows: Vec<Row>,
17
18 pub affected_rows: usize,
20}
21
22impl QueryResult {
23 pub fn new() -> Self {
25 Self {
26 rows: Vec::new(),
27 affected_rows: 0,
28 }
29 }
30
31 pub fn with_rows(rows: Vec<Row>) -> Self {
33 Self {
34 rows,
35 affected_rows: 0,
36 }
37 }
38
39 pub fn with_affected_rows(affected_rows: usize) -> Self {
41 Self {
42 rows: Vec::new(),
43 affected_rows,
44 }
45 }
46
47 pub fn len(&self) -> usize {
49 self.rows.len()
50 }
51
52 pub fn is_empty(&self) -> bool {
54 self.rows.is_empty()
55 }
56
57 pub fn one(self) -> Result<Row> {
59 match self.rows.len() {
60 0 => Err(QueryError::RowNotFound),
61 1 => Ok(self.rows.into_iter().next().unwrap()),
62 n => Err(QueryError::MultipleRowsFound { count: n }),
63 }
64 }
65
66 pub fn optional(self) -> Result<Option<Row>> {
68 match self.rows.len() {
69 0 => Ok(None),
70 1 => Ok(Some(self.rows.into_iter().next().unwrap())),
71 n => Err(QueryError::MultipleRowsFound { count: n }),
72 }
73 }
74
75 pub fn all(self) -> Vec<Row> {
77 self.rows
78 }
79
80 pub fn iter(&self) -> impl Iterator<Item = &Row> {
82 self.rows.iter()
83 }
84}
85
86impl Default for QueryResult {
87 fn default() -> Self {
88 Self::new()
89 }
90}
91
92impl IntoIterator for QueryResult {
93 type Item = Row;
94 type IntoIter = std::vec::IntoIter<Row>;
95
96 fn into_iter(self) -> Self::IntoIter {
97 self.rows.into_iter()
98 }
99}
100
101#[derive(Debug, Clone, PartialEq)]
105pub struct Row {
106 columns: HashMap<String, Value>,
108}
109
110impl Row {
111 pub fn new() -> Self {
113 Self {
114 columns: HashMap::new(),
115 }
116 }
117
118 pub fn from_map(columns: HashMap<String, Value>) -> Self {
120 Self { columns }
121 }
122
123 pub fn get(&self, column: &str) -> Option<&Value> {
125 self.columns.get(column)
126 }
127
128 pub fn get_required(&self, column: &str) -> Result<&Value> {
130 self.columns
131 .get(column)
132 .ok_or_else(|| QueryError::missing_field(column))
133 }
134
135 pub fn insert(&mut self, column: String, value: Value) {
137 self.columns.insert(column, value);
138 }
139
140 pub fn has_column(&self, column: &str) -> bool {
142 self.columns.contains_key(column)
143 }
144
145 pub fn columns(&self) -> Vec<&str> {
147 self.columns.keys().map(|s| s.as_str()).collect()
148 }
149
150 pub fn len(&self) -> usize {
152 self.columns.len()
153 }
154
155 pub fn is_empty(&self) -> bool {
157 self.columns.is_empty()
158 }
159}
160
161impl Default for Row {
162 fn default() -> Self {
163 Self::new()
164 }
165}
166
167#[derive(Debug, Clone, PartialEq)]
171pub enum Value {
172 Null,
174
175 Bool(bool),
177
178 Integer(i64),
180
181 Float(f64),
183
184 String(String),
186
187 Uuid(Uuid),
189
190 Timestamp(DateTime<Utc>),
192
193 Bytes(Vec<u8>),
195
196 Array(Vec<Value>),
198
199 Object(HashMap<String, Value>),
201}
202
203impl Value {
204 pub fn is_null(&self) -> bool {
206 matches!(self, Value::Null)
207 }
208
209 pub fn as_bool(&self) -> Result<bool> {
211 match self {
212 Value::Bool(b) => Ok(*b),
213 _ => Err(QueryError::type_mismatch("Bool", self.type_name())),
214 }
215 }
216
217 pub fn as_i64(&self) -> Result<i64> {
219 match self {
220 Value::Integer(i) => Ok(*i),
221 _ => Err(QueryError::type_mismatch("Integer", self.type_name())),
222 }
223 }
224
225 pub fn as_f64(&self) -> Result<f64> {
227 match self {
228 Value::Float(f) => Ok(*f),
229 Value::Integer(i) => Ok(*i as f64),
230 _ => Err(QueryError::type_mismatch("Float", self.type_name())),
231 }
232 }
233
234 pub fn as_str(&self) -> Result<&str> {
236 match self {
237 Value::String(s) => Ok(s.as_str()),
238 _ => Err(QueryError::type_mismatch("String", self.type_name())),
239 }
240 }
241
242 pub fn as_uuid(&self) -> Result<Uuid> {
244 match self {
245 Value::Uuid(u) => Ok(*u),
246 _ => Err(QueryError::type_mismatch("Uuid", self.type_name())),
247 }
248 }
249
250 pub fn as_timestamp(&self) -> Result<DateTime<Utc>> {
252 match self {
253 Value::Timestamp(t) => Ok(*t),
254 _ => Err(QueryError::type_mismatch("Timestamp", self.type_name())),
255 }
256 }
257
258 pub fn as_bytes(&self) -> Result<&Vec<u8>> {
260 match self {
261 Value::Bytes(b) => Ok(b),
262 _ => Err(QueryError::type_mismatch("Bytes", self.type_name())),
263 }
264 }
265
266 pub fn as_array(&self) -> Result<&Vec<Value>> {
268 match self {
269 Value::Array(a) => Ok(a),
270 _ => Err(QueryError::type_mismatch("Array", self.type_name())),
271 }
272 }
273
274 pub fn as_object(&self) -> Result<&HashMap<String, Value>> {
276 match self {
277 Value::Object(o) => Ok(o),
278 _ => Err(QueryError::type_mismatch("Object", self.type_name())),
279 }
280 }
281
282 pub fn type_name(&self) -> &str {
284 match self {
285 Value::Null => "Null",
286 Value::Bool(_) => "Bool",
287 Value::Integer(_) => "Integer",
288 Value::Float(_) => "Float",
289 Value::String(_) => "String",
290 Value::Bytes(_) => "Bytes",
291 Value::Uuid(_) => "Uuid",
292 Value::Timestamp(_) => "Timestamp",
293 Value::Array(_) => "Array",
294 Value::Object(_) => "Object",
295 }
296 }
297}
298
299impl From<bool> for Value {
302 fn from(b: bool) -> Self {
303 Value::Bool(b)
304 }
305}
306
307impl From<i64> for Value {
308 fn from(i: i64) -> Self {
309 Value::Integer(i)
310 }
311}
312
313impl From<i32> for Value {
314 fn from(i: i32) -> Self {
315 Value::Integer(i as i64)
316 }
317}
318
319impl From<f64> for Value {
320 fn from(f: f64) -> Self {
321 Value::Float(f)
322 }
323}
324
325impl From<String> for Value {
326 fn from(s: String) -> Self {
327 Value::String(s)
328 }
329}
330
331impl From<&str> for Value {
332 fn from(s: &str) -> Self {
333 Value::String(s.to_string())
334 }
335}
336
337impl From<Uuid> for Value {
338 fn from(u: Uuid) -> Self {
339 Value::Uuid(u)
340 }
341}
342
343impl From<DateTime<Utc>> for Value {
344 fn from(t: DateTime<Utc>) -> Self {
345 Value::Timestamp(t)
346 }
347}
348
349impl From<Vec<u8>> for Value {
350 fn from(b: Vec<u8>) -> Self {
351 Value::Bytes(b)
352 }
353}
354
355#[cfg(test)]
356mod tests {
357 use super::*;
358
359 #[test]
360 fn test_query_result_new() {
361 let result = QueryResult::new();
362 assert!(result.is_empty());
363 assert_eq!(result.len(), 0);
364 assert_eq!(result.affected_rows, 0);
365 }
366
367 #[test]
368 fn test_query_result_with_rows() {
369 let rows = vec![Row::new(), Row::new()];
370 let result = QueryResult::with_rows(rows);
371 assert_eq!(result.len(), 2);
372 assert!(!result.is_empty());
373 }
374
375 #[test]
376 fn test_query_result_one() {
377 let result = QueryResult::with_rows(vec![Row::new()]);
378 assert!(result.one().is_ok());
379
380 let empty = QueryResult::new();
381 assert!(empty.one().is_err());
382
383 let multiple = QueryResult::with_rows(vec![Row::new(), Row::new()]);
384 assert!(multiple.one().is_err());
385 }
386
387 #[test]
388 fn test_query_result_optional() {
389 let result = QueryResult::new();
390 assert_eq!(result.optional().unwrap(), None);
391
392 let one = QueryResult::with_rows(vec![Row::new()]);
393 assert!(one.optional().unwrap().is_some());
394
395 let multiple = QueryResult::with_rows(vec![Row::new(), Row::new()]);
396 assert!(multiple.optional().is_err());
397 }
398
399 #[test]
400 fn test_row_operations() {
401 let mut row = Row::new();
402 assert!(row.is_empty());
403
404 row.insert("id".to_string(), Value::Integer(1));
405 row.insert("name".to_string(), Value::String("Alice".to_string()));
406
407 assert_eq!(row.len(), 2);
408 assert!(row.get("id").is_some());
409 assert!(row.get("name").is_some());
410 assert!(row.get("missing").is_none());
411 }
412
413 #[test]
414 fn test_row_get_required() {
415 let mut row = Row::new();
416 row.insert("id".to_string(), Value::Integer(1));
417
418 assert!(row.get_required("id").is_ok());
419 assert!(row.get_required("missing").is_err());
420 }
421
422 #[test]
423 fn test_value_types() {
424 assert!(Value::Null.is_null());
425 assert!(!Value::Bool(true).is_null());
426
427 let bool_val = Value::Bool(true);
428 assert_eq!(bool_val.as_bool().unwrap(), true);
429
430 let int_val = Value::Integer(42);
431 assert_eq!(int_val.as_i64().unwrap(), 42);
432
433 let float_val = Value::Float(3.14);
434 assert!((float_val.as_f64().unwrap() - 3.14).abs() < 0.01);
435
436 let str_val = Value::String("hello".to_string());
437 assert_eq!(str_val.as_str().unwrap(), "hello");
438 }
439
440 #[test]
441 fn test_value_type_mismatch() {
442 let int_val = Value::Integer(42);
443 assert!(int_val.as_bool().is_err());
444 assert!(int_val.as_str().is_err());
445
446 let str_val = Value::String("hello".to_string());
447 assert!(str_val.as_i64().is_err());
448 }
449
450 #[test]
451 fn test_value_type_name() {
452 assert_eq!(Value::Null.type_name(), "Null");
453 assert_eq!(Value::Bool(true).type_name(), "Bool");
454 assert_eq!(Value::Integer(1).type_name(), "Integer");
455 assert_eq!(Value::Float(1.0).type_name(), "Float");
456 assert_eq!(Value::String("".to_string()).type_name(), "String");
457 assert_eq!(Value::Uuid(Uuid::new_v4()).type_name(), "Uuid");
458 }
459
460 #[test]
461 fn test_value_conversions() {
462 let bool_val: Value = true.into();
463 assert!(matches!(bool_val, Value::Bool(true)));
464
465 let int_val: Value = 42i64.into();
466 assert!(matches!(int_val, Value::Integer(42)));
467
468 let str_val: Value = "hello".into();
469 assert!(matches!(str_val, Value::String(_)));
470
471 let uuid = Uuid::new_v4();
472 let uuid_val: Value = uuid.into();
473 assert!(matches!(uuid_val, Value::Uuid(_)));
474 }
475
476 #[test]
477 fn test_value_float_from_int() {
478 let int_val = Value::Integer(42);
479 assert_eq!(int_val.as_f64().unwrap(), 42.0);
480 }
481
482 #[test]
483 fn test_value_array() {
484 let arr = Value::Array(vec![Value::Integer(1), Value::Integer(2)]);
485 let arr_ref = arr.as_array().unwrap();
486 assert_eq!(arr_ref.len(), 2);
487 }
488
489 #[test]
490 fn test_value_object() {
491 let mut map = HashMap::new();
492 map.insert("key".to_string(), Value::String("value".to_string()));
493 let obj = Value::Object(map);
494 let obj_ref = obj.as_object().unwrap();
495 assert_eq!(obj_ref.len(), 1);
496 }
497}