TeaQL Showcase: See What Your Business Code Actually Does
Instead of hiding database behavior behind an opaque ORM, this demo shows the full execution path of a domain action:
Instead of hiding database behavior behind an opaque ORM, this demo shows the full execution path of a domain action:
TeaQL Rust uses runtime providers to keep generated business APIs separate from storage execution.
The application code should use the generated API. The runtime should decide how that API executes against PostgreSQL, MySQL, SQLite, embedded SQLite, or memory.
| Provider | Best for |
|---|---|
| SQLx PostgreSQL | production-grade backend services, complex queries, transactions, aggregation |
| SQLx MySQL | enterprise MySQL systems and migration scenarios |
| SQLx SQLite | local-first apps, tests, lightweight services |
| rusqlite SQLite | embedded, router, edge, sync execution, multi-architecture devices |
| MemoryRepository | no-database tests, demos, fast model validation |
PostgreSQL is the strongest default for production backend systems that need:
TeaQL's SQLx PostgreSQL provider keeps PostgreSQL-specific execution behind the repository boundary.
MySQL remains common in enterprise business systems. TeaQL's SQLx MySQL provider is intended for teams that want generated business APIs while staying on a familiar MySQL backend.
This is especially useful when moving away from handwritten mapper-heavy persistence without moving the database first.
SQLite has two important TeaQL paths.
SQLx SQLite is useful for async local-first apps, integration tests, small services, and portable demos.
rusqlite is useful when synchronous embedded SQLite is a better fit:
Not every generated API test needs a database.
MemoryRepository gives TeaQL a no-database path for:
The goal is to test generated API behavior without requiring a database server.
The provider is registered below UserContext:
Generated service crate
-> RuntimeModule
-> UserContext
-> Repository API
-> selected provider
Generated crates can expose helpers for module registration, behavior/checker registration, provider-backed runtime setup, and schema bootstrap.
Without a provider boundary, application code tends to mix business intent with database details.
With providers, the generated API remains stable:
Q::platforms()
.select_merchant_list_with(Q::merchants().select_name())
.execute_for_list(&ctx)
.await?;
The runtime decides whether that request executes through PostgreSQL, MySQL, SQLite, rusqlite, or memory.
That is the point of TeaQL's multi-database runtime direction.
TeaQL Rust supports both SQLx and rusqlite because they solve different deployment problems.
This is not duplication. It is provider choice.
The generated business API should remain stable while the runtime provider changes underneath.
SQLx is a strong fit for async server-side Rust services.
TeaQL uses SQLx providers for:
SQLx fits services that already run inside an async runtime, use connection pools, and need production backend behavior such as transactions, schema bootstrap, row decoding, and database-specific SQL execution.
Good SQLx targets:
rusqlite is a strong fit for synchronous embedded SQLite.
That matters for deployments where the database is not a remote backend service:
In those cases, an async pool-oriented provider may be unnecessary weight. A synchronous SQLite provider can be easier to deploy and reason about.
The application should still use generated APIs:
let rows = Q::orders()
.select_self()
.select_line_item_list_with(Q::line_items().select_self())
.execute_for_list(&ctx)
.await?;
The question of SQLx SQLite versus rusqlite SQLite should be a runtime decision, not a reason to rewrite business query code.
The boundary looks like this:
Generated Q API
-> UserContext
-> Repository API
-> SQLx PostgreSQL / SQLx MySQL / SQLx SQLite / rusqlite SQLite
This keeps database execution below generated business intent.
Use SQLx when:
Use rusqlite when:
TeaQL is not only about database support. It is about keeping domain APIs independent of storage execution.
Supporting both SQLx and rusqlite lets the same generated model fit more deployment shapes without changing the programming model.
TeaQL expands into Rust. The core runtime ships with procedural macros, dual database support, and a unified id space.
Java served us well for enterprise backends. Rust brings zero-cost abstractions, memory safety without GC, and native performance. The goal is not to replace the Java stack but to offer a lean alternative for performance-critical services.
#[derive(TeaQLEntity)]
struct User {
id: u64,
name: String,
}
The TeaQLEntity macro derives:
| Database | Schema Ensuring | Status |
|---|---|---|
| SQLite | ensure_schema | Ready |
| PostgreSQL | ensure_schema | Ready |
let db = SqliteBackend::open("app.db").await?;
db.ensure_schema::<User>().await?;
All entity ids moved from i32 to u64:
Graph writes and a query DSL are already in progress.
Internationalization milestone with SQLite schema migration enhancements.
+ Full Traditional Chinese (zh-TW) translation
+ BaseLanguageTranslator base class
Supported languages: English (en), Simplified Chinese (zh-CN), Traditional Chinese (zh-TW).
SQLite's limited ALTER TABLE support implemented via table recreation:
+ SQLiteRepository: alter column via table recreation
+ Data preservation during table recreation
Constant values emitted exactly as defined in the domain model without transformation.
Default boolean naming changed from hasXxx to haveXxx:
// Before
user.hasPermission()
// After (default)
user.havePermission()
Legacy projects can set use_has='true' to maintain compatibility.