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://{}", 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        let mut data = self.data.write().await;
409
410        // Parse INSERT, UPDATE, DELETE queries
411        let query_upper = query.trim().to_uppercase();
412
413        if query_upper.starts_with("INSERT") {
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            self.save().await?;
418            Ok(1)
419        } else if query_upper.starts_with("UPDATE") {
420            let (table_name, updates, where_clause, where_params) =
421                parse_update_query(query, params)?;
422            if let Some(records) = data.get_mut(&table_name) {
423                let mut updated = 0;
424                for record in records.iter_mut() {
425                    if matches_json_where(record, &where_clause, &where_params)? {
426                        record.extend(updates.clone());
427                        updated += 1;
428                    }
429                }
430                self.save().await?;
431                Ok(updated)
432            } else {
433                Ok(0)
434            }
435        } else if query_upper.starts_with("DELETE") {
436            let (table_name, where_clause, where_params) = parse_delete_query(query, params)?;
437            if let Some(records) = data.get_mut(&table_name) {
438                let initial_len = records.len();
439                records.retain(|record| {
440                    !matches_json_where(record, &where_clause, &where_params).unwrap_or(false)
441                });
442                let deleted = initial_len - records.len();
443                self.save().await?;
444                Ok(deleted as u64)
445            } else {
446                Ok(0)
447            }
448        } else {
449            Ok(0)
450        }
451    }
452
453    async fn execute_with_id(&self, query: &str, params: &[Value]) -> Result<String> {
454        // For INSERT, extract the ID from the inserted record
455        let mut data = self.data.write().await;
456
457        if query.trim().to_uppercase().starts_with("INSERT") {
458            let (table_name, mut record) = parse_insert_query(query, params)?;
459
460            // Generate ID if not present
461            if !record.contains_key("id") {
462                use uuid::Uuid;
463                record.insert("id".to_string(), Value::String(Uuid::new_v4().to_string()));
464            }
465
466            let id = record.get("id").and_then(|v| v.as_str()).unwrap_or("").to_string();
467
468            let records = data.entry(table_name).or_insert_with(Vec::new);
469            records.push(record);
470            self.save().await?;
471            Ok(id)
472        } else {
473            self.execute(query, params).await?;
474            Ok(String::new())
475        }
476    }
477
478    async fn table_exists(&self, table_name: &str) -> Result<bool> {
479        let data = self.data.read().await;
480        Ok(data.contains_key(table_name))
481    }
482
483    async fn create_table(&self, _create_statement: &str) -> Result<()> {
484        // JSON backend doesn't need explicit table creation
485        Ok(())
486    }
487
488    fn connection_info(&self) -> String {
489        format!("JSON: {}", self.path.display())
490    }
491
492    async fn close(&mut self) -> Result<()> {
493        self.save().await
494    }
495}
496
497/// In-memory database backend implementation
498pub struct InMemoryDatabase {
499    data: Arc<RwLock<HashMap<String, Vec<HashMap<String, Value>>>>>,
500}
501
502impl InMemoryDatabase {
503    /// Create a new in-memory database
504    pub async fn new() -> Result<Self> {
505        Ok(Self {
506            data: Arc::new(RwLock::new(HashMap::new())),
507        })
508    }
509}
510
511#[async_trait]
512impl VirtualDatabase for InMemoryDatabase {
513    async fn initialize(&mut self) -> Result<()> {
514        // In-memory databases don't need initialization
515        Ok(())
516    }
517
518    async fn query(&self, query: &str, params: &[Value]) -> Result<Vec<HashMap<String, Value>>> {
519        // Reuse JSON backend query logic (same structure)
520        let data = self.data.read().await;
521        let query_upper = query.trim().to_uppercase();
522
523        // Handle SELECT COUNT(*) queries
524        if query_upper.contains("COUNT(*)") || query_upper.contains("COUNT( * )") {
525            let table_name = extract_table_name_from_select(query)?;
526            let count = if let Some(records) = data.get(table_name) {
527                if query.contains("WHERE") {
528                    apply_json_where_clause(records, query, params)?.len()
529                } else {
530                    records.len()
531                }
532            } else {
533                // Table doesn't exist yet, return 0
534                0
535            };
536            let mut result = HashMap::new();
537            result.insert("count".to_string(), Value::Number(count.into()));
538            return Ok(vec![result]);
539        } else if query_upper.starts_with("SELECT") {
540            let table_name = extract_table_name_from_select(query)?;
541
542            if let Some(records) = data.get(table_name) {
543                let filtered = if query.contains("WHERE") {
544                    apply_json_where_clause(records, query, params)?
545                } else {
546                    records.clone()
547                };
548
549                let result = apply_json_pagination(&filtered, query)?;
550                return Ok(result);
551            }
552        } else if query_upper.starts_with("COUNT") {
553            let table_name = extract_table_name_from_count(query)?;
554            if let Some(records) = data.get(table_name) {
555                let count = if query.contains("WHERE") {
556                    apply_json_where_clause(records, query, params)?.len()
557                } else {
558                    records.len()
559                };
560                let mut result = HashMap::new();
561                result.insert("total".to_string(), Value::Number(count.into()));
562                return Ok(vec![result]);
563            }
564        }
565
566        Ok(vec![])
567    }
568
569    async fn execute(&self, query: &str, params: &[Value]) -> Result<u64> {
570        let mut data = self.data.write().await;
571
572        let query_upper = query.trim().to_uppercase();
573
574        if query_upper.starts_with("INSERT") {
575            let (table_name, record) = parse_insert_query(query, params)?;
576            let records = data.entry(table_name).or_insert_with(Vec::new);
577            records.push(record);
578            Ok(1)
579        } else if query_upper.starts_with("UPDATE") {
580            let (table_name, updates, where_clause, where_params) =
581                parse_update_query(query, params)?;
582            if let Some(records) = data.get_mut(&table_name) {
583                let mut updated = 0;
584                for record in records.iter_mut() {
585                    if matches_json_where(record, &where_clause, &where_params)? {
586                        record.extend(updates.clone());
587                        updated += 1;
588                    }
589                }
590                Ok(updated)
591            } else {
592                Ok(0)
593            }
594        } else if query_upper.starts_with("DELETE") {
595            let (table_name, where_clause, where_params) = parse_delete_query(query, params)?;
596            // Ensure table exists (for DELETE FROM table_name without WHERE, we need the table)
597            let records = data.entry(table_name.clone()).or_insert_with(Vec::new);
598            let initial_len = records.len();
599            records.retain(|record| {
600                !matches_json_where(record, &where_clause, &where_params).unwrap_or(false)
601            });
602            let deleted = initial_len - records.len();
603            Ok(deleted as u64)
604        } else {
605            Ok(0)
606        }
607    }
608
609    async fn execute_with_id(&self, query: &str, params: &[Value]) -> Result<String> {
610        let mut data = self.data.write().await;
611
612        if query.trim().to_uppercase().starts_with("INSERT") {
613            let (table_name, mut record) = parse_insert_query(query, params)?;
614
615            if !record.contains_key("id") {
616                use uuid::Uuid;
617                record.insert("id".to_string(), Value::String(Uuid::new_v4().to_string()));
618            }
619
620            let id = record.get("id").and_then(|v| v.as_str()).unwrap_or("").to_string();
621
622            let records = data.entry(table_name).or_insert_with(Vec::new);
623            records.push(record);
624            Ok(id)
625        } else {
626            self.execute(query, params).await?;
627            Ok(String::new())
628        }
629    }
630
631    async fn table_exists(&self, table_name: &str) -> Result<bool> {
632        let data = self.data.read().await;
633        Ok(data.contains_key(table_name))
634    }
635
636    async fn create_table(&self, create_statement: &str) -> Result<()> {
637        // In-memory backend doesn't need explicit table creation, but we should
638        // extract table name and ensure it exists in the data HashMap
639        // Extract table name from CREATE TABLE statement
640        // Format: "CREATE TABLE IF NOT EXISTS table_name (" or "CREATE TABLE table_name ("
641        let query_upper = create_statement.to_uppercase();
642        if query_upper.contains("CREATE TABLE") {
643            let mut rest = create_statement;
644
645            // Skip "CREATE TABLE"
646            if let Some(idx) = query_upper.find("CREATE TABLE") {
647                rest = &create_statement[idx + 12..];
648            }
649
650            // Skip "IF NOT EXISTS" if present
651            let rest_upper = rest.to_uppercase();
652            if rest_upper.trim_start().starts_with("IF NOT EXISTS") {
653                if let Some(idx) = rest_upper.find("IF NOT EXISTS") {
654                    rest = &rest[idx + 13..];
655                }
656            }
657
658            // Find the table name (ends at '(' or whitespace)
659            let table_name = rest
660                .trim_start()
661                .split(|c: char| c == '(' || c.is_whitespace())
662                .next()
663                .unwrap_or("")
664                .trim()
665                .to_string();
666
667            if !table_name.is_empty() {
668                let mut data = self.data.write().await;
669                data.entry(table_name).or_insert_with(Vec::new);
670            }
671        }
672        Ok(())
673    }
674
675    fn connection_info(&self) -> String {
676        "In-Memory".to_string()
677    }
678
679    async fn close(&mut self) -> Result<()> {
680        // In-memory databases don't need cleanup
681        Ok(())
682    }
683}
684
685// Helper functions for JSON/InMemory query parsing
686
687/// Extract table name from SELECT query
688fn extract_table_name_from_select(query: &str) -> Result<&str> {
689    // Simple parser: "SELECT * FROM table_name"
690    let parts: Vec<&str> = query.split_whitespace().collect();
691    if let Some(from_idx) = parts.iter().position(|&p| p.to_uppercase() == "FROM") {
692        if from_idx + 1 < parts.len() {
693            let table_name = parts[from_idx + 1].trim_end_matches(';');
694            return Ok(table_name);
695        }
696    }
697    Err(Error::generic("Invalid SELECT query: missing FROM clause".to_string()))
698}
699
700/// Extract table name from COUNT query
701fn extract_table_name_from_count(query: &str) -> Result<&str> {
702    // "SELECT COUNT(*) FROM table_name" or "SELECT COUNT(*) as total FROM table_name"
703    extract_table_name_from_select(query)
704}
705
706/// Apply WHERE clause filtering to JSON records
707fn apply_json_where_clause(
708    records: &[HashMap<String, Value>],
709    query: &str,
710    params: &[Value],
711) -> Result<Vec<HashMap<String, Value>>> {
712    // Simple WHERE clause parser - supports basic "field = ?" patterns
713    let mut result = Vec::new();
714
715    for record in records {
716        if matches_json_where(record, query, params)? {
717            result.push(record.clone());
718        }
719    }
720
721    Ok(result)
722}
723
724/// Check if a record matches WHERE clause
725fn matches_json_where(
726    record: &HashMap<String, Value>,
727    query: &str,
728    params: &[Value],
729) -> Result<bool> {
730    // Extract WHERE clause from query
731    if let Some(where_idx) = query.to_uppercase().find("WHERE") {
732        let where_clause = &query[where_idx + 5..];
733
734        // Parse simple conditions like "field = ?"
735        let parts: Vec<&str> = where_clause.split_whitespace().collect();
736        if parts.len() >= 3 && parts[1] == "=" {
737            let field = parts[0];
738            let param_idx = parts.iter().position(|&p| p == "?").unwrap_or(0);
739
740            if param_idx < params.len() {
741                let expected_value = &params[0]; // Use first param for simple cases
742                let actual_value = record.get(field);
743
744                return Ok(matches_value(actual_value, expected_value));
745            }
746        }
747    }
748
749    Ok(true) // No WHERE clause or couldn't parse
750}
751
752/// Check if two values match
753fn matches_value(actual: Option<&Value>, expected: &Value) -> bool {
754    match (actual, expected) {
755        (Some(a), e) => a == e,
756        (None, Value::Null) => true,
757        _ => false,
758    }
759}
760
761/// Apply pagination (LIMIT and OFFSET) to results
762fn apply_json_pagination(
763    records: &[HashMap<String, Value>],
764    query: &str,
765) -> Result<Vec<HashMap<String, Value>>> {
766    let mut result = records.to_vec();
767
768    // Extract LIMIT
769    if let Some(limit_idx) = query.to_uppercase().find("LIMIT") {
770        let limit_str = query[limit_idx + 5..]
771            .split_whitespace()
772            .next()
773            .unwrap_or("")
774            .trim_end_matches(';');
775
776        if let Ok(limit) = limit_str.parse::<usize>() {
777            // Extract OFFSET
778            let offset = if let Some(offset_idx) = query.to_uppercase().find("OFFSET") {
779                query[offset_idx + 6..]
780                    .split_whitespace()
781                    .next()
782                    .unwrap_or("0")
783                    .trim_end_matches(';')
784                    .parse::<usize>()
785                    .unwrap_or(0)
786            } else {
787                0
788            };
789
790            let start = offset.min(result.len());
791            let end = (start + limit).min(result.len());
792            result = result[start..end].to_vec();
793        }
794    }
795
796    Ok(result)
797}
798
799/// Parse INSERT query and return (table_name, record)
800fn parse_insert_query(query: &str, params: &[Value]) -> Result<(String, HashMap<String, Value>)> {
801    // Simple parser: "INSERT INTO table_name (field1, field2) VALUES (?, ?)"
802    let parts: Vec<&str> = query.split_whitespace().collect();
803
804    if let Some(into_idx) = parts.iter().position(|&p| p.to_uppercase() == "INTO") {
805        if into_idx + 1 < parts.len() {
806            let table_name = parts[into_idx + 1].to_string();
807
808            // Extract field names
809            if let Some(fields_start) = query.find('(') {
810                if let Some(fields_end) = query[fields_start + 1..].find(')') {
811                    let fields_str = &query[fields_start + 1..fields_start + 1 + fields_end];
812                    let fields: Vec<&str> = fields_str.split(',').map(|s| s.trim()).collect();
813
814                    // Build record from params
815                    let mut record = HashMap::new();
816                    for (idx, field) in fields.iter().enumerate() {
817                        if idx < params.len() {
818                            record.insert(field.to_string(), params[idx].clone());
819                        }
820                    }
821
822                    return Ok((table_name, record));
823                }
824            }
825        }
826    }
827
828    Err(Error::generic("Invalid INSERT query format".to_string()))
829}
830
831/// Parse UPDATE query
832fn parse_update_query(
833    query: &str,
834    params: &[Value],
835) -> Result<(String, HashMap<String, Value>, String, Vec<Value>)> {
836    // "UPDATE table_name SET field1 = ?, field2 = ? WHERE field3 = ?"
837    let parts: Vec<&str> = query.split_whitespace().collect();
838
839    if parts.len() < 4 || parts[0].to_uppercase() != "UPDATE" {
840        return Err(Error::generic("Invalid UPDATE query".to_string()));
841    }
842
843    let table_name = parts[1].to_string();
844
845    // Extract SET clause
846    if let Some(set_idx) = parts.iter().position(|&p| p.to_uppercase() == "SET") {
847        let set_clause = &query[query.to_uppercase().find("SET").unwrap() + 3..];
848        let where_clause = if let Some(where_idx) = set_clause.to_uppercase().find("WHERE") {
849            &set_clause[..where_idx]
850        } else {
851            set_clause
852        };
853
854        // Parse SET fields
855        let mut updates = HashMap::new();
856        let set_parts: Vec<&str> = where_clause.split(',').collect();
857        let mut param_idx = 0;
858
859        for part in set_parts {
860            let field_eq: Vec<&str> = part.split('=').map(|s| s.trim()).collect();
861            if field_eq.len() == 2 && field_eq[1] == "?" && param_idx < params.len() {
862                updates.insert(field_eq[0].to_string(), params[param_idx].clone());
863                param_idx += 1;
864            }
865        }
866
867        // Extract WHERE clause
868        let (where_clause_str, where_params) =
869            if let Some(where_idx) = set_clause.to_uppercase().find("WHERE") {
870                let where_part = &set_clause[where_idx + 5..];
871                (where_part.to_string(), params[param_idx..].to_vec())
872            } else {
873                (String::new(), Vec::new())
874            };
875
876        return Ok((table_name, updates, where_clause_str, where_params));
877    }
878
879    Err(Error::generic("Invalid UPDATE query: missing SET clause".to_string()))
880}
881
882/// Parse DELETE query
883fn parse_delete_query(query: &str, params: &[Value]) -> Result<(String, String, Vec<Value>)> {
884    // "DELETE FROM table_name WHERE field = ?"
885    let parts: Vec<&str> = query.split_whitespace().collect();
886
887    if let Some(from_idx) = parts.iter().position(|&p| p.to_uppercase() == "FROM") {
888        if from_idx + 1 < parts.len() {
889            let table_name = parts[from_idx + 1].to_string();
890
891            // Extract WHERE clause
892            if let Some(where_idx) = query.to_uppercase().find("WHERE") {
893                let where_clause = query[where_idx + 5..].to_string();
894                return Ok((table_name, where_clause, params.to_vec()));
895            } else {
896                return Ok((table_name, String::new(), Vec::new()));
897            }
898        }
899    }
900
901    Err(Error::generic("Invalid DELETE query".to_string()))
902}
903
904#[cfg(test)]
905mod tests {
906    use super::*;
907    use crate::config::StorageBackend;
908
909    // Helper functions for testing
910    async fn create_test_table(db: &dyn VirtualDatabase) -> Result<()> {
911        let create_sql = "CREATE TABLE IF NOT EXISTS test_users (
912            id TEXT PRIMARY KEY,
913            name TEXT NOT NULL,
914            email TEXT,
915            age INTEGER
916        )";
917        db.create_table(create_sql).await
918    }
919
920    // SqliteDatabase tests
921    #[tokio::test]
922    async fn test_sqlite_database_creation() {
923        let temp_dir = tempfile::tempdir().unwrap();
924        let db_path = temp_dir.path().join("test.db");
925        let result = SqliteDatabase::new(&db_path).await;
926        assert!(result.is_ok());
927    }
928
929    #[tokio::test]
930    async fn test_sqlite_database_connection_info() {
931        let temp_dir = tempfile::tempdir().unwrap();
932        let db_path = temp_dir.path().join("test.db");
933        let db = SqliteDatabase::new(&db_path).await.unwrap();
934        let info = db.connection_info();
935        assert!(info.contains("SQLite"));
936        assert!(info.contains("test.db"));
937    }
938
939    #[tokio::test]
940    async fn test_sqlite_database_initialize() {
941        let temp_dir = tempfile::tempdir().unwrap();
942        let db_path = temp_dir.path().join("test.db");
943        let mut db = SqliteDatabase::new(&db_path).await.unwrap();
944        let result = db.initialize().await;
945        assert!(result.is_ok());
946    }
947
948    #[tokio::test]
949    async fn test_sqlite_create_table() {
950        let temp_dir = tempfile::tempdir().unwrap();
951        let db_path = temp_dir.path().join("test.db");
952        let db = SqliteDatabase::new(&db_path).await.unwrap();
953        let result = create_test_table(&db).await;
954        assert!(result.is_ok());
955    }
956
957    #[tokio::test]
958    async fn test_sqlite_table_exists() {
959        let temp_dir = tempfile::tempdir().unwrap();
960        let db_path = temp_dir.path().join("test.db");
961        let db = SqliteDatabase::new(&db_path).await.unwrap();
962        create_test_table(&db).await.unwrap();
963
964        let exists = db.table_exists("test_users").await.unwrap();
965        assert!(exists);
966
967        let not_exists = db.table_exists("nonexistent_table").await.unwrap();
968        assert!(!not_exists);
969    }
970
971    #[tokio::test]
972    async fn test_sqlite_execute_insert() {
973        let temp_dir = tempfile::tempdir().unwrap();
974        let db_path = temp_dir.path().join("test.db");
975        let db = SqliteDatabase::new(&db_path).await.unwrap();
976        create_test_table(&db).await.unwrap();
977
978        let query = "INSERT INTO test_users (id, name, email, age) VALUES (?, ?, ?, ?)";
979        let params = vec![
980            Value::String("1".to_string()),
981            Value::String("John Doe".to_string()),
982            Value::String("john@example.com".to_string()),
983            Value::Number(30.into()),
984        ];
985
986        let result = db.execute(query, &params).await;
987        assert!(result.is_ok());
988        assert_eq!(result.unwrap(), 1);
989    }
990
991    #[tokio::test]
992    async fn test_sqlite_execute_with_id() {
993        let temp_dir = tempfile::tempdir().unwrap();
994        let db_path = temp_dir.path().join("test.db");
995        let db = SqliteDatabase::new(&db_path).await.unwrap();
996        create_test_table(&db).await.unwrap();
997
998        let query = "INSERT INTO test_users (id, name, email) VALUES (?, ?, ?)";
999        let params = vec![
1000            Value::String("test-id".to_string()),
1001            Value::String("Jane Doe".to_string()),
1002            Value::String("jane@example.com".to_string()),
1003        ];
1004
1005        let result = db.execute_with_id(query, &params).await;
1006        assert!(result.is_ok());
1007    }
1008
1009    #[tokio::test]
1010    async fn test_sqlite_query_select() {
1011        let temp_dir = tempfile::tempdir().unwrap();
1012        let db_path = temp_dir.path().join("test.db");
1013        let db = SqliteDatabase::new(&db_path).await.unwrap();
1014        create_test_table(&db).await.unwrap();
1015
1016        // Insert test data
1017        let insert_query = "INSERT INTO test_users (id, name, email) VALUES (?, ?, ?)";
1018        db.execute(
1019            insert_query,
1020            &[
1021                Value::String("1".to_string()),
1022                Value::String("Test User".to_string()),
1023                Value::String("test@example.com".to_string()),
1024            ],
1025        )
1026        .await
1027        .unwrap();
1028
1029        // Query data
1030        let select_query = "SELECT * FROM test_users WHERE id = ?";
1031        let results = db.query(select_query, &[Value::String("1".to_string())]).await;
1032        assert!(results.is_ok());
1033        let rows = results.unwrap();
1034        assert_eq!(rows.len(), 1);
1035        assert_eq!(rows[0].get("id").unwrap().as_str().unwrap(), "1");
1036        assert_eq!(rows[0].get("name").unwrap().as_str().unwrap(), "Test User");
1037    }
1038
1039    #[tokio::test]
1040    async fn test_sqlite_execute_update() {
1041        let temp_dir = tempfile::tempdir().unwrap();
1042        let db_path = temp_dir.path().join("test.db");
1043        let db = SqliteDatabase::new(&db_path).await.unwrap();
1044        create_test_table(&db).await.unwrap();
1045
1046        // Insert
1047        db.execute(
1048            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1049            &[
1050                Value::String("1".to_string()),
1051                Value::String("Original Name".to_string()),
1052            ],
1053        )
1054        .await
1055        .unwrap();
1056
1057        // Update
1058        let update_result = db
1059            .execute(
1060                "UPDATE test_users SET name = ? WHERE id = ?",
1061                &[
1062                    Value::String("Updated Name".to_string()),
1063                    Value::String("1".to_string()),
1064                ],
1065            )
1066            .await;
1067
1068        assert!(update_result.is_ok());
1069        assert_eq!(update_result.unwrap(), 1);
1070
1071        // Verify update
1072        let rows = db
1073            .query("SELECT name FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1074            .await
1075            .unwrap();
1076        assert_eq!(rows[0].get("name").unwrap().as_str().unwrap(), "Updated Name");
1077    }
1078
1079    #[tokio::test]
1080    async fn test_sqlite_execute_delete() {
1081        let temp_dir = tempfile::tempdir().unwrap();
1082        let db_path = temp_dir.path().join("test.db");
1083        let db = SqliteDatabase::new(&db_path).await.unwrap();
1084        create_test_table(&db).await.unwrap();
1085
1086        // Insert
1087        db.execute(
1088            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1089            &[
1090                Value::String("1".to_string()),
1091                Value::String("Test".to_string()),
1092            ],
1093        )
1094        .await
1095        .unwrap();
1096
1097        // Delete
1098        let delete_result = db
1099            .execute("DELETE FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1100            .await;
1101        assert!(delete_result.is_ok());
1102        assert_eq!(delete_result.unwrap(), 1);
1103
1104        // Verify deletion
1105        let rows = db
1106            .query("SELECT * FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1107            .await
1108            .unwrap();
1109        assert_eq!(rows.len(), 0);
1110    }
1111
1112    #[tokio::test]
1113    async fn test_sqlite_close() {
1114        let temp_dir = tempfile::tempdir().unwrap();
1115        let db_path = temp_dir.path().join("test.db");
1116        let mut db = SqliteDatabase::new(&db_path).await.unwrap();
1117        let result = db.close().await;
1118        assert!(result.is_ok());
1119    }
1120
1121    // JsonDatabase tests
1122    #[tokio::test]
1123    async fn test_json_database_creation() {
1124        let temp_dir = tempfile::tempdir().unwrap();
1125        let db_path = temp_dir.path().join("test.json");
1126        let result = JsonDatabase::new(&db_path).await;
1127        assert!(result.is_ok());
1128    }
1129
1130    #[tokio::test]
1131    async fn test_json_database_connection_info() {
1132        let temp_dir = tempfile::tempdir().unwrap();
1133        let db_path = temp_dir.path().join("test.json");
1134        let db = JsonDatabase::new(&db_path).await.unwrap();
1135        let info = db.connection_info();
1136        assert!(info.contains("JSON"));
1137        assert!(info.contains("test.json"));
1138    }
1139
1140    #[tokio::test]
1141    async fn test_json_database_initialize() {
1142        let temp_dir = tempfile::tempdir().unwrap();
1143        let db_path = temp_dir.path().join("test.json");
1144        let mut db = JsonDatabase::new(&db_path).await.unwrap();
1145        let result = db.initialize().await;
1146        assert!(result.is_ok());
1147    }
1148
1149    #[tokio::test]
1150    async fn test_json_create_table() {
1151        let temp_dir = tempfile::tempdir().unwrap();
1152        let db_path = temp_dir.path().join("test.json");
1153        let db = JsonDatabase::new(&db_path).await.unwrap();
1154        let result = db.create_table("CREATE TABLE test_users (id TEXT, name TEXT)").await;
1155        assert!(result.is_ok());
1156    }
1157
1158    #[tokio::test]
1159    async fn test_json_table_exists() {
1160        let temp_dir = tempfile::tempdir().unwrap();
1161        let db_path = temp_dir.path().join("test.json");
1162        let db = JsonDatabase::new(&db_path).await.unwrap();
1163
1164        // Table doesn't exist initially
1165        assert!(!db.table_exists("test_users").await.unwrap());
1166
1167        // Insert a record (creates the table)
1168        db.execute(
1169            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1170            &[
1171                Value::String("1".to_string()),
1172                Value::String("Test".to_string()),
1173            ],
1174        )
1175        .await
1176        .unwrap();
1177
1178        // Now table should exist
1179        assert!(db.table_exists("test_users").await.unwrap());
1180    }
1181
1182    #[tokio::test]
1183    async fn test_json_execute_insert() {
1184        let temp_dir = tempfile::tempdir().unwrap();
1185        let db_path = temp_dir.path().join("test.json");
1186        let db = JsonDatabase::new(&db_path).await.unwrap();
1187
1188        let query = "INSERT INTO test_users (id, name, email) VALUES (?, ?, ?)";
1189        let params = vec![
1190            Value::String("1".to_string()),
1191            Value::String("John Doe".to_string()),
1192            Value::String("john@example.com".to_string()),
1193        ];
1194
1195        let result = db.execute(query, &params).await;
1196        assert!(result.is_ok());
1197        assert_eq!(result.unwrap(), 1);
1198    }
1199
1200    #[tokio::test]
1201    async fn test_json_execute_with_id() {
1202        let temp_dir = tempfile::tempdir().unwrap();
1203        let db_path = temp_dir.path().join("test.json");
1204        let db = JsonDatabase::new(&db_path).await.unwrap();
1205
1206        let query = "INSERT INTO test_users (name, email) VALUES (?, ?)";
1207        let params = vec![
1208            Value::String("Jane Doe".to_string()),
1209            Value::String("jane@example.com".to_string()),
1210        ];
1211
1212        let result = db.execute_with_id(query, &params).await;
1213        assert!(result.is_ok());
1214        // Should return auto-generated ID
1215        assert!(!result.unwrap().is_empty());
1216    }
1217
1218    #[tokio::test]
1219    async fn test_json_query_select() {
1220        let temp_dir = tempfile::tempdir().unwrap();
1221        let db_path = temp_dir.path().join("test.json");
1222        let db = JsonDatabase::new(&db_path).await.unwrap();
1223
1224        // Insert test data
1225        db.execute(
1226            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1227            &[
1228                Value::String("1".to_string()),
1229                Value::String("Test User".to_string()),
1230            ],
1231        )
1232        .await
1233        .unwrap();
1234
1235        // Query data
1236        let results = db
1237            .query("SELECT * FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1238            .await;
1239        assert!(results.is_ok());
1240        let rows = results.unwrap();
1241        assert_eq!(rows.len(), 1);
1242        assert_eq!(rows[0].get("id").unwrap().as_str().unwrap(), "1");
1243    }
1244
1245    #[tokio::test]
1246    async fn test_json_query_count() {
1247        let temp_dir = tempfile::tempdir().unwrap();
1248        let db_path = temp_dir.path().join("test.json");
1249        let db = JsonDatabase::new(&db_path).await.unwrap();
1250
1251        // Insert multiple records
1252        db.execute(
1253            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1254            &[
1255                Value::String("1".to_string()),
1256                Value::String("User 1".to_string()),
1257            ],
1258        )
1259        .await
1260        .unwrap();
1261        db.execute(
1262            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1263            &[
1264                Value::String("2".to_string()),
1265                Value::String("User 2".to_string()),
1266            ],
1267        )
1268        .await
1269        .unwrap();
1270
1271        // Query count
1272        let results = db.query("SELECT COUNT(*) FROM test_users", &[]).await;
1273        assert!(results.is_ok());
1274        let rows = results.unwrap();
1275        assert_eq!(rows.len(), 1);
1276        assert_eq!(rows[0].get("count").unwrap().as_u64().unwrap(), 2);
1277    }
1278
1279    #[tokio::test]
1280    async fn test_json_execute_update() {
1281        let temp_dir = tempfile::tempdir().unwrap();
1282        let db_path = temp_dir.path().join("test.json");
1283        let db = JsonDatabase::new(&db_path).await.unwrap();
1284
1285        // Insert
1286        db.execute(
1287            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1288            &[
1289                Value::String("1".to_string()),
1290                Value::String("Original".to_string()),
1291            ],
1292        )
1293        .await
1294        .unwrap();
1295
1296        // Update
1297        let update_result = db
1298            .execute(
1299                "UPDATE test_users SET name = ? WHERE id = ?",
1300                &[
1301                    Value::String("Updated".to_string()),
1302                    Value::String("1".to_string()),
1303                ],
1304            )
1305            .await;
1306
1307        assert!(update_result.is_ok());
1308        assert_eq!(update_result.unwrap(), 1);
1309    }
1310
1311    #[tokio::test]
1312    async fn test_json_execute_delete() {
1313        let temp_dir = tempfile::tempdir().unwrap();
1314        let db_path = temp_dir.path().join("test.json");
1315        let db = JsonDatabase::new(&db_path).await.unwrap();
1316
1317        // Insert
1318        db.execute(
1319            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1320            &[
1321                Value::String("1".to_string()),
1322                Value::String("Test".to_string()),
1323            ],
1324        )
1325        .await
1326        .unwrap();
1327
1328        // Delete
1329        let delete_result = db
1330            .execute("DELETE FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1331            .await;
1332        assert!(delete_result.is_ok());
1333        assert_eq!(delete_result.unwrap(), 1);
1334    }
1335
1336    #[tokio::test]
1337    async fn test_json_close() {
1338        let temp_dir = tempfile::tempdir().unwrap();
1339        let db_path = temp_dir.path().join("test.json");
1340        let mut db = JsonDatabase::new(&db_path).await.unwrap();
1341        let result = db.close().await;
1342        assert!(result.is_ok());
1343    }
1344
1345    // InMemoryDatabase tests
1346    #[tokio::test]
1347    async fn test_inmemory_database_creation() {
1348        let result = InMemoryDatabase::new().await;
1349        assert!(result.is_ok());
1350    }
1351
1352    #[tokio::test]
1353    async fn test_inmemory_database_connection_info() {
1354        let db = InMemoryDatabase::new().await.unwrap();
1355        let info = db.connection_info();
1356        assert_eq!(info, "In-Memory");
1357    }
1358
1359    #[tokio::test]
1360    async fn test_inmemory_database_initialize() {
1361        let mut db = InMemoryDatabase::new().await.unwrap();
1362        let result = db.initialize().await;
1363        assert!(result.is_ok());
1364    }
1365
1366    #[tokio::test]
1367    async fn test_inmemory_create_table() {
1368        let db = InMemoryDatabase::new().await.unwrap();
1369        let result = db.create_table("CREATE TABLE test_users (id TEXT, name TEXT)").await;
1370        assert!(result.is_ok());
1371    }
1372
1373    #[tokio::test]
1374    async fn test_inmemory_table_exists() {
1375        let db = InMemoryDatabase::new().await.unwrap();
1376
1377        // Create table
1378        db.create_table("CREATE TABLE test_users (id TEXT)").await.unwrap();
1379
1380        // Table should exist
1381        assert!(db.table_exists("test_users").await.unwrap());
1382        assert!(!db.table_exists("nonexistent").await.unwrap());
1383    }
1384
1385    #[tokio::test]
1386    async fn test_inmemory_execute_insert() {
1387        let db = InMemoryDatabase::new().await.unwrap();
1388
1389        let query = "INSERT INTO test_users (id, name) VALUES (?, ?)";
1390        let params = vec![
1391            Value::String("1".to_string()),
1392            Value::String("John Doe".to_string()),
1393        ];
1394
1395        let result = db.execute(query, &params).await;
1396        assert!(result.is_ok());
1397        assert_eq!(result.unwrap(), 1);
1398    }
1399
1400    #[tokio::test]
1401    async fn test_inmemory_execute_with_id() {
1402        let db = InMemoryDatabase::new().await.unwrap();
1403
1404        let query = "INSERT INTO test_users (name) VALUES (?)";
1405        let params = vec![Value::String("Jane Doe".to_string())];
1406
1407        let result = db.execute_with_id(query, &params).await;
1408        assert!(result.is_ok());
1409        assert!(!result.unwrap().is_empty());
1410    }
1411
1412    #[tokio::test]
1413    async fn test_inmemory_query_select() {
1414        let db = InMemoryDatabase::new().await.unwrap();
1415
1416        // Insert
1417        db.execute(
1418            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1419            &[
1420                Value::String("1".to_string()),
1421                Value::String("Test User".to_string()),
1422            ],
1423        )
1424        .await
1425        .unwrap();
1426
1427        // Query
1428        let results = db
1429            .query("SELECT * FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1430            .await;
1431        assert!(results.is_ok());
1432        let rows = results.unwrap();
1433        assert_eq!(rows.len(), 1);
1434    }
1435
1436    #[tokio::test]
1437    async fn test_inmemory_query_count() {
1438        let db = InMemoryDatabase::new().await.unwrap();
1439
1440        // Insert multiple
1441        db.execute(
1442            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1443            &[
1444                Value::String("1".to_string()),
1445                Value::String("User 1".to_string()),
1446            ],
1447        )
1448        .await
1449        .unwrap();
1450        db.execute(
1451            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1452            &[
1453                Value::String("2".to_string()),
1454                Value::String("User 2".to_string()),
1455            ],
1456        )
1457        .await
1458        .unwrap();
1459
1460        // Count
1461        let results = db.query("SELECT COUNT(*) FROM test_users", &[]).await;
1462        assert!(results.is_ok());
1463        let rows = results.unwrap();
1464        assert_eq!(rows[0].get("count").unwrap().as_u64().unwrap(), 2);
1465    }
1466
1467    #[tokio::test]
1468    async fn test_inmemory_execute_update() {
1469        let db = InMemoryDatabase::new().await.unwrap();
1470
1471        // Insert
1472        db.execute(
1473            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1474            &[
1475                Value::String("1".to_string()),
1476                Value::String("Original".to_string()),
1477            ],
1478        )
1479        .await
1480        .unwrap();
1481
1482        // Update
1483        let result = db
1484            .execute(
1485                "UPDATE test_users SET name = ? WHERE id = ?",
1486                &[
1487                    Value::String("Updated".to_string()),
1488                    Value::String("1".to_string()),
1489                ],
1490            )
1491            .await;
1492
1493        assert!(result.is_ok());
1494        assert_eq!(result.unwrap(), 1);
1495    }
1496
1497    #[tokio::test]
1498    async fn test_inmemory_execute_delete() {
1499        let db = InMemoryDatabase::new().await.unwrap();
1500
1501        // Insert
1502        db.execute(
1503            "INSERT INTO test_users (id, name) VALUES (?, ?)",
1504            &[
1505                Value::String("1".to_string()),
1506                Value::String("Test".to_string()),
1507            ],
1508        )
1509        .await
1510        .unwrap();
1511
1512        // Delete
1513        let result = db
1514            .execute("DELETE FROM test_users WHERE id = ?", &[Value::String("1".to_string())])
1515            .await;
1516        assert!(result.is_ok());
1517        assert_eq!(result.unwrap(), 1);
1518    }
1519
1520    #[tokio::test]
1521    async fn test_inmemory_close() {
1522        let mut db = InMemoryDatabase::new().await.unwrap();
1523        let result = db.close().await;
1524        assert!(result.is_ok());
1525    }
1526
1527    // create_database tests
1528    #[tokio::test]
1529    async fn test_create_database_sqlite() {
1530        let temp_dir = tempfile::tempdir().unwrap();
1531        let db_path = temp_dir.path().join("test.db");
1532        let backend = StorageBackend::Sqlite {
1533            path: db_path.clone(),
1534        };
1535        let result = create_database(&backend).await;
1536        assert!(result.is_ok());
1537        let db = result.unwrap();
1538        assert!(db.connection_info().contains("SQLite"));
1539    }
1540
1541    #[tokio::test]
1542    async fn test_create_database_json() {
1543        let temp_dir = tempfile::tempdir().unwrap();
1544        let db_path = temp_dir.path().join("test.json");
1545        let backend = StorageBackend::Json {
1546            path: db_path.clone(),
1547        };
1548        let result = create_database(&backend).await;
1549        assert!(result.is_ok());
1550        let db = result.unwrap();
1551        assert!(db.connection_info().contains("JSON"));
1552    }
1553
1554    #[tokio::test]
1555    async fn test_create_database_memory() {
1556        let backend = StorageBackend::Memory;
1557        let result = create_database(&backend).await;
1558        assert!(result.is_ok());
1559        let db = result.unwrap();
1560        assert_eq!(db.connection_info(), "In-Memory");
1561    }
1562
1563    // Helper function tests
1564    #[test]
1565    fn test_extract_table_name_from_select() {
1566        let query = "SELECT * FROM users";
1567        let result = extract_table_name_from_select(query);
1568        assert!(result.is_ok());
1569        assert_eq!(result.unwrap(), "users");
1570    }
1571
1572    #[test]
1573    fn test_extract_table_name_from_select_with_where() {
1574        let query = "SELECT * FROM products WHERE price > 10";
1575        let result = extract_table_name_from_select(query);
1576        assert!(result.is_ok());
1577        assert_eq!(result.unwrap(), "products");
1578    }
1579
1580    #[test]
1581    fn test_extract_table_name_from_select_invalid() {
1582        let query = "SELECT * users";
1583        let result = extract_table_name_from_select(query);
1584        assert!(result.is_err());
1585    }
1586
1587    #[test]
1588    fn test_parse_insert_query() {
1589        let query = "INSERT INTO users (id, name) VALUES (?, ?)";
1590        let params = vec![
1591            Value::String("1".to_string()),
1592            Value::String("John".to_string()),
1593        ];
1594        let result = parse_insert_query(query, &params);
1595        assert!(result.is_ok());
1596        let (table_name, record) = result.unwrap();
1597        assert_eq!(table_name, "users");
1598        assert_eq!(record.len(), 2);
1599        assert_eq!(record.get("id").unwrap().as_str().unwrap(), "1");
1600    }
1601
1602    #[test]
1603    fn test_parse_insert_query_invalid() {
1604        let query = "INSERT users VALUES (?)";
1605        let params = vec![Value::String("1".to_string())];
1606        let result = parse_insert_query(query, &params);
1607        assert!(result.is_err());
1608    }
1609
1610    #[test]
1611    fn test_parse_update_query() {
1612        let query = "UPDATE users SET name = ? WHERE id = ?";
1613        let params = vec![
1614            Value::String("John".to_string()),
1615            Value::String("1".to_string()),
1616        ];
1617        let result = parse_update_query(query, &params);
1618        assert!(result.is_ok());
1619        let (table_name, updates, _where_clause, _where_params) = result.unwrap();
1620        assert_eq!(table_name, "users");
1621        assert_eq!(updates.len(), 1);
1622    }
1623
1624    #[test]
1625    fn test_parse_delete_query() {
1626        let query = "DELETE FROM users WHERE id = ?";
1627        let params = vec![Value::String("1".to_string())];
1628        let result = parse_delete_query(query, &params);
1629        assert!(result.is_ok());
1630        let (table_name, _where_clause, where_params) = result.unwrap();
1631        assert_eq!(table_name, "users");
1632        assert_eq!(where_params.len(), 1);
1633    }
1634
1635    #[test]
1636    fn test_matches_value() {
1637        assert!(matches_value(
1638            Some(&Value::String("test".to_string())),
1639            &Value::String("test".to_string())
1640        ));
1641        assert!(!matches_value(
1642            Some(&Value::String("test".to_string())),
1643            &Value::String("other".to_string())
1644        ));
1645        assert!(matches_value(None, &Value::Null));
1646        assert!(!matches_value(None, &Value::String("test".to_string())));
1647    }
1648
1649    #[tokio::test]
1650    async fn test_json_pagination() {
1651        let temp_dir = tempfile::tempdir().unwrap();
1652        let db_path = temp_dir.path().join("test.json");
1653        let db = JsonDatabase::new(&db_path).await.unwrap();
1654
1655        // Insert multiple records
1656        for i in 1..=5 {
1657            db.execute(
1658                "INSERT INTO test_users (id, name) VALUES (?, ?)",
1659                &[
1660                    Value::String(i.to_string()),
1661                    Value::String(format!("User {}", i)),
1662                ],
1663            )
1664            .await
1665            .unwrap();
1666        }
1667
1668        // Query with LIMIT
1669        let results = db.query("SELECT * FROM test_users LIMIT 2", &[]).await.unwrap();
1670        assert_eq!(results.len(), 2);
1671
1672        // Query with LIMIT and OFFSET
1673        let results = db.query("SELECT * FROM test_users LIMIT 2 OFFSET 2", &[]).await.unwrap();
1674        assert_eq!(results.len(), 2);
1675    }
1676
1677    #[tokio::test]
1678    async fn test_inmemory_pagination() {
1679        let db = InMemoryDatabase::new().await.unwrap();
1680
1681        // Insert multiple records
1682        for i in 1..=5 {
1683            db.execute(
1684                "INSERT INTO test_users (id, name) VALUES (?, ?)",
1685                &[
1686                    Value::String(i.to_string()),
1687                    Value::String(format!("User {}", i)),
1688                ],
1689            )
1690            .await
1691            .unwrap();
1692        }
1693
1694        // Query with LIMIT
1695        let results = db.query("SELECT * FROM test_users LIMIT 2", &[]).await.unwrap();
1696        assert_eq!(results.len(), 2);
1697
1698        // Query with LIMIT and OFFSET
1699        let results = db.query("SELECT * FROM test_users LIMIT 2 OFFSET 2", &[]).await.unwrap();
1700        assert_eq!(results.len(), 2);
1701    }
1702}