Skip to main content

sqlmodel_sqlite/
lib.rs

1//! SQLite driver for SQLModel Rust.
2//!
3//! `sqlmodel-sqlite` is the **SQLite driver** for the SQLModel ecosystem. It implements
4//! the `Connection` trait from `sqlmodel-core`, providing a lightweight backend that is
5//! ideal for local development, embedded use, and testing.
6//!
7//! # Role In The Architecture
8//!
9//! - Implements `sqlmodel-core::Connection` for SQLite
10//! - Supplies FFI-backed execution and type conversion
11//! - Enables `sqlmodel-query` and `sqlmodel-session` to run against SQLite
12//!
13// FFI bindings require unsafe code - this is expected for database drivers
14#![allow(unsafe_code)]
15//!
16//! This crate provides a SQLite database driver using FFI bindings to libsqlite3.
17//! It implements the `Connection` trait from sqlmodel-core for seamless integration
18//! with the rest of the SQLModel ecosystem.
19//!
20//! # Features
21//!
22//! - Full Connection trait implementation
23//! - Transaction support with savepoints
24//! - Type-safe parameter binding
25//! - In-memory and file-based databases
26//! - Configurable open flags and busy timeout
27//!
28//! # Example
29//!
30//! ```rust,ignore
31//! use sqlmodel_sqlite::{SqliteConnection, SqliteConfig};
32//! use sqlmodel_core::{Connection, Value, Cx, Outcome};
33//!
34//! // Open an in-memory database
35//! let conn = SqliteConnection::open_memory().unwrap();
36//!
37//! // Create a table
38//! conn.execute_raw("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)").unwrap();
39//!
40//! // Insert data using the Connection trait
41//! let cx = Cx::for_testing();
42//! match conn.insert(&cx, "INSERT INTO users (name) VALUES (?)", &[Value::Text("Alice".into())]).await {
43//!     Outcome::Ok(id) => println!("Inserted user with id: {}", id),
44//!     Outcome::Err(e) => eprintln!("Error: {}", e),
45//!     _ => {}
46//! }
47//! ```
48//!
49//! # Type Mapping
50//!
51//! | Rust Type | SQLite Type |
52//! |-----------|-------------|
53//! | `bool` | INTEGER (0/1) |
54//! | `i8`, `i16`, `i32` | INTEGER |
55//! | `i64` | INTEGER |
56//! | `f32`, `f64` | REAL |
57//! | `String` | TEXT |
58//! | `Vec<u8>` | BLOB |
59//! | `Option<T>` | NULL or T |
60//! | `Date`, `Time`, `Timestamp` | TEXT (ISO-8601) |
61//! | `Uuid` | BLOB (16 bytes) |
62//! | `Json` | TEXT |
63//!
64//! # Thread Safety
65//!
66//! `SqliteConnection` is both `Send` and `Sync`, using internal mutex
67//! synchronization to protect the underlying SQLite handle. This allows
68//! connections to be shared across async tasks safely.
69
70// Keep libsqlite3-sys linked so its bundled SQLite build script owns the native
71// library search path for the manual FFI declarations in ffi.rs.
72extern crate libsqlite3_sys as _;
73
74pub mod connection;
75pub mod ffi;
76pub mod types;
77
78pub use connection::{
79    OpenFlags, SqliteConfig, SqliteConnection, SqliteErrorCode, SqliteTransaction,
80    sqlite_error_code,
81};
82
83// Console integration (feature-gated)
84#[cfg(feature = "console")]
85pub use sqlmodel_console::ConsoleAware;
86
87/// Re-export the SQLite library version.
88pub fn sqlite_version() -> &'static str {
89    ffi::version()
90}
91
92/// Re-export the SQLite library version number.
93pub fn sqlite_version_number() -> i32 {
94    ffi::version_number()
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn test_sqlite_version() {
103        let version = sqlite_version();
104        assert!(
105            version.starts_with('3'),
106            "Expected SQLite 3.x, got {}",
107            version
108        );
109    }
110
111    #[test]
112    fn test_sqlite_version_number() {
113        let num = sqlite_version_number();
114        assert!(
115            num >= 3_000_000,
116            "Expected SQLite 3.x.x (>= 3000000), got {}",
117            num
118        );
119    }
120}