Skip to main content

6 posts tagged with "postgresql"

View All Tags

TeaQL Was 2,000× Faster Than the Obvious SQLx Query—Here’s What Actually Happened

· 8 min read
Philip Z
Architect

We recently measured two implementations of the same application request over the MusicBrainz dataset:

Load the newest 100 recordings that have linked works, and load at most ten work relations for each recording.

The controlled SQLx test returned the same 100 recordings, 103 relation rows, 103 links, 103 link types, and Work-ID checksum through both paths. One took 5,871.169 milliseconds. The other took 2.469 milliseconds—a 2,378× difference inside SQLx itself.

TeaQL Rust previously completed the corresponding typed graph workload in 2.864 milliseconds. That does not mean TeaQL has a PostgreSQL driver 2,000× faster than SQLx. The difference was the amount of work requested from the database. The expert SQLx control proves it.

What Does a Governed Data Runtime Cost? TeaQL vs Diesel and SeaORM on MusicBrainz

· 12 min read
Philip Z
Architect

TeaQL does more during a query than map database rows into Rust structs.

It preserves loaded, null, and not-loaded state. It builds an identity-consistent object graph. It carries query purpose and diagnostic comments. The same runtime also supports checker/fix behavior, mutation ledgers, audit boundaries, and cross-data-source relations.

That raises a fair question: what does this additional runtime model cost on a real relational graph?

We tested a retained TeaQL Rust build against Diesel and SeaORM using a PostgreSQL copy of the public MusicBrainz database. The result is more useful than a simple winner: across three relationship shapes, TeaQL consistently landed between Diesel and SeaORM—and came within 3.4% of Diesel on one five-query graph.

From ORM Claims to Executed Evidence: Six TeaQL Runtimes and a Nine-Database Java Matrix

· 4 min read
TeaQL Team
Core Team

TeaQL now has a dated, executed database baseline across six generated language runtimes: Java, Rust, Go, Python, C#/.NET, and TypeScript.

The headline result is Java's real nine-database matrix:

tests=9 failures=0 errors=0 skipped=0

The databases were PostgreSQL, MySQL, SQLite, Oracle, DB2, DM8 (Dameng), SAP HANA, SQL Server, and DuckDB.

That is meaningful only because these were not adapter-discovery tests. The generated domain APIs compiled and executed schema creation, graph persistence, reconnect queries, optimistic updates, and direct database checks.

TeaQL Runtime Providers: PostgreSQL, MySQL, SQLite

· 2 min read
TeaQL Team
Core Team

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 Matrix

ProviderBest for
SQLx PostgreSQLproduction-grade backend services, complex queries, transactions, aggregation
SQLx MySQLenterprise MySQL systems and migration scenarios
SQLx SQLitelocal-first apps, tests, lightweight services
rusqlite SQLiteembedded, router, edge, sync execution, multi-architecture devices
MemoryRepositoryno-database tests, demos, fast model validation

PostgreSQL

PostgreSQL is the strongest default for production backend systems that need:

  • transactions;
  • rich query behavior;
  • grouped aggregation;
  • Decimal/NUMERIC support;
  • schema bootstrap;
  • id-space generation;
  • production database tooling.

TeaQL's SQLx PostgreSQL provider keeps PostgreSQL-specific execution behind the repository boundary.

MySQL

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

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:

  • devices;
  • routers;
  • edge deployments;
  • appliance controllers;
  • local agent memory.

MemoryRepository

Not every generated API test needs a database.

MemoryRepository gives TeaQL a no-database path for:

  • unit tests;
  • model validation;
  • lightweight demos;
  • fast runtime simulation.

The goal is to test generated API behavior without requiring a database server.

Runtime Assembly

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.

Why Providers Matter

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().comment("Query merchants").purpose("Load data").select_name())
.comment("Query platforms").purpose("Load data")
.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 Core Runtime

· One min read
TeaQL Team
Core Team

TeaQL expands into Rust. The core runtime ships with procedural macros, dual database support, and a unified id space.

Why Rust

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.

Procedural Macros

#[derive(TeaQLEntity)]
struct User {
id: u64,
name: String,
}

The TeaQLEntity macro derives:

  • Schema mapping
  • Query DSL methods
  • Graph relation helpers

Database Support

DatabaseSchema EnsuringStatus
SQLiteensure_schemaReady
PostgreSQLensure_schemaReady
let db = SqliteBackend::open("app.db").await?;
db.ensure_schema::<User>().await?;

u64 Id Space

All entity ids moved from i32 to u64:

  • 64-bit range eliminates overflow concerns
  • Consistent with Snowflake-style distributed ids
  • Progress tracking built into the runtime

What's Next

Graph writes and a query DSL are already in progress.