Skip to main content

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