Skip to content

pgzest

Raw PostgreSQL, with zest. Write plain SQL; pgzest checks it the way PostgreSQL would, and turns it into typed Rust, migrations and observable routines — without a database connection.
-- queries/restaurants.sql
-- name: restaurant_by_slug
SELECT id, name, opened_on, created_at
FROM restaurants
WHERE slug = $slug;

slug is UNIQUE, opened_on is nullable: pgzest reads it from the schema, and the query becomes a function returning at most one row.

pub struct RestaurantBySlugRow {
pub id: i64,
pub name: String,
pub opened_on: Option<time::Date>,
pub created_at: time::OffsetDateTime,
}
pub async fn restaurant_by_slug<C: GenericClient + ?Sized>(
client: &C,
params: RestaurantBySlugParams<'_>,
) -> Result<Option<RestaurantBySlugRow>, pgzest_runtime::Error>;

A mistake in the SQL fails cargo build, at its line in the .sql file.

pgzest rebuilds the catalog by replaying your schema or migrations, then types every query as PostgreSQL would. An oracle runs the same queries on a real PostgreSQL 18 and compares:

  • 243 queries: 749/751 columns and 146/146 parameters typed exactly as PostgreSQL prepares them;
  • 19,032/19,032 function and operator resolutions identical;
  • two real projects’ migrations (1,740 and 294 statements) fully parsed, and replayed into catalogs identical to the databases they build — DDL run through dynamic SQL aside, which the replay reports instead of guessing.

Typed queries, per language

Rust today: named queries in .sql files or sql! in code, compiled into functions over tokio-postgres — as fast as hand-written code (145.0 vs 145.7 µs per query). TypeScript next.

Analysis as PostgreSQL would

Types, overloads, nullability, NOT NULL through joins, PL/pgSQL bodies and triggers per table — and what is not analyzed is said, never guessed.

Fragments and macros

A column list or an expression written once and inserted with @name; @function, @trigger without the boilerplate, expanded to plain SQL.

Declarative schema, generated migrations

Edit the schema, pgzest migrate create writes the migration and verifies it by replay. Prisma and Diesel layouts read as is.

Observable routines

Run logs, isolated temp tables, snapshots, OpenTelemetry traces of the triggers a statement fired, a depth limit for endless cascades, and db check for hand changes in production.

In the editor

VS Code: errors as you type, hover with types and query descriptors, completion, macro expansion — in .sql files and inside Rust strings.

pgzest is made by Creatiwity, free and open source under the MIT or Apache-2.0 license.

GitHubLegal notice