1use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17pub enum Value {
18 Null,
19 Bool(bool),
20 Int(i64),
21 Float(f64),
22 String(String),
23 Bytes(Vec<u8>),
24 Array(Vec<Value>),
25 Object(HashMap<String, Value>),
26 Timestamp(i64),
27}
28
29impl Value {
30 pub fn is_null(&self) -> bool {
32 matches!(self, Self::Null)
33 }
34
35 pub fn as_bool(&self) -> Option<bool> {
37 match self {
38 Self::Bool(b) => Some(*b),
39 _ => None,
40 }
41 }
42
43 pub fn as_int(&self) -> Option<i64> {
45 match self {
46 Self::Int(i) => Some(*i),
47 Self::Float(f) => Some(*f as i64),
48 _ => None,
49 }
50 }
51
52 pub fn as_float(&self) -> Option<f64> {
54 match self {
55 Self::Float(f) => Some(*f),
56 Self::Int(i) => Some(*i as f64),
57 _ => None,
58 }
59 }
60
61 pub fn as_str(&self) -> Option<&str> {
63 match self {
64 Self::String(s) => Some(s),
65 _ => None,
66 }
67 }
68
69 pub fn as_bytes(&self) -> Option<&[u8]> {
71 match self {
72 Self::Bytes(b) => Some(b),
73 _ => None,
74 }
75 }
76
77 pub fn as_array(&self) -> Option<&[Value]> {
79 match self {
80 Self::Array(a) => Some(a),
81 _ => None,
82 }
83 }
84
85 pub fn as_object(&self) -> Option<&HashMap<String, Value>> {
87 match self {
88 Self::Object(o) => Some(o),
89 _ => None,
90 }
91 }
92}
93
94impl From<bool> for Value {
95 fn from(v: bool) -> Self {
96 Self::Bool(v)
97 }
98}
99
100impl From<i32> for Value {
101 fn from(v: i32) -> Self {
102 Self::Int(v as i64)
103 }
104}
105
106impl From<i64> for Value {
107 fn from(v: i64) -> Self {
108 Self::Int(v)
109 }
110}
111
112impl From<f64> for Value {
113 fn from(v: f64) -> Self {
114 Self::Float(v)
115 }
116}
117
118impl From<String> for Value {
119 fn from(v: String) -> Self {
120 Self::String(v)
121 }
122}
123
124impl From<&str> for Value {
125 fn from(v: &str) -> Self {
126 Self::String(v.to_string())
127 }
128}
129
130impl From<Vec<u8>> for Value {
131 fn from(v: Vec<u8>) -> Self {
132 Self::Bytes(v)
133 }
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct Column {
143 pub name: String,
144 pub data_type: DataType,
145 pub nullable: bool,
146}
147
148impl Column {
149 pub fn new(name: impl Into<String>, data_type: DataType) -> Self {
150 Self {
151 name: name.into(),
152 data_type,
153 nullable: true,
154 }
155 }
156}
157
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
164pub enum DataType {
165 Boolean,
166 Integer,
167 BigInt,
168 Float,
169 Double,
170 Text,
171 Varchar,
172 Blob,
173 Timestamp,
174 Date,
175 Time,
176 Json,
177 Array,
178 Unknown,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct Row {
188 columns: Vec<String>,
189 values: Vec<Value>,
190}
191
192impl Row {
193 pub fn new(columns: Vec<String>, values: Vec<Value>) -> Self {
195 Self { columns, values }
196 }
197
198 pub fn get(&self, index: usize) -> Option<&Value> {
200 self.values.get(index)
201 }
202
203 pub fn get_by_name(&self, name: &str) -> Option<&Value> {
205 let index = self.columns.iter().position(|c| c == name)?;
206 self.values.get(index)
207 }
208
209 pub fn len(&self) -> usize {
211 self.values.len()
212 }
213
214 pub fn is_empty(&self) -> bool {
216 self.values.is_empty()
217 }
218
219 pub fn columns(&self) -> &[String] {
221 &self.columns
222 }
223
224 pub fn values(&self) -> &[Value] {
226 &self.values
227 }
228
229 pub fn get_bool(&self, index: usize) -> Option<bool> {
231 self.get(index).and_then(|v| v.as_bool())
232 }
233
234 pub fn get_int(&self, index: usize) -> Option<i64> {
236 self.get(index).and_then(|v| v.as_int())
237 }
238
239 pub fn get_float(&self, index: usize) -> Option<f64> {
241 self.get(index).and_then(|v| v.as_float())
242 }
243
244 pub fn get_str(&self, index: usize) -> Option<&str> {
246 self.get(index).and_then(|v| v.as_str())
247 }
248
249 pub fn to_map(&self) -> HashMap<String, Value> {
251 self.columns
252 .iter()
253 .zip(self.values.iter())
254 .map(|(k, v)| (k.clone(), v.clone()))
255 .collect()
256 }
257}
258
259impl IntoIterator for Row {
260 type Item = Value;
261 type IntoIter = std::vec::IntoIter<Value>;
262
263 fn into_iter(self) -> Self::IntoIter {
264 self.values.into_iter()
265 }
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct QueryResult {
275 columns: Vec<Column>,
276 rows: Vec<Row>,
277 rows_affected: u64,
278 execution_time_ms: u64,
279}
280
281impl QueryResult {
282 pub fn new(columns: Vec<Column>, rows: Vec<Row>) -> Self {
284 Self {
285 columns,
286 rows,
287 rows_affected: 0,
288 execution_time_ms: 0,
289 }
290 }
291
292 pub fn empty() -> Self {
294 Self {
295 columns: Vec::new(),
296 rows: Vec::new(),
297 rows_affected: 0,
298 execution_time_ms: 0,
299 }
300 }
301
302 pub fn affected(rows_affected: u64) -> Self {
304 Self {
305 columns: Vec::new(),
306 rows: Vec::new(),
307 rows_affected,
308 execution_time_ms: 0,
309 }
310 }
311
312 pub fn with_execution_time(mut self, ms: u64) -> Self {
314 self.execution_time_ms = ms;
315 self
316 }
317
318 pub fn columns(&self) -> &[Column] {
320 &self.columns
321 }
322
323 pub fn rows(&self) -> &[Row] {
325 &self.rows
326 }
327
328 pub fn row_count(&self) -> usize {
330 self.rows.len()
331 }
332
333 pub fn rows_affected(&self) -> u64 {
335 self.rows_affected
336 }
337
338 pub fn execution_time_ms(&self) -> u64 {
340 self.execution_time_ms
341 }
342
343 pub fn is_empty(&self) -> bool {
345 self.rows.is_empty()
346 }
347
348 pub fn first(&self) -> Option<&Row> {
350 self.rows.first()
351 }
352
353 pub fn scalar(&self) -> Option<&Value> {
355 self.first().and_then(|r| r.get(0))
356 }
357
358 pub fn iter(&self) -> impl Iterator<Item = &Row> {
360 self.rows.iter()
361 }
362}
363
364impl IntoIterator for QueryResult {
365 type Item = Row;
366 type IntoIter = std::vec::IntoIter<Row>;
367
368 fn into_iter(self) -> Self::IntoIter {
369 self.rows.into_iter()
370 }
371}
372
373#[cfg(test)]
378mod tests {
379 use super::*;
380
381 #[test]
382 fn test_value_types() {
383 let v = Value::Int(42);
384 assert_eq!(v.as_int(), Some(42));
385 assert_eq!(v.as_float(), Some(42.0));
386
387 let v = Value::String("hello".to_string());
388 assert_eq!(v.as_str(), Some("hello"));
389
390 let v = Value::Null;
391 assert!(v.is_null());
392 }
393
394 #[test]
395 fn test_value_from() {
396 let v: Value = 42i32.into();
397 assert_eq!(v, Value::Int(42));
398
399 let v: Value = "hello".into();
400 assert_eq!(v, Value::String("hello".to_string()));
401
402 let v: Value = true.into();
403 assert_eq!(v, Value::Bool(true));
404 }
405
406 #[test]
407 fn test_row() {
408 let columns = vec!["id".to_string(), "name".to_string()];
409 let values = vec![Value::Int(1), Value::String("Alice".to_string())];
410 let row = Row::new(columns, values);
411
412 assert_eq!(row.len(), 2);
413 assert_eq!(row.get_int(0), Some(1));
414 assert_eq!(row.get_str(1), Some("Alice"));
415 assert_eq!(
416 row.get_by_name("name"),
417 Some(&Value::String("Alice".to_string()))
418 );
419 }
420
421 #[test]
422 fn test_row_to_map() {
423 let columns = vec!["a".to_string(), "b".to_string()];
424 let values = vec![Value::Int(1), Value::Int(2)];
425 let row = Row::new(columns, values);
426
427 let map = row.to_map();
428 assert_eq!(map.get("a"), Some(&Value::Int(1)));
429 assert_eq!(map.get("b"), Some(&Value::Int(2)));
430 }
431
432 #[test]
433 fn test_query_result() {
434 let columns = vec![Column::new("id", DataType::Integer)];
435 let rows = vec![
436 Row::new(vec!["id".to_string()], vec![Value::Int(1)]),
437 Row::new(vec!["id".to_string()], vec![Value::Int(2)]),
438 ];
439
440 let result = QueryResult::new(columns, rows);
441 assert_eq!(result.row_count(), 2);
442 assert_eq!(result.scalar(), Some(&Value::Int(1)));
443 }
444
445 #[test]
446 fn test_query_result_affected() {
447 let result = QueryResult::affected(5);
448 assert_eq!(result.rows_affected(), 5);
449 assert!(result.is_empty());
450 }
451}