Rust Database Providers
TeaQL Rust separates generated business APIs from storage execution. The same generated domain API can target PostgreSQL, MySQL, SQLite, embedded SQLite, or an in-memory repository depending on the provider.
Read Rust Overview first if you need the runtime and generated-crate context. Read Java Parity & Generator if you need to understand how Rust maps the Java TeaQL programming model.
Overview
Provider support is centered on these runtime targets:
| Provider | When to use |
|---|---|
| SQLx PostgreSQL | Production-grade server backends, complex queries, transactions, aggregation analysis |
| SQLx MySQL | Enterprise MySQL backends and migration scenarios |
| SQLx SQLite | Local-first apps, tests, small services |
| rusqlite SQLite | Embedded, router, edge devices, synchronous execution, small dependency footprint |
| MemoryRepository | Unit tests, no-database demos, fast model validation |
Provider Architecture
Generated Q API
-> generated service crate
-> RuntimeModule / module()
-> UserContext
-> Repository API
-> Provider
-> Database or memory store
The generated API should not care whether the underlying execution target is PostgreSQL, MySQL, SQLite, rusqlite, or memory. Provider selection is an infrastructure decision made during runtime assembly.
SQLx PostgreSQL
Use SQLx PostgreSQL for production server-side backends where you need mature PostgreSQL operations, transactions, aggregation, and predictable async execution.
Best fit:
- Multi-user backend services
- Complex business systems
- Reporting and aggregation paths
- Production databases with migration discipline
SQLx MySQL
Use SQLx MySQL when the business system already standardizes on MySQL or when the migration path is from a MySQL-centric enterprise stack.
Best fit:
- Enterprise MySQL applications
- Business systems moving from handwritten MyBatis-style persistence
- Standard async backend services
SQLx SQLite
Use SQLx SQLite for local-first applications, tests, and lightweight services where async SQLx integration is still useful.
Best fit:
- Local-first business tools
- Developer tests
- Small services
- Portable demos
[!WARNING] In-Memory Connection Isolation When using in-memory SQLite (
sqlite::memory:), SQLite creates a separate, completely isolated database for each physical connection. Under a standard database connection pool (which creates multiple connections by default), different queries will execute against different in-memory database instances, leading to "table not found" or missing record issues.To solve this, always configure your in-memory SQLite connection string to use a shared cache so all connections in the pool access the same in-memory instance:
let pool = SqlitePool::connect("sqlite::memory:?cache=shared").await?;
rusqlite SQLite
Use rusqlite when synchronous SQLite execution, embedded deployment, small dependency shape, or multi-architecture device support matters more than async server integration.
Best fit:
- Embedded devices
- Router and edge environments
- Offline business apps
- Agent memory on local devices
- Multi-architecture targets
MemoryRepository
Use MemoryRepository when you want to exercise generated APIs without a database.
Best fit:
- Unit tests
- No-database demos
- Model validation
- Fast runtime simulation
Choosing a Provider
| Need | Provider |
|---|---|
| Production PostgreSQL backend | SQLx PostgreSQL |
| Enterprise MySQL backend | SQLx MySQL |
| Local-first async SQLite | SQLx SQLite |
| Embedded or edge SQLite | rusqlite SQLite |
| Fast tests without storage | MemoryRepository |
Example Configuration
Provider configuration follows the runtime assembly model:
Domain model
-> generated Rust package
-> RuntimeModule
-> selected repository provider
-> PostgreSQL / MySQL / SQLite / Memory
Use the model's data-service concept to keep provider choice explicit. For the current shared data-service vocabulary, see KSML data service config.
Generated crates can expose runtime helpers for provider-backed services, including database URL environment variable names, pool setup, provider registration, and ensure_schema() after the selected provider is registered.
Common Patterns
- Use SQLx PostgreSQL or SQLx MySQL for backend services.
- Use SQLx SQLite for local-first and test-heavy server code.
- Use rusqlite for embedded devices and sync execution.
- Use MemoryRepository when testing generated API behavior without persistence.
- Keep business query code provider-agnostic.
Limitations and Roadmap
The Rust runtime is active runtime work, not a placeholder. Current direction:
- Java TeaQL remains mature and proven for enterprise Java systems.
- Rust core runtime is being rebuilt around provider-backed execution.
- MySQL, PostgreSQL, and SQLite are the primary Rust database targets.
- rusqlite exists for embedded SQLite scenarios.
- MemoryRepository supports no-database tests and simplified execution.