Skip to main content

5 posts tagged with "orm"

View All Tags

Java E Expressions: Catch Unloaded Data Before Production

· 4 min read
Philip Z
Architect

Java applications have spent decades improving null handling, yet one dangerous ambiguity remains common in data-access code:

Does null mean the database value is NULL, or does it mean the query never loaded the property?

Those two states have completely different business meanings. Treating both as null can make a test pass and let the wrong decision reach production.

TeaQL's generated Java E expressions now preserve three states: Value, Null, and NotLoaded. A missing preload becomes a structured exception at the point of use, while a genuine SQL NULL remains a legitimate null value.

Rust Option Is Not Enough for Partially Loaded Entities

· 4 min read
Philip Z
Architect

Rust's Option<T> is one of the language's best tools. It forces absence into the type system and eliminates an entire class of null-pointer failures.

But an ORM or data runtime has another state that Option<T> cannot express on its own: the field was not loaded.

If both SQL NULL and an unselected column become None, business logic cannot tell a legitimate absence from an incomplete query. TeaQL Rust models the missing state explicitly with EvalResult::Value, EvalResult::Null, and EvalResult::NotLoaded.

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.

The Return of E Expressions: Fluent Chaining and Structured Panics for AI Auto-Healing

· 4 min read
Philip Z
Architect

In the evolution of TeaQL, we've constantly navigated the tension between developer ergonomics and idiomatic Rust. We recently brought the E:: fluent expression chain back to Rust.

This is not a simple rollback. The new design uses reference chaining instead of cloning entity graphs and emits structured diagnostics when a relation was not loaded.

TeaQL is not just an ORM

· 2 min read
TeaQL Team
Core Team

It is tempting to describe TeaQL as an ORM because TeaQL knows about entities, relations, repositories, and databases.

That description is incomplete.

TeaQL is a generated business API layer. Persistence is one part of the system, but the main value is the generated domain language that sits above persistence.

What an ORM Usually Optimizes

Most ORM discussions focus on mapping:

  • classes to tables;
  • fields to columns;
  • relations to joins;
  • objects to rows;
  • transactions to persistence sessions.

Those are real problems. TeaQL also needs to solve them. But large business systems have another repeated problem: the same business request is rebuilt again and again in controllers, repositories, DTOs, SQL, validators, and frontend response logic.

What TeaQL Optimizes

TeaQL optimizes the business API surface.

It generates request APIs that can express:

  • selection;
  • nested relation loading;
  • filters;
  • list-existence queries;
  • pagination;
  • grouped statistics;
  • relation aggregates;
  • graph writes;
  • validation hooks;
  • runtime customization.

The generated API is meant to be read by backend engineers, domain engineers, reviewers, and AI coding tools.

Generated Business APIs

An ORM might make it easy to load an Order.

TeaQL aims to make it clear how a complete order page is assembled:

Q.orders().filterByMerchant(ctx.getMerchant())
.selectCustomer(Q.customers().comment("Query customers").purpose("Load data").selectName())
.selectLineItemList(Q.lineItems().selectSku().selectQuantity())
.countLineItems()
.orderByCreateTimeDescending()
.page(1, 20)
.comment("Query orders").purpose("Load data")
.executeForList(ctx);

The key is not whether this compiles to SQL. It does. The key is that the API names the business shape before the runtime turns it into storage operations.

Runtime Boundary

TeaQL also treats runtime behavior as part of the model:

  • user context;
  • tenant and permission policy;
  • cache behavior;
  • distributed locks;
  • logging and metrics;
  • validation;
  • event dispatch;
  • database provider selection.

That is why TeaQL has a runtime layer instead of only a mapper layer.

Why This Helps AI

AI tools should not need to guess SQL, join rules, table names, tenant filters, and response shapes from scattered code.

Generated APIs give AI tools a deterministic vocabulary:

  • call this field selector;
  • use this relation loader;
  • compose this query fragment;
  • execute through this runtime context;
  • do not bypass the provider.

That is a different goal from a traditional ORM.

The Short Version

TeaQL uses persistence mapping, but it is not defined by persistence mapping.

It is a generated business API platform that keeps domain intent visible while allowing the runtime provider to change underneath.