Rusqlite Integration
Relevant source files
The following files were used as context for generating this wiki page:
The Rusqlite integration within sea-schema provides a synchronous interface for database schema discovery and execution, specifically tailored for SQLite. While the core library is built around asynchronous patterns (often using SQLx), the sea-schema-sync crate utilizes Rusqlite to allow developers to perform schema-related operations in a blocking environment. This is achieved through a set of wrapper types and transformation scripts that map standard database interactions to the Rusqlite driver.
Sources: sea-schema-sync/Cargo.toml:35-36, src/lib.rs:18-22, build-tools/make-sync.sh:22-26
Core Architecture and Wrapper Types
The integration is centered around the rusqlite_types module, which abstracts the underlying Rusqlite library into types compatible with the sea-schema definition system. This module provides a bridge between the raw rusqlite::Row and the internal representation used for schema discovery.
RusqliteRow Structure
The RusqliteRow struct serves as the primary data container for query results. It encapsulates a vector of rusqlite::types::Value objects, allowing for indexed access and type conversion via the get method.
The diagram above shows the structure of the RusqliteRow wrapper used to handle database records synchronously.
Sources: src/rusqlite_types/real.rs:10-39
Shared Type Aliases
To maintain consistency between async and sync versions of the library, several aliases and re-exports are provided:
| Type Alias | Underlying Type | Purpose |
|---|---|---|
Row | RusqliteRow | Standardized row interface |
RusqliteConnection | rusqlite::Connection | Blocking database connection |
RusqliteError | rusqlite::Error | Driver-specific error handling |
Sources: src/rusqlite_types/real.rs:1-8
Schema Discovery and Mapping
The integration enables the translation of SQLite-specific metadata (retrieved via PRAGMA statements) into high-level SeaSchema definitions like ColumnInfo, IndexInfo, and ForeignKeysInfo.
Column Definition Mapping
The to_column_def function is critical for converting a RusqliteRow into a ColumnInfo struct. This process involves parsing SQLite's internal column metadata, including default values and primary key status.
This flowchart illustrates the logic used to map a row from a PRAGMA table_info query to the internal ColumnInfo representation.
Sources: sea-schema-sync/src/sqlite/def/column.rs:24-55
Connection Management
Database connections are established using the connect_sqlite utility, which handles URL parsing to support both file-based and in-memory SQLite instances.
connect_sqlite(url: &str): Opens a connection by trimmingsqlite://orsqlite:prefixes from the connection string.execute_sqlite(conn: &RusqliteConnection, sql: &str): Provides a simplified interface for executing batch SQL statements synchronously.
Sources: src/rusqlite_types/real.rs:46-57
Implementation in Discovery Workflows
In practice, the Rusqlite integration is used by the SchemaDiscovery engine to populate the Schema object. This process involves executing multiple queries to gather table names, column details, and index structures.
Example Workflow
- Establish a connection via
connect_sqlite. - Initialize
SchemaDiscoverywith the connection. - Call
.discover()to trigger the synchronous retrieval of metadata.
// Derived from test implementation
let url = "sqlite::memory:";
let connection = connect_sqlite(&url).unwrap();
let schema_discovery = SchemaDiscovery::new(connection);
let schema = schema_discovery.discover()?;
Sources: sea-schema-sync/tests/live/sqlite/src/main.rs:189-196
Discovery Components Summarized
| Component | Functionality | Source File |
|---|---|---|
SchemaDiscovery | Entry point for discovering the entire database structure | sea-schema-sync/tests/live/sqlite/src/main.rs |
ColumnInfo | Maps cid, name, type, and constraints from PRAGMA | sea-schema-sync/src/sqlite/def/column.rs |
IndexInfo | Maps index names and uniqueness from sqlite_master | sea-schema-sync/src/sqlite/def/column.rs |
ForeignKeysInfo | Maps FK relations including on_update and on_delete actions | sea-schema-sync/src/sqlite/def/column.rs |
Sources: sea-schema-sync/src/sqlite/def/column.rs:10-22, 106-114, 212-226
Conclusion
The Rusqlite integration is a vital component of the sea-schema-sync ecosystem, enabling robust, blocking schema discovery for SQLite. By wrapping Rusqlite's native types and providing a consistent mapping logic for SQLite's metadata, it allows the SeaQL suite to support environments where asynchronous execution is not preferred or required. The architecture ensures that the same high-level schema definitions are produced regardless of whether the underlying driver is async (SQLx) or sync (Rusqlite).
Sources: build-tools/make-sync.sh:1-30, sea-schema-sync/Cargo.toml:1-15