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