mockforge_vbr/
database.rs

1//! Virtual database abstraction
2//!
3//! This module provides a virtual database abstraction trait that supports multiple
4//! storage backends: SQLite (persistent, production-like), JSON files (human-readable),
5//! and in-memory (fast, no persistence).
6
7use crate::{Error, Result};
8use async_trait::async_trait;
9use serde_json::Value;
10use sqlx::{Column, Row};
11use std::collections::HashMap;
12use std::sync::Arc;
13use tokio::sync::RwLock;
14
15/// Virtual database abstraction trait
16///
17/// This trait allows the VBR engine to work with different storage backends
18/// transparently, supporting SQLite, JSON files, and in-memory storage.
19#[async_trait]
20pub trait VirtualDatabase: Send + Sync {
21    /// Initialize the database and create necessary tables/schemas
22    async fn initialize(&mut self) -> Result<()>;
23
24    /// Execute a query that returns rows (SELECT)
25    async fn query(&self, query: &str, params: &[Value]) -> Result<Vec<HashMap<String, Value>>>;
26
27    /// Execute a query that modifies data (INSERT, UPDATE, DELETE)
28    async fn execute(&self, query: &str, params: &[Value]) -> Result<u64>;
29
30    /// Execute a query and return the last inserted row ID
31    async fn execute_with_id(&self, query: &str, params: &[Value]) -> Result<String>;
32
33    /// Check if a table exists
34    async fn table_exists(&self, table_name: &str) -> Result<bool>;
35
36    /// Create a table from a CREATE TABLE statement
37    async fn create_table(&self, create_statement: &str) -> Result<()>;
38
39    /// Get database connection information (for debugging)
40    fn connection_info(&self) -> String;
41
42    /// Close the database connection (cleanup)
43    async fn close(&mut self) -> Result<()>;
44}
45
46/// Create a virtual database instance based on the storage backend configuration
47pub async fn create_database(
48    backend: &crate::config::StorageBackend,
49) -> Result<std::sync::Arc<dyn VirtualDatabase + Send + Sync>> {
50    use std::sync::Arc;
51    match backend {
52        crate::config::StorageBackend::Sqlite { path } => {
53            let mut db = SqliteDatabase::new(path.clone()).await?;
54            db.initialize().await?;
55            Ok(Arc::new(db))
56        }
57        crate::config::StorageBackend::Json { path } => {
58            let mut db = JsonDatabase::new(path.clone()).await?;
59            db.initialize().await?;
60            Ok(Arc::new(db))
61        }
62        crate::config::StorageBackend::Memory => {
63            let mut db = InMemoryDatabase::new().await?;
64            db.initialize().await?;
65            Ok(Arc::new(db))
66        }
67    }
68}
69
70/// SQLite database backend implementation
71pub struct SqliteDatabase {
72    pool: sqlx::SqlitePool,
73    path: std::path::PathBuf,
74}
75
76impl SqliteDatabase {
77    /// Create a new SQLite database connection
78    pub async fn new<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
79        let path = path.as_ref().to_path_buf();
80
81        // Ensure parent directory exists
82        if let Some(parent) = path.parent() {
83            tokio::fs::create_dir_all(parent).await.map_err(|e| {
84                Error::generic(format!("Failed to create database directory: {}", e))
85            })?;
86        }
87
88        let db_url = format!("sqlite://{}?mode=rwc", path.display());
89        let pool = sqlx::sqlite::SqlitePoolOptions::new()
90            .max_connections(10)
91            .connect(&db_url)
92            .await
93            .map_err(|e| Error::generic(format!("Failed to connect to SQLite database: {}", e)))?;
94
95        // Enable WAL mode for better concurrency
96        sqlx::query("PRAGMA journal_mode = WAL")
97            .execute(&pool)
98            .await
99            .map_err(|e| Error::generic(format!("Failed to enable WAL mode: {}", e)))?;
100
101        // Enable foreign keys
102        sqlx::query("PRAGMA foreign_keys = ON")
103            .execute(&pool)
104            .await
105            .map_err(|e| Error::generic(format!("Failed to enable foreign keys: {}", e)))?;
106
107        Ok(Self { pool, path })
108    }
109}
110
111#[async_trait]
112impl VirtualDatabase for SqliteDatabase {
113    async fn initialize(&mut self) -> Result<()> {
114        // SQLite databases are initialized on connection
115        // Additional initialization can be done here if needed
116        Ok(())
117    }
118
119    async fn query(&self, query: &str, params: &[Value]) -> Result<Vec<HashMap<String, Value>>> {
120        use sqlx::Row;
121
122        // For now, use a simple approach - bind parameters one by one
123        // This is a simplified implementation; full implementation would handle
124        // parameterized queries more robustly
125        let mut query_builder = sqlx::query(query);
126
127        // Bind parameters based on their type
128        for param in params {
129            query_builder = match param {
130                Value::String(s) => query_builder.bind(s),
131                Value::Number(n) => {
132                    if let Some(i) = n.as_i64() {
133                        query_builder.bind(i)
134                    } else if let Some(f) = n.as_f64() {
135                        query_builder.bind(f)
136                    } else {
137                        query_builder.bind(n.to_string())
138                    }
139                }
140                Value::Bool(b) => query_builder.bind(*b),
141                Value::Null => query_builder.bind::<Option<String>>(None),
142                Value::Array(_) | Value::Object(_) => {
143                    let json_str = serde_json::to_string(param).unwrap_or_default();
144                    query_builder.bind(json_str)
145                }
146            };
147        }
148
149        let rows = query_builder
150            .fetch_all(&self.pool)
151            .await
152            .map_err(|e| Error::generic(format!("Query execution failed: {}", e)))?;
153
154        // Convert rows to HashMap
155        let mut results = Vec::new();
156        for row in rows {
157            let mut map = HashMap::new();
158            let columns = row.columns();
159            for (idx, column) in columns.iter().enumerate() {
160                let value = row_value_to_json(&row, idx)?;
161                map.insert(column.name().to_string(), value);
162            }
163            results.push(map);
164        }
165
166        Ok(results)
167    }
168
169    async fn execute(&self, query: &str, params: &[Value]) -> Result<u64> {
170        // Build query with parameters
171        let mut query_builder = sqlx::query(query);
172
173        // Bind parameters based on their type
174        for param in params {
175            query_builder = match param {
176                Value::String(s) => query_builder.bind(s),
177                Value::Number(n) => {
178                    if let Some(i) = n.as_i64() {
179                        query_builder.bind(i)
180                    } else if let Some(f) = n.as_f64() {
181                        query_builder.bind(f)
182                    } else {
183                        query_builder.bind(n.to_string())
184                    }
185                }
186                Value::Bool(b) => query_builder.bind(*b),
187                Value::Null => query_builder.bind::<Option<String>>(None),
188                Value::Array(_) | Value::Object(_) => {
189                    let json_str = serde_json::to_string(param).unwrap_or_default();
190                    query_builder.bind(json_str)
191                }
192            };
193        }
194
195        let result = query_builder
196            .execute(&self.pool)
197            .await
198            .map_err(|e| Error::generic(format!("Execute failed: {}", e)))?;
199
200        Ok(result.rows_affected())
201    }
202
203    async fn execute_with_id(&self, query: &str, params: &[Value]) -> Result<String> {
204        // Build query with parameters
205        let mut query_builder = sqlx::query(query);
206
207        // Bind parameters based on their type
208        for param in params {
209            query_builder = match param {
210                Value::String(s) => query_builder.bind(s),
211                Value::Number(n) => {
212                    if let Some(i) = n.as_i64() {
213                        query_builder.bind(i)
214                    } else if let Some(f) = n.as_f64() {
215                        query_builder.bind(f)
216                    } else {
217                        query_builder.bind(n.to_string())
218                    }
219                }
220                Value::Bool(b) => query_builder.bind(*b),
221                Value::Null => query_builder.bind::<Option<String>>(None),
222                Value::Array(_) | Value::Object(_) => {
223                    let json_str = serde_json::to_string(param).unwrap_or_default();
224                    query_builder.bind(json_str)
225                }
226            };
227        }
228
229        let result = query_builder
230            .execute(&self.pool)
231            .await
232            .map_err(|e| Error::generic(format!("Execute failed: {}", e)))?;
233
234        // Get last inserted row ID
235        let last_id = result.last_insert_rowid();
236        Ok(last_id.to_string())
237    }
238
239    async fn table_exists(&self, table_name: &str) -> Result<bool> {
240        let query = "SELECT name FROM sqlite_master WHERE type='table' AND name=?";
241        let result = sqlx::query_scalar::<_, String>(query)
242            .bind(table_name)
243            .fetch_optional(&self.pool)
244            .await
245            .map_err(|e| Error::generic(format!("Failed to check table existence: {}", e)))?;
246
247        Ok(result.is_some())
248    }
249
250    async fn create_table(&self, create_statement: &str) -> Result<()> {
251        sqlx::query(create_statement)
252            .execute(&self.pool)
253            .await
254            .map_err(|e| Error::generic(format!("Failed to create table: {}", e)))?;
255
256        Ok(())
257    }
258
259    fn connection_info(&self) -> String {
260        format!("SQLite: {}", self.path.display())
261    }
262
263    async fn close(&mut self) -> Result<()> {
264        self.pool.close().await;
265        Ok(())
266    }
267}
268
269/// Helper function to extract a row value as JSON
270fn row_value_to_json(row: &sqlx::sqlite::SqliteRow, idx: usize) -> Result<Value> {
271    use sqlx::Row;
272
273    // Try to get the value as different types
274    if let Ok(value) = row.try_get::<String, _>(idx) {
275        return Ok(Value::String(value));
276    }
277    if let Ok(value) = row.try_get::<i64, _>(idx) {
278        return Ok(Value::Number(value.into()));
279    }
280    if let Ok(value) = row.try_get::<f64, _>(idx) {
281        if let Some(n) = serde_json::Number::from_f64(value) {
282            return Ok(Value::Number(n));
283        }
284    }
285    if let Ok(value) = row.try_get::<bool, _>(idx) {
286        return Ok(Value::Bool(value));
287    }
288    if let Ok(value) = row.try_get::<Option<String>, _>(idx) {
289        return Ok(value.map(Value::String).unwrap_or(Value::Null));
290    }
291
292    // Default: try to get as string
293    Ok(Value::String(row.get::<String, _>(idx)))
294}
295
296/// JSON file database backend implementation
297pub struct JsonDatabase {
298    path: std::path::PathBuf,
299    data: Arc<RwLock<HashMap<String, Vec<HashMap<String, Value>>>>>,
300}
301
302impl JsonDatabase {
303    /// Create a new JSON database
304    pub async fn new<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
305        let path = path.as_ref().to_path_buf();
306
307        // Load existing data if file exists
308        let data = if path.exists() {
309            let content = tokio::fs::read_to_string(&path)
310                .await
311                .map_err(|e| Error::generic(format!("Failed to read JSON database: {}", e)))?;
312            serde_json::from_str(&content).unwrap_or_default()
313        } else {
314            HashMap::new()
315        };
316
317        Ok(Self {
318            path,
319            data: Arc::new(RwLock::new(data)),
320        })
321    }
322
323    /// Save data to JSON file
324    async fn save(&self) -> Result<()> {
325        let data = self.data.read().await;
326
327        // Ensure parent directory exists
328        if let Some(parent) = self.path.parent() {
329            tokio::fs::create_dir_all(parent).await.map_err(|e| {
330                Error::generic(format!("Failed to create database directory: {}", e))
331            })?;
332        }
333
334        // Serialize the data (not the RwLock wrapper)
335        let content = serde_json::to_string_pretty(&*data)
336            .map_err(|e| Error::generic(format!("Failed to serialize JSON database: {}", e)))?;
337
338        tokio::fs::write(&self.path, content)
339            .await
340            .map_err(|e| Error::generic(format!("Failed to write JSON database: {}", e)))?;
341
342        Ok(())
343    }
344}
345
346#[async_trait]
347impl VirtualDatabase for JsonDatabase {
348    async fn initialize(&mut self) -> Result<()> {
349        // JSON databases don't need schema initialization
350        Ok(())
351    }
352
353    async fn query(&self, query: &str, params: &[Value]) -> Result<Vec<HashMap<String, Value>>> {
354        // Simple SQL-like query parser for JSON backend
355        // This is a basic implementation - for full SQL support, consider using sqlparser crate
356        let data = self.data.read().await;
357        let query_upper = query.trim().to_uppercase();
358
359        // Handle SELECT COUNT(*) queries
360        if query_upper.contains("COUNT(*)") || query_upper.contains("COUNT( * )") {
361            let table_name = extract_table_name_from_select(query)?;
362            if let Some(records) = data.get(table_name) {
363                let count = if query.contains("WHERE") {
364                    apply_json_where_clause(records, query, params)?.len()
365                } else {
366                    records.len()
367                };
368                let mut result = HashMap::new();
369                // Always use "count" as the field name for COUNT(*) queries
370                result.insert("count".to_string(), Value::Number(count.into()));
371                return Ok(vec![result]);
372            }
373        } else if query_upper.starts_with("SELECT") {
374            // Extract table name from query
375            let table_name = extract_table_name_from_select(query)?;
376
377            if let Some(records) = data.get(table_name) {
378                // Apply simple WHERE filtering
379                let filtered = if query.contains("WHERE") {
380                    apply_json_where_clause(records, query, params)?
381                } else {
382                    records.clone()
383                };
384
385                // Apply LIMIT and OFFSET
386                let result = apply_json_pagination(&filtered, query)?;
387                return Ok(result);
388            }
389        } else if query_upper.starts_with("COUNT") {
390            // Handle COUNT queries
391            let table_name = extract_table_name_from_count(query)?;
392            if let Some(records) = data.get(table_name) {
393                let count = if query.contains("WHERE") {
394                    apply_json_where_clause(records, query, params)?.len()
395                } else {
396                    records.len()
397                };
398                let mut result = HashMap::new();
399                result.insert("total".to_string(), Value::Number(count.into()));
400                return Ok(vec![result]);
401            }
402        }
403
404        Ok(vec![])
405    }
406
407    async fn execute(&self, query: &str, params: &[Value]) -> Result<u64> {
408        // Parse INSERT, UPDATE, DELETE queries
409        let query_upper = query.trim().to_uppercase();
410
411        if query_upper.starts_with("INSERT") {
412            {
413                let mut data = self.data.write().await;
414                let (table_name, record) = parse_insert_query(query, params)?;
415                let records = data.entry(table_name).or_insert_with(Vec::new);
416                records.push(record);
417            } // Drop write lock before save
418            self.save().await?;
419            Ok(1)
420        } else if query_upper.starts_with("UPDATE") {
421            let updated = {
422                let mut data = self.data.write().await;
423                let (table_name, updates, where_clause, where_params) =
424                    parse_update_query(query, params)?;
425                if let Some(records) = data.get_mut(&table_name) {
426                    let mut updated = 0;
427                    for record in records.iter_mut() {
428                        if matches_json_where(record, &where_clause, &where_params)? {
429                            record.extend(updates.clone());
430                            updated += 1;
431                        }
432                    }
433                    updated
434                } else {
435                    0
436                }
437            }; // Drop write lock before save
438            if updated > 0 {
439                self.save().await?;
440            }
441            Ok(updated)
442        } else if query_upper.starts_with("DELETE") {
443            let deleted = {
444                let mut data = self.data.write().await;
445                let (table_name, where_clause, where_params) = parse_delete_query(query, params)?;
446                if let Some(records) = data.get_mut(&table_name) {
447                    let initial_len = records.len();
448                    records.retain(|record| {
449                        !matches_json_where(record, &where_clause, &where_params).unwrap_or(false)
450                    });
451                    (initial_len - records.len()) as u64
452                } else {
453                    0
454                }
455            }; // Drop write lock before save
456            if deleted > 0 {
457                self.save().await?;
458            }
459            Ok(deleted)
460        } else {
461            Ok(0)
462        }
463    }
464
465    async fn execute_with_id(&self, query: &str, params: &[Value]) -> Result<String> {
466        // For INSERT, extract the ID from the inserted record
467        if query.trim().to_uppercase().starts_with("INSERT") {
468            let id = {
469                let mut data = self.data.write().await;
470                let (table_name, mut record) = parse_insert_query(query, params)?;
471
472                // Generate ID if not present
473                if !record.contains_key("id") {
474                    use uuid::Uuid;
475                    record.insert("id".to_string(), Value::String(Uuid::new_v4().to_string()));
476                }
477
478                let id = record.get("id").and_then(|v| v.as_str()).unwrap_or("").to_string();
479
480                let records = data.entry(table_name).or_insert_with(Vec::new);
481                records.push(record);
482                id
483            }; // Drop write lock before save
484            self.save().await?;
485            Ok(id)
486        } else {
487            self.execute(query, params).await?;
488            Ok(String::new())
489        }
490    }
491
492    async fn table_exists(&self, table_name: &str) -> Result<bool> {
493        let data = self.data.read().await;
494        Ok(data.contains_key(table_name))
495    }
496
497    async fn create_table(&self, _create_statement: &str) -> Result<()> {
498        // JSON backend doesn't need explicit table creation
499        Ok(())
500    }
501
502    fn connection_info(&self) -> String {
503        format!("JSON: {}", self.path.display())
504    }
505
506    async fn close(&mut self) -> Result<()> {
507        self.save().await
508    }
509}
510
511/// In-memory database backend implementation
512pub struct InMemoryDatabase {
513    data: Arc<RwLock<HashMap<String, Vec<HashMap<String, Value>>>>>,
514}
515
516impl InMemoryDatabase {
517    /// Create a new in-memory database
518    pub async fn new() -> Result<Self> {
519        Ok(Self {
520            data: Arc::new(RwLock::new(HashMap::new())),
521        })
522    }
523}
524
525#[async_trait]
526impl VirtualDatabase for InMemoryDatabase {
527    async fn initialize(&mut self) -> Result<()> {
528        // In-memory databases don't need initialization
529        Ok(())
530    }
531
532    async fn query(&self, query: &str, params: &[Value]) -> Result<Vec<HashMap<String, Value>>> {
533        // Reuse JSON backend query logic (same structure)
534        let data = self.data.read().await;
535        let query_upper = query.trim().to_uppercase();
536
537        // Handle SELECT COUNT(*) queries
538        if query_upper.contains("COUNT(*)") || query_upper.contains("COUNT( * )") {
539            let table_name = extract_table_name_from_select(query)?;
540            let count = if let Some(records) = data.get(table_name) {
541                if query.contains("WHERE") {
542                    apply_json_where_clause(records, query, params)?.len()
543                } else {
544                    records.len()
545                }
546            } else {
547                // Table doesn't exist yet, return 0
548                0
549            };
550            let mut result = HashMap::new();
551            result.insert("count".to_string(), Value::Number(count.into()));
552            return Ok(vec![result]);
553        } else if query_upper.starts_with("SELECT") {
554            let table_name = extract_table_name_from_select(query)?;
555
556            if let Some(records) = data.get(table_name) {
557                let filtered = if query.contains("WHERE") {
558                    apply_json_where_clause(records, query, params)?
559                } else {
560                    records.clone()
561                };
562
563                let result = apply_json_pagination(&filtered, query)?;
564                return Ok(result);
565            }
566        } else if query_upper.starts_with("COUNT") {
567            let table_name = extract_table_name_from_count(query)?;
568            if let Some(records) = data.get(table_name) {
569                let count = if query.contains("WHERE") {
570                    apply_json_where_clause(records, query, params)?.len()
571                } else {
572                    records.len()
573                };
574                let mut result = HashMap::new();
575                result.insert("total".to_string(), Value::Number(count.into()));
576                return Ok(vec![result]);
577            }
578        }
579
580        Ok(vec![])
581    }
582
583    async fn execute(&self, query: &str, params: &[Value]) -> Result<u64> {
584        let mut data = self.data.write().await;
585
586        let query_upper = query.trim().to_uppercase();
587
588        if query_upper.starts_with("INSERT") {
589            let (table_name, record) = parse_insert_query(query, params)?;
590            let records = data.entry(table_name).or_insert_with(Vec::new);
591            records.push(record);
592            Ok(1)
593        } else if query_upper.starts_with("UPDATE") {
594            let (table_name, updates, where_clause, where_params) =
595                parse_update_query(query, params)?;
596            if let Some(records) = data.get_mut(&table_name) {
597                let mut updated = 0;
598                for record in records.iter_mut() {
599                    if matches_json_where(record, &where_clause, &where_params)? {
600                        record.extend(updates.clone());
601                        updated += 1;
602                    }
603                }
604                Ok(updated)
605            } else {
606                Ok(0)
607            }
608        } else if query_upper.starts_with("DELETE") {
609            let (table_name, where_clause, where_params) = parse_delete_query(query, params)?;
610            // Ensure table exists (for DELETE FROM table_name without WHERE, we need the table)
611            let records = data.entry(table_name.clone()).or_insert_with(Vec::new);
612            let initial_len = records.len();
613            records.retain(|record| {
614                !matches_json_where(record, &where_clause, &where_params).unwrap_or(false)
615            });
616            let deleted = initial_len - records.len();
617            Ok(deleted as u64)
618        } else {
619            Ok(0)
620        }
621    }
622
623    async fn execute_with_id(&self, query: &str, params: &[Value]) -> Result<String> {
624        let mut data = self.data.write().await;
625
626        if query.trim().to_uppercase().starts_with("INSERT") {
627            let (table_name, mut record) = parse_insert_query(query, params)?;
628
629            if !record.contains_key("id") {
630                use uuid::Uuid;
631                record.insert("id".to_string(), Value::String(Uuid::new_v4().to_string()));
632            }
633
634            let id = record.get("id").and_then(|v| v.as_str()).unwrap_or("").to_string();
635
636            let records = data.entry(table_name).or_insert_with(Vec::new);
637            records.push(record);
638            Ok(id)
639        } else {
640            self.execute(query, params).await?;
641            Ok(String::new())
642        }
643    }
644
645    async fn table_exists(&self, table_name: &str) -> Result<bool> {
646        let data = self.data.read().await;
647        Ok(data.contains_key(table_name))
648    }
649
650    async fn create_table(&self, create_statement: &str) -> Result<()> {
651        // In-memory backend doesn't need explicit table creation, but we should
652        // extract table name and ensure it exists in the data HashMap
653        // Extract table name from CREATE TABLE statement
654        // Format: "CREATE TABLE IF NOT EXISTS table_name (" or "CREATE TABLE table_name ("
655        let query_upper = create_statement.to_uppercase();
656        if query_upper.contains("CREATE TABLE") {
657            let mut rest = create_statement;
658
659            // Skip "CREATE TABLE"
660            if let Some(idx) = query_upper.find("CREATE TABLE") {
661                rest = &create_statement[idx + 12..];
662            }
663
664            // Skip "IF NOT EXISTS" if present
665            let rest_upper = rest.to_uppercase();
666            if rest_upper.trim_start().starts_with("IF NOT EXISTS") {
667                if let Some(idx) = rest_upper.find("IF NOT EXISTS") {
668                    rest = &rest[idx + 13..];
669                }
670            }
671
672            // Find the table name (ends at '(' or whitespace)
673            let table_name = rest
674                .trim_start()
675                .split(|c: char| c == '(' || c.is_whitespace())
676                .next()
677                .unwrap_or("")
678                .trim()
679                .to_string();
680
681            if !table_name.is_empty() {
682                let mut data = self.data.write().await;
683                data.entry(table_name).or_insert_with(Vec::new);
684            }
685        }
686        Ok(())
687    }
688
689    fn connection_info(&self) -> String {
690        "In-Memory".to_string()
691    }
692
693    async fn close(&mut self) -> Result<()> {
694        // In-memory databases don't need cleanup
695        Ok(())
696    }
697}
698
699// Helper functions for JSON/InMemory query parsing
700
701/// Extract table name from SELECT query
702fn extract_table_name_from_select(query: &str) -> Result<&str> {
703    // Simple parser: "SELECT * FROM table_name"
704    let parts: Vec<&str> = query.split_whitespace().collect();
705    if let Some(from_idx) = parts.iter().position(|&p| p.to_uppercase() == "FROM") {
706        if from_idx + 1 < parts.len() {
707            let table_name = parts[from_idx + 1].trim_end_matches(';');
708            return Ok(table_name);
709        }
710    }
711    Err(Error::generic("Invalid SELECT query: missing FROM clause".to_string()))
712}
713
714/// Extract table name from COUNT query
715fn extract_table_name_from_count(query: &str) -> Result<&str> {
716    // "SELECT COUNT(*) FROM table_name" or "SELECT COUNT(*) as total FROM table_name"
717    extract_table_name_from_select(query)
718}
719
720/// Apply WHERE clause filtering to JSON records
721fn apply_json_where_clause(
722    records: &[HashMap<String, Value>],
723    query: &str,
724    params: &[Value],
725) -> Result<Vec<HashMap<String, Value>>> {
726    // Simple WHERE clause parser - supports basic "field = ?" patterns
727    let mut result = Vec::new();
728
729    for record in records {
730        if matches_json_where(record, query, params)? {
731            result.push(record.clone());
732        }
733    }
734
735    Ok(result)
736}
737
738/// Check if a record matches WHERE clause
739fn matches_json_where(
740    record: &HashMap<String, Value>,
741    query: &str,
742    params: &[Value],
743) -> Result<bool> {
744    // Extract WHERE clause from query
745    if let Some(where_idx) = query.to_uppercase().find("WHERE") {
746        let where_clause = &query[where_idx + 5..];
747
748        // Handle multiple AND conditions
749        let conditions: Vec<&str> = where_clause.split(" AND ").collect();
750        let mut param_index = 0;
751
752        for condition in conditions {
753            let parts: Vec<&str> = condition.split_whitespace().collect();
754
755            if parts.len() >= 3 {
756                let field = parts[0];
757                let operator = parts[1];
758
759                if parts.iter().any(|&p| p == "?") && param_index < params.len() {
760                    let expected_value = &params[param_index];
761                    let actual_value = record.get(field);
762                    param_index += 1;
763
764                    let matches = match operator {
765                        "=" => matches_value(actual_value, expected_value),
766                        "!=" => !matches_value(actual_value, expected_value),
767                        _ => true, // Unknown operator, skip
768                    };
769
770                    if !matches {
771                        return Ok(false);
772                    }
773                }
774            }
775        }
776
777        return Ok(true); // All conditions matched
778    }
779
780    Ok(true) // No WHERE clause
781}
782
783/// Check if two values match
784fn matches_value(actual: Option<&Value>, expected: &Value) -> bool {
785    match (actual, expected) {
786        (Some(a), e) => a == e,
787        (None, Value::Null) => true,
788        _ => false,
789    }
790}
791
792/// Apply pagination (LIMIT and OFFSET) to results
793fn apply_json_pagination(
794    records: &[HashMap<String, Value>],
795    query: &str,
796) -> Result<Vec<HashMap<String, Value>>> {
797    let mut result = records.to_vec();
798
799    // Extract LIMIT
800    if let Some(limit_idx) = query.to_uppercase().find("LIMIT") {
801        let limit_str = query[limit_idx + 5..]
802            .split_whitespace()
803            .next()
804            .unwrap_or("")
805            .trim_end_matches(';');
806
807        if let Ok(limit) = limit_str.parse::<usize>() {
808            // Extract OFFSET
809            let offset = if let Some(offset_idx) = query.to_uppercase().find("OFFSET") {
810                query[offset_idx + 6..]
811                    .split_whitespace()
812                    .next()
813                    .unwrap_or("0")
814                    .trim_end_matches(';')
815                    .parse::<usize>()
816                    .unwrap_or(0)
817            } else {
818                0
819            };
820
821            let start = offset.min(result.len());
822            let end = (start + limit).min(result.len());
823            result = result[start..end].to_vec();
824        }
825    }
826
827    Ok(result)
828}
829
830/// Parse INSERT query and return (table_name, record)
831fn parse_insert_query(query: &str, params: &[Value]) -> Result<(String, HashMap<String, Value>)> {
832    // Simple parser: "INSERT INTO table_name (field1, field2) VALUES (?, ?)"
833    let parts: Vec<&str> = query.split_whitespace().collect();
834
835    if let Some(into_idx) = parts.iter().position(|&p| p.to_uppercase() == "INTO") {
836        if into_idx + 1 < parts.len() {
837            let table_name = parts[into_idx + 1].to_string();
838
839            // Extract field names
840            if let Some(fields_start) = query.find('(') {
841                if let Some(fields_end) = query[fields_start + 1..].find(')') {
842                    let fields_str = &query[fields_start + 1..fields_start + 1 + fields_end];
843                    let fields: Vec<&str> = fields_str.split(',').map(|s| s.trim()).collect();
844
845                    // Build record from params
846                    let mut record = HashMap::new();
847                    for (idx, field) in fields.iter().enumerate() {
848                        if idx < params.len() {
849                            record.insert(field.to_string(), params[idx].clone());
850                        }
851                    }
852
853                    return Ok((table_name, record));
854                }
855            }
856        }
857    }
858
859    Err(Error::generic("Invalid INSERT query format".to_string()))
860}
861
862/// Parse UPDATE query
863fn parse_update_query(
864    query: &str,
865    params: &[Value],
866) -> Result<(String, HashMap<String, Value>, String, Vec<Value>)> {
867    // "UPDATE table_name SET field1 = ?, field2 = ? WHERE field3 = ?"
868    let parts: Vec<&str> = query.split_whitespace().collect();
869
870    if parts.len() < 4 || parts[0].to_uppercase() != "UPDATE" {
871        return Err(Error::generic("Invalid UPDATE query".to_string()));
872    }
873
874    let table_name = parts[1].to_string();
875
876    // Extract SET clause
877    if let Some(set_idx) = parts.iter().position(|&p| p.to_uppercase() == "SET") {
878        let set_clause = &query[query.to_uppercase().find("SET").unwrap() + 3..];
879        let where_clause = if let Some(where_idx) = set_clause.to_uppercase().find("WHERE") {
880            &set_clause[..where_idx]
881        } else {
882            set_clause
883        };
884
885        // Parse SET fields
886        let mut updates = HashMap::new();
887        let set_parts: Vec<&str> = where_clause.split(',').collect();
888        let mut param_idx = 0;
889
890        for part in set_parts {
891            let field_eq: Vec<&str> = part.split('=').map(|s| s.trim()).collect();
892            if field_eq.len() == 2 && field_eq[1] == "?" && param_idx < params.len() {
893                updates.insert(field_eq[0].to_string(), params[param_idx].clone());
894                param_idx += 1;
895            }
896        }
897
898        // Extract WHERE clause
899        let (where_clause_str, where_params) =
900            if let Some(where_idx) = set_clause.to_uppercase().find("WHERE") {
901                let where_part = &set_clause[where_idx + 5..];
902                (where_part.to_string(), params[param_idx..].to_vec())
903            } else {
904                (String::new(), Vec::new())
905            };
906
907        return Ok((table_name, updates, where_clause_str, where_params));
908    }
909
910    Err(Error::generic("Invalid UPDATE query: missing SET clause".to_string()))
911}
912
913/// Parse DELETE query
914fn parse_delete_query(query: &str, params: &[Value]) -> Result<(String, String, Vec<Value>)> {
915    // "DELETE FROM table_name WHERE field = ?"
916    let parts: Vec<&str> = query.split_whitespace().collect();
917
918    if let Some(from_idx) = parts.iter().position(|&p| p.to_uppercase() == "FROM") {
919        if from_idx + 1 < parts.len() {
920            let table_name = parts[from_idx + 1].to_string();
921
922            // Extract WHERE clause
923            if let Some(where_idx) = query.to_uppercase().find("WHERE") {
924                let where_clause = query[where_idx + 5..].to_string();
925                return Ok((table_name, where_clause, params.to_vec()));
926            } else {
927                return Ok((table_name, String::new(), Vec::new()));
928            }
929        }
930    }
931
932    Err(Error::generic("Invalid DELETE query".to_string()))
933}
934
935#[cfg(test)]
936mod tests {
937    use super::*;
938    use crate::config::StorageBackend;
939
940    // Helper functions for testing
941    async fn create_test_table(db: &dyn VirtualDatabase) -> Result<()> {
942        let create_sql = "CREATE TABLE IF NOT EXISTS test_users (
943            id TEXT PRIMARY KEY,
944            name TEXT NOT NULL,
945            email TEXT,
946            age INTEGER
947        )";
948        db.create_table(create_sql).await
949    }
950
951    // SqliteDatabase tests
952    #[tokio::test]
953    async fn test_sqlite_database_creation() {
954        let temp_dir = tempfile::tempdir().unwrap();
955        let db_path = temp_dir.path().join("test.db");
956        let result = SqliteDatabase::new(&db_path).await;
957        assert!(result.is_ok());
958    }
959
960    #[tokio::test]
961    async fn test_sqlite_database_connection_info() {
962        let temp_dir = tempfile::tempdir().unwrap();
963        let db_path = temp_dir.path().join("test.db");
964        let db = SqliteDatabase::new(&db_path).await.unwrap();
965        let info = db.connection_info();
966        assert!(info.contains("SQLite"));
967        assert!(info.contains("test.db"));
968    }
969
970    #[tokio::test]
971    async fn test_sqlite_database_initialize() {
972        let temp_dir = tempfile::tempdir().unwrap();
973        let db_path = temp_dir.path().join("test.db");
974        let mut db = SqliteDatabase::new(&db_path).await.unwrap();
975        let result = db.initialize().await;
976        assert!(result.is_ok());
977    }
978
979    #[tokio::test]
980    async fn test_sqlite_create_table() {
981        let temp_dir = tempfile::tempdir().unwrap();
982        let db_path = temp_dir.path().join("test.db");
983        let db = SqliteDatabase::new(&db_path).await.unwrap();
984        let result = create_test_table(&db).await;
985        assert!(result.is_ok());
986    }
987
988    #[tokio::test]
989    async fn test_sqlite_table_exists() {
990        let temp_dir = tempfile::tempdir().unwrap();
991        let db_path = temp_dir.path().join("test.db");
992        let db = SqliteDatabase::new(&db_path).await.unwrap();
993        create_test_table(&db).await.unwrap();
994
995        let exists = db.table_exists("test_users").await.unwrap();
996        assert!(exists);
997
998        let not_exists = db.table_exists("nonexistent_table").await.unwrap();
999        assert!(!not_exists);
1000    }
1001
1002    #[tokio::test]
1003    async fn test_sqlite_execute_insert() {
1004        let temp_dir = tempfile::tempdir().unwrap();
1005        let db_path = temp_dir.path().join("test.db");
1006        let db = SqliteDatabase::new(&db_path).await.unwrap();
1007        create_test_table(&db).await.unwrap();
1008
1009        let query = "INSERT INTO test_users (id, name, email, age) VALUES (?, ?, ?, ?)";
1010        let params = vec![
1011            Value::String("1".to_string()),
1012            Value::String("John Doe".to_string()),
1013            Value::String("john@example.com".to_string()),
1014            Value::Number(30.into()),
1015        ];
1016
1017        let result = db.execute(query, &params).await;
1018        assert!(result.is_ok());
1019        assert_eq!(result.unwrap(), 1);
1020    }
1021
1022    #[tokio::test]
1023    async fn test_sqlite_execute_with_id() {
1024        let temp_dir = tempfile::tempdir().unwrap();
1025        let db_path = temp_dir.path().join("test.db");
1026        let db = SqliteDatabase::new(&db_path).await.unwrap();
1027        create_test_table(&db).await.unwrap();
1028
1029        let query = "INSERT INTO test_users (id, name, email) VALUES (?, ?, ?)";
1030        let params = vec![
1031            Value::String("test-id".to_string()),
1032            Value::String("Jane Doe".to_string()),
1033            Value::String("jane@example.com".to_string()),
1034        ];
1035
1036        let result = db.execute_with_id(query, &params).await;
1037        assert!(result.is_ok());
1038    }
1039
1040    #[tokio::test]
1041    async fn test_sqlite_query_select() {
1042        let temp_dir = tempfile::tempdir().unwrap();
1043        let db_path = temp_dir.path().join("test.db");
1044        let db = SqliteDatabase::new(&db_path).await.unwrap();
1045        create_test_table(&db).await.unwrap();
1046
1047        // Insert test data
1048        let insert_query = "INSERT INTO test_users (id, name, email) VALUES (?, ?, ?)";
1049        db.execute(
1050            insert_query,
1051            &[
1052                Value::String("1".to_string()),
1053                Value::String("Test User".to_string()),
1054                Value::String("test@example.com".to_string()),
1055            ],
1056        )
1057        .await
1058        .unwrap();
1059
1060        // Query data
1061        let select_query = "SELECT * FROM test_users WHERE id = ?";
1062        let results = db.query(select_query, &[Value::String("1".to_string())]).await;
1063        assert!(results.is_ok());
1064        let rows = results.unwrap();
1065        assert_eq!(rows.len(), 1);
1066        assert_eq!(rows[0].get("id").unwrap().as_str().unwrap(), "1");
1067        assert_eq!(rows[0].get("name").unwrap().as_str().unwrap(), "Test User");
1068    }
1069
1070    #[tokio::test]
1071    async fn test_sqlite_execute_update() {
1072        let temp_dir = tempfile::tempdir().unwrap();
1073        let db_path = temp_dir.path().join("test.db");
1074        let db = SqliteDatabase::new(&db_path).await.unwrap();
1075        create_test_table(&db).await.unwrap();
1076
1077        // Insert
1078        db.execute(
1079            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1080            &[
1081                Value::String("1".to_string()),
1082                Value::String("Original Name".to_string()),
1083            ],
1084        )
1085        .await
1086        .unwrap();
1087
1088        // Update
1089        let update_result = db
1090            .execute(
1091                "UPDATE test_users SET name = ? WHERE id = ?",
1092                &[
1093                    Value::String("Updated Name".to_string()),
1094                    Value::String("1".to_string()),
1095                ],
1096            )
1097            .await;
1098
1099        assert!(update_result.is_ok());
1100        assert_eq!(update_result.unwrap(), 1);
1101
1102        // Verify update
1103        let rows = db
1104            .query("SELECT name FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1105            .await
1106            .unwrap();
1107        assert_eq!(rows[0].get("name").unwrap().as_str().unwrap(), "Updated Name");
1108    }
1109
1110    #[tokio::test]
1111    async fn test_sqlite_execute_delete() {
1112        let temp_dir = tempfile::tempdir().unwrap();
1113        let db_path = temp_dir.path().join("test.db");
1114        let db = SqliteDatabase::new(&db_path).await.unwrap();
1115        create_test_table(&db).await.unwrap();
1116
1117        // Insert
1118        db.execute(
1119            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1120            &[
1121                Value::String("1".to_string()),
1122                Value::String("Test".to_string()),
1123            ],
1124        )
1125        .await
1126        .unwrap();
1127
1128        // Delete
1129        let delete_result = db
1130            .execute("DELETE FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1131            .await;
1132        assert!(delete_result.is_ok());
1133        assert_eq!(delete_result.unwrap(), 1);
1134
1135        // Verify deletion
1136        let rows = db
1137            .query("SELECT * FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1138            .await
1139            .unwrap();
1140        assert_eq!(rows.len(), 0);
1141    }
1142
1143    #[tokio::test]
1144    async fn test_sqlite_close() {
1145        let temp_dir = tempfile::tempdir().unwrap();
1146        let db_path = temp_dir.path().join("test.db");
1147        let mut db = SqliteDatabase::new(&db_path).await.unwrap();
1148        let result = db.close().await;
1149        assert!(result.is_ok());
1150    }
1151
1152    // JsonDatabase tests
1153    #[tokio::test]
1154    async fn test_json_database_creation() {
1155        let temp_dir = tempfile::tempdir().unwrap();
1156        let db_path = temp_dir.path().join("test.json");
1157        let result = JsonDatabase::new(&db_path).await;
1158        assert!(result.is_ok());
1159    }
1160
1161    #[tokio::test]
1162    async fn test_json_database_connection_info() {
1163        let temp_dir = tempfile::tempdir().unwrap();
1164        let db_path = temp_dir.path().join("test.json");
1165        let db = JsonDatabase::new(&db_path).await.unwrap();
1166        let info = db.connection_info();
1167        assert!(info.contains("JSON"));
1168        assert!(info.contains("test.json"));
1169    }
1170
1171    #[tokio::test]
1172    async fn test_json_database_initialize() {
1173        let temp_dir = tempfile::tempdir().unwrap();
1174        let db_path = temp_dir.path().join("test.json");
1175        let mut db = JsonDatabase::new(&db_path).await.unwrap();
1176        let result = db.initialize().await;
1177        assert!(result.is_ok());
1178    }
1179
1180    #[tokio::test]
1181    async fn test_json_create_table() {
1182        let temp_dir = tempfile::tempdir().unwrap();
1183        let db_path = temp_dir.path().join("test.json");
1184        let db = JsonDatabase::new(&db_path).await.unwrap();
1185        let result = db.create_table("CREATE TABLE test_users (id TEXT, name TEXT)").await;
1186        assert!(result.is_ok());
1187    }
1188
1189    #[tokio::test]
1190    async fn test_json_table_exists() {
1191        let temp_dir = tempfile::tempdir().unwrap();
1192        let db_path = temp_dir.path().join("test.json");
1193        let db = JsonDatabase::new(&db_path).await.unwrap();
1194
1195        // Table doesn't exist initially
1196        assert!(!db.table_exists("test_users").await.unwrap());
1197
1198        // Insert a record (creates the table)
1199        db.execute(
1200            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1201            &[
1202                Value::String("1".to_string()),
1203                Value::String("Test".to_string()),
1204            ],
1205        )
1206        .await
1207        .unwrap();
1208
1209        // Now table should exist
1210        assert!(db.table_exists("test_users").await.unwrap());
1211    }
1212
1213    #[tokio::test]
1214    async fn test_json_execute_insert() {
1215        let temp_dir = tempfile::tempdir().unwrap();
1216        let db_path = temp_dir.path().join("test.json");
1217        let db = JsonDatabase::new(&db_path).await.unwrap();
1218
1219        let query = "INSERT INTO test_users (id, name, email) VALUES (?, ?, ?)";
1220        let params = vec![
1221            Value::String("1".to_string()),
1222            Value::String("John Doe".to_string()),
1223            Value::String("john@example.com".to_string()),
1224        ];
1225
1226        let result = db.execute(query, &params).await;
1227        assert!(result.is_ok());
1228        assert_eq!(result.unwrap(), 1);
1229    }
1230
1231    #[tokio::test]
1232    async fn test_json_execute_with_id() {
1233        let temp_dir = tempfile::tempdir().unwrap();
1234        let db_path = temp_dir.path().join("test.json");
1235        let db = JsonDatabase::new(&db_path).await.unwrap();
1236
1237        let query = "INSERT INTO test_users (name, email) VALUES (?, ?)";
1238        let params = vec![
1239            Value::String("Jane Doe".to_string()),
1240            Value::String("jane@example.com".to_string()),
1241        ];
1242
1243        let result = db.execute_with_id(query, &params).await;
1244        assert!(result.is_ok());
1245        // Should return auto-generated ID
1246        assert!(!result.unwrap().is_empty());
1247    }
1248
1249    #[tokio::test]
1250    async fn test_json_query_select() {
1251        let temp_dir = tempfile::tempdir().unwrap();
1252        let db_path = temp_dir.path().join("test.json");
1253        let db = JsonDatabase::new(&db_path).await.unwrap();
1254
1255        // Insert test data
1256        db.execute(
1257            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1258            &[
1259                Value::String("1".to_string()),
1260                Value::String("Test User".to_string()),
1261            ],
1262        )
1263        .await
1264        .unwrap();
1265
1266        // Query data
1267        let results = db
1268            .query("SELECT * FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1269            .await;
1270        assert!(results.is_ok());
1271        let rows = results.unwrap();
1272        assert_eq!(rows.len(), 1);
1273        assert_eq!(rows[0].get("id").unwrap().as_str().unwrap(), "1");
1274    }
1275
1276    #[tokio::test]
1277    async fn test_json_query_count() {
1278        let temp_dir = tempfile::tempdir().unwrap();
1279        let db_path = temp_dir.path().join("test.json");
1280        let db = JsonDatabase::new(&db_path).await.unwrap();
1281
1282        // Insert multiple records
1283        db.execute(
1284            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1285            &[
1286                Value::String("1".to_string()),
1287                Value::String("User 1".to_string()),
1288            ],
1289        )
1290        .await
1291        .unwrap();
1292        db.execute(
1293            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1294            &[
1295                Value::String("2".to_string()),
1296                Value::String("User 2".to_string()),
1297            ],
1298        )
1299        .await
1300        .unwrap();
1301
1302        // Query count
1303        let results = db.query("SELECT COUNT(*) FROM test_users", &[]).await;
1304        assert!(results.is_ok());
1305        let rows = results.unwrap();
1306        assert_eq!(rows.len(), 1);
1307        assert_eq!(rows[0].get("count").unwrap().as_u64().unwrap(), 2);
1308    }
1309
1310    #[tokio::test]
1311    async fn test_json_execute_update() {
1312        let temp_dir = tempfile::tempdir().unwrap();
1313        let db_path = temp_dir.path().join("test.json");
1314        let db = JsonDatabase::new(&db_path).await.unwrap();
1315
1316        // Insert
1317        db.execute(
1318            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1319            &[
1320                Value::String("1".to_string()),
1321                Value::String("Original".to_string()),
1322            ],
1323        )
1324        .await
1325        .unwrap();
1326
1327        // Update
1328        let update_result = db
1329            .execute(
1330                "UPDATE test_users SET name = ? WHERE id = ?",
1331                &[
1332                    Value::String("Updated".to_string()),
1333                    Value::String("1".to_string()),
1334                ],
1335            )
1336            .await;
1337
1338        assert!(update_result.is_ok());
1339        assert_eq!(update_result.unwrap(), 1);
1340    }
1341
1342    #[tokio::test]
1343    async fn test_json_execute_delete() {
1344        let temp_dir = tempfile::tempdir().unwrap();
1345        let db_path = temp_dir.path().join("test.json");
1346        let db = JsonDatabase::new(&db_path).await.unwrap();
1347
1348        // Insert
1349        db.execute(
1350            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1351            &[
1352                Value::String("1".to_string()),
1353                Value::String("Test".to_string()),
1354            ],
1355        )
1356        .await
1357        .unwrap();
1358
1359        // Delete
1360        let delete_result = db
1361            .execute("DELETE FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1362            .await;
1363        assert!(delete_result.is_ok());
1364        assert_eq!(delete_result.unwrap(), 1);
1365    }
1366
1367    #[tokio::test]
1368    async fn test_json_close() {
1369        let temp_dir = tempfile::tempdir().unwrap();
1370        let db_path = temp_dir.path().join("test.json");
1371        let mut db = JsonDatabase::new(&db_path).await.unwrap();
1372        let result = db.close().await;
1373        assert!(result.is_ok());
1374    }
1375
1376    // InMemoryDatabase tests
1377    #[tokio::test]
1378    async fn test_inmemory_database_creation() {
1379        let result = InMemoryDatabase::new().await;
1380        assert!(result.is_ok());
1381    }
1382
1383    #[tokio::test]
1384    async fn test_inmemory_database_connection_info() {
1385        let db = InMemoryDatabase::new().await.unwrap();
1386        let info = db.connection_info();
1387        assert_eq!(info, "In-Memory");
1388    }
1389
1390    #[tokio::test]
1391    async fn test_inmemory_database_initialize() {
1392        let mut db = InMemoryDatabase::new().await.unwrap();
1393        let result = db.initialize().await;
1394        assert!(result.is_ok());
1395    }
1396
1397    #[tokio::test]
1398    async fn test_inmemory_create_table() {
1399        let db = InMemoryDatabase::new().await.unwrap();
1400        let result = db.create_table("CREATE TABLE test_users (id TEXT, name TEXT)").await;
1401        assert!(result.is_ok());
1402    }
1403
1404    #[tokio::test]
1405    async fn test_inmemory_table_exists() {
1406        let db = InMemoryDatabase::new().await.unwrap();
1407
1408        // Create table
1409        db.create_table("CREATE TABLE test_users (id TEXT)").await.unwrap();
1410
1411        // Table should exist
1412        assert!(db.table_exists("test_users").await.unwrap());
1413        assert!(!db.table_exists("nonexistent").await.unwrap());
1414    }
1415
1416    #[tokio::test]
1417    async fn test_inmemory_execute_insert() {
1418        let db = InMemoryDatabase::new().await.unwrap();
1419
1420        let query = "INSERT INTO test_users (id, name) VALUES (?, ?)";
1421        let params = vec![
1422            Value::String("1".to_string()),
1423            Value::String("John Doe".to_string()),
1424        ];
1425
1426        let result = db.execute(query, &params).await;
1427        assert!(result.is_ok());
1428        assert_eq!(result.unwrap(), 1);
1429    }
1430
1431    #[tokio::test]
1432    async fn test_inmemory_execute_with_id() {
1433        let db = InMemoryDatabase::new().await.unwrap();
1434
1435        let query = "INSERT INTO test_users (name) VALUES (?)";
1436        let params = vec![Value::String("Jane Doe".to_string())];
1437
1438        let result = db.execute_with_id(query, &params).await;
1439        assert!(result.is_ok());
1440        assert!(!result.unwrap().is_empty());
1441    }
1442
1443    #[tokio::test]
1444    async fn test_inmemory_query_select() {
1445        let db = InMemoryDatabase::new().await.unwrap();
1446
1447        // Insert
1448        db.execute(
1449            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1450            &[
1451                Value::String("1".to_string()),
1452                Value::String("Test User".to_string()),
1453            ],
1454        )
1455        .await
1456        .unwrap();
1457
1458        // Query
1459        let results = db
1460            .query("SELECT * FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1461            .await;
1462        assert!(results.is_ok());
1463        let rows = results.unwrap();
1464        assert_eq!(rows.len(), 1);
1465    }
1466
1467    #[tokio::test]
1468    async fn test_inmemory_query_count() {
1469        let db = InMemoryDatabase::new().await.unwrap();
1470
1471        // Insert multiple
1472        db.execute(
1473            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1474            &[
1475                Value::String("1".to_string()),
1476                Value::String("User 1".to_string()),
1477            ],
1478        )
1479        .await
1480        .unwrap();
1481        db.execute(
1482            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1483            &[
1484                Value::String("2".to_string()),
1485                Value::String("User 2".to_string()),
1486            ],
1487        )
1488        .await
1489        .unwrap();
1490
1491        // Count
1492        let results = db.query("SELECT COUNT(*) FROM test_users", &[]).await;
1493        assert!(results.is_ok());
1494        let rows = results.unwrap();
1495        assert_eq!(rows[0].get("count").unwrap().as_u64().unwrap(), 2);
1496    }
1497
1498    #[tokio::test]
1499    async fn test_inmemory_execute_update() {
1500        let db = InMemoryDatabase::new().await.unwrap();
1501
1502        // Insert
1503        db.execute(
1504            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1505            &[
1506                Value::String("1".to_string()),
1507                Value::String("Original".to_string()),
1508            ],
1509        )
1510        .await
1511        .unwrap();
1512
1513        // Update
1514        let result = db
1515            .execute(
1516                "UPDATE test_users SET name = ? WHERE id = ?",
1517                &[
1518                    Value::String("Updated".to_string()),
1519                    Value::String("1".to_string()),
1520                ],
1521            )
1522            .await;
1523
1524        assert!(result.is_ok());
1525        assert_eq!(result.unwrap(), 1);
1526    }
1527
1528    #[tokio::test]
1529    async fn test_inmemory_execute_delete() {
1530        let db = InMemoryDatabase::new().await.unwrap();
1531
1532        // Insert
1533        db.execute(
1534            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1535            &[
1536                Value::String("1".to_string()),
1537                Value::String("Test".to_string()),
1538            ],
1539        )
1540        .await
1541        .unwrap();
1542
1543        // Delete
1544        let result = db
1545            .execute("DELETE FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1546            .await;
1547        assert!(result.is_ok());
1548        assert_eq!(result.unwrap(), 1);
1549    }
1550
1551    #[tokio::test]
1552    async fn test_inmemory_close() {
1553        let mut db = InMemoryDatabase::new().await.unwrap();
1554        let result = db.close().await;
1555        assert!(result.is_ok());
1556    }
1557
1558    // create_database tests
1559    #[tokio::test]
1560    async fn test_create_database_sqlite() {
1561        let temp_dir = tempfile::tempdir().unwrap();
1562        let db_path = temp_dir.path().join("test.db");
1563        let backend = StorageBackend::Sqlite {
1564            path: db_path.clone(),
1565        };
1566        let result = create_database(&backend).await;
1567        assert!(result.is_ok());
1568        let db = result.unwrap();
1569        assert!(db.connection_info().contains("SQLite"));
1570    }
1571
1572    #[tokio::test]
1573    async fn test_create_database_json() {
1574        let temp_dir = tempfile::tempdir().unwrap();
1575        let db_path = temp_dir.path().join("test.json");
1576        let backend = StorageBackend::Json {
1577            path: db_path.clone(),
1578        };
1579        let result = create_database(&backend).await;
1580        assert!(result.is_ok());
1581        let db = result.unwrap();
1582        assert!(db.connection_info().contains("JSON"));
1583    }
1584
1585    #[tokio::test]
1586    async fn test_create_database_memory() {
1587        let backend = StorageBackend::Memory;
1588        let result = create_database(&backend).await;
1589        assert!(result.is_ok());
1590        let db = result.unwrap();
1591        assert_eq!(db.connection_info(), "In-Memory");
1592    }
1593
1594    // Helper function tests
1595    #[test]
1596    fn test_extract_table_name_from_select() {
1597        let query = "SELECT * FROM users";
1598        let result = extract_table_name_from_select(query);
1599        assert!(result.is_ok());
1600        assert_eq!(result.unwrap(), "users");
1601    }
1602
1603    #[test]
1604    fn test_extract_table_name_from_select_with_where() {
1605        let query = "SELECT * FROM products WHERE price > 10";
1606        let result = extract_table_name_from_select(query);
1607        assert!(result.is_ok());
1608        assert_eq!(result.unwrap(), "products");
1609    }
1610
1611    #[test]
1612    fn test_extract_table_name_from_select_invalid() {
1613        let query = "SELECT * users";
1614        let result = extract_table_name_from_select(query);
1615        assert!(result.is_err());
1616    }
1617
1618    #[test]
1619    fn test_parse_insert_query() {
1620        let query = "INSERT INTO users (id, name) VALUES (?, ?)";
1621        let params = vec![
1622            Value::String("1".to_string()),
1623            Value::String("John".to_string()),
1624        ];
1625        let result = parse_insert_query(query, &params);
1626        assert!(result.is_ok());
1627        let (table_name, record) = result.unwrap();
1628        assert_eq!(table_name, "users");
1629        assert_eq!(record.len(), 2);
1630        assert_eq!(record.get("id").unwrap().as_str().unwrap(), "1");
1631    }
1632
1633    #[test]
1634    fn test_parse_insert_query_invalid() {
1635        let query = "INSERT users VALUES (?)";
1636        let params = vec![Value::String("1".to_string())];
1637        let result = parse_insert_query(query, &params);
1638        assert!(result.is_err());
1639    }
1640
1641    #[test]
1642    fn test_parse_update_query() {
1643        let query = "UPDATE users SET name = ? WHERE id = ?";
1644        let params = vec![
1645            Value::String("John".to_string()),
1646            Value::String("1".to_string()),
1647        ];
1648        let result = parse_update_query(query, &params);
1649        assert!(result.is_ok());
1650        let (table_name, updates, _where_clause, _where_params) = result.unwrap();
1651        assert_eq!(table_name, "users");
1652        assert_eq!(updates.len(), 1);
1653    }
1654
1655    #[test]
1656    fn test_parse_delete_query() {
1657        let query = "DELETE FROM users WHERE id = ?";
1658        let params = vec![Value::String("1".to_string())];
1659        let result = parse_delete_query(query, &params);
1660        assert!(result.is_ok());
1661        let (table_name, _where_clause, where_params) = result.unwrap();
1662        assert_eq!(table_name, "users");
1663        assert_eq!(where_params.len(), 1);
1664    }
1665
1666    #[test]
1667    fn test_matches_value() {
1668        assert!(matches_value(
1669            Some(&Value::String("test".to_string())),
1670            &Value::String("test".to_string())
1671        ));
1672        assert!(!matches_value(
1673            Some(&Value::String("test".to_string())),
1674            &Value::String("other".to_string())
1675        ));
1676        assert!(matches_value(None, &Value::Null));
1677        assert!(!matches_value(None, &Value::String("test".to_string())));
1678    }
1679
1680    #[tokio::test]
1681    async fn test_json_pagination() {
1682        let temp_dir = tempfile::tempdir().unwrap();
1683        let db_path = temp_dir.path().join("test.json");
1684        let db = JsonDatabase::new(&db_path).await.unwrap();
1685
1686        // Insert multiple records
1687        for i in 1..=5 {
1688            db.execute(
1689                "INSERT INTO test_users (id, name) VALUES (?, ?)",
1690                &[
1691                    Value::String(i.to_string()),
1692                    Value::String(format!("User {}", i)),
1693                ],
1694            )
1695            .await
1696            .unwrap();
1697        }
1698
1699        // Query with LIMIT
1700        let results = db.query("SELECT * FROM test_users LIMIT 2", &[]).await.unwrap();
1701        assert_eq!(results.len(), 2);
1702
1703        // Query with LIMIT and OFFSET
1704        let results = db.query("SELECT * FROM test_users LIMIT 2 OFFSET 2", &[]).await.unwrap();
1705        assert_eq!(results.len(), 2);
1706    }
1707
1708    #[tokio::test]
1709    async fn test_inmemory_pagination() {
1710        let db = InMemoryDatabase::new().await.unwrap();
1711
1712        // Insert multiple records
1713        for i in 1..=5 {
1714            db.execute(
1715                "INSERT INTO test_users (id, name) VALUES (?, ?)",
1716                &[
1717                    Value::String(i.to_string()),
1718                    Value::String(format!("User {}", i)),
1719                ],
1720            )
1721            .await
1722            .unwrap();
1723        }
1724
1725        // Query with LIMIT
1726        let results = db.query("SELECT * FROM test_users LIMIT 2", &[]).await.unwrap();
1727        assert_eq!(results.len(), 2);
1728
1729        // Query with LIMIT and OFFSET
1730        let results = db.query("SELECT * FROM test_users LIMIT 2 OFFSET 2", &[]).await.unwrap();
1731        assert_eq!(results.len(), 2);
1732    }
1733}