vibesql/
connection.rs

1//! Database connection implementation
2//!
3//! This module provides the Database class for establishing connections
4//! to the in-memory vibesql database following DB-API 2.0 conventions.
5
6use std::sync::Arc;
7
8use parking_lot::Mutex;
9use pyo3::prelude::*;
10
11use crate::cursor::Cursor;
12
13/// Database connection object
14///
15/// Represents a connection to an in-memory vibesql database.
16/// Follows DB-API 2.0 conventions for database connections.
17///
18/// # Example
19/// ```python
20/// db = vibesql.connect()
21/// cursor = db.cursor()
22/// cursor.execute("SELECT 1")
23/// ```
24#[pyclass]
25pub struct Database {
26    pub(crate) db: Arc<Mutex<vibesql_storage::Database>>,
27}
28
29#[pymethods]
30impl Database {
31    /// Create a new database connection
32    ///
33    /// # Returns
34    /// A new Database instance with an empty in-memory database.
35    #[new]
36    pub fn new() -> Self {
37        Database { db: Arc::new(Mutex::new(vibesql_storage::Database::new())) }
38    }
39
40    /// Create a cursor for executing queries
41    ///
42    /// # Returns
43    /// A new Cursor object for executing SQL statements and fetching results.
44    fn cursor(&self) -> PyResult<Cursor> {
45        Cursor::new(Arc::clone(&self.db))
46    }
47
48    /// Close the database connection
49    ///
50    /// For in-memory databases, this is a no-op but provided for DB-API 2.0 compatibility.
51    fn close(&self) -> PyResult<()> {
52        // In-memory database, no cleanup needed
53        Ok(())
54    }
55
56    /// Commit the current transaction
57    ///
58    /// For in-memory databases without transaction support, this is a no-op
59    /// but provided for DB-API 2.0 compatibility.
60    fn commit(&self) -> PyResult<()> {
61        // In-memory database, no transaction needed
62        Ok(())
63    }
64
65    /// Get version string
66    ///
67    /// # Returns
68    /// A string containing the version identifier.
69    fn version(&self) -> String {
70        "vibesql-py 0.1.0".to_string()
71    }
72
73    /// Save database to SQL dump file
74    ///
75    /// Generates a SQL dump file containing all schemas, tables, indexes,
76    /// roles, and data needed to recreate the current database state.
77    ///
78    /// # Arguments
79    /// * `path` - Path where the SQL dump file will be created
80    ///
81    /// # Example
82    /// ```python
83    /// db = vibesql.connect()
84    /// cursor = db.cursor()
85    /// cursor.execute("CREATE TABLE users (id INTEGER, name TEXT)")
86    /// cursor.execute("INSERT INTO users VALUES (1, 'Alice')")
87    /// db.save("mydata.vbsql")
88    /// ```
89    fn save(&self, path: &str) -> PyResult<()> {
90        // Use binary format to preserve sequences and column defaults (for AUTOINCREMENT)
91        self.db.lock().save(path).map_err(|e| {
92            pyo3::exceptions::PyIOError::new_err(format!("Failed to save database: {}", e))
93        })
94    }
95
96    /// Load database from binary file
97    ///
98    /// Creates a new Database instance by loading binary database file.
99    /// This preserves sequences and column defaults for AUTOINCREMENT support.
100    /// This is a static method that returns a new Database.
101    ///
102    /// # Arguments
103    /// * `path` - Path to the binary database file (.vbsql)
104    ///
105    /// # Returns
106    /// A new Database instance with the loaded state
107    ///
108    /// # Example
109    /// ```python
110    /// # Save a database
111    /// db1 = vibesql.connect()
112    /// cursor = db1.cursor()
113    /// cursor.execute("CREATE TABLE users (id INTEGER, name TEXT)")
114    /// db1.save("mydata.vbsql")
115    ///
116    /// # Load it later
117    /// db2 = vibesql.Database.load("mydata.vbsql")
118    /// cursor2 = db2.cursor()
119    /// cursor2.execute("SELECT * FROM users")
120    /// ```
121    #[staticmethod]
122    fn load(path: &str) -> PyResult<Database> {
123        // Use default format (compressed or uncompressed binary) to preserve
124        // sequences and column defaults (for AUTOINCREMENT)
125        let db = vibesql_storage::Database::load(path).map_err(|e| {
126            pyo3::exceptions::PyIOError::new_err(format!("Failed to load database: {}", e))
127        })?;
128        Ok(Database { db: Arc::new(Mutex::new(db)) })
129    }
130}