Qubu

Build SQL queries from typed tables and reusable values.

Qubu builds SQL from reusable values. You can combine query parts without changing a shared query-builder object.

TypeScript checks:

  • Which fields the query returns and their types.
  • Whether each column belongs to a source in the query.
  • Whether a result can be null.

Render a query to inspect its SQL text and ordered parameters.

The preferred source style names each projected field and writes the final select() clauses in SQL order. Clause values remain order-independent at runtime, so a reusable where() or orderBy() fragment can be built earlier and placed in that final call where it reads best.

Start here

If this is your first query, follow Getting started to define a table, build a SELECT, and inspect its SQL and parameters.

Build and run queries

Work with schemas and migrations

The query pipeline

The same query value can be rendered for inspection or passed to an adapter for execution. The application-owned adapter handles the driver, database connection, and driver-specific row and mutation-result details.

Tables and columns Expressions and clauses Typed query Dialect renderer SQL text + ordered parameters Application-owned adapter Rows + optional mutation facts

Values become bound parameters, and the active dialect quotes identifiers. Raw SQL is available through explicit unsafe helpers. The call site shows where that unchecked syntax enters the query.

Understand the Qubu model

Use these pages when a guide leaves a rule unexplained or when an extension needs to preserve a fact across composition:

Model Start with Covers
Query model Source scope Source identity, result shapes, fragments, metadata, and query composition
Schema model Tables and names Tables, snapshots, diffs, migration plans, and DDL emission
Migration operations Migration operations Artifacts, adapters, CLI policy, baselines, execution, and recovery
Database introspection Database introspection Catalog readers, Snapshot v1 mapping, identities, diagnostics, and support limits
Schema source generation Generate a schema Machine-owned TypeScript, identity handoff, controlled mappings, and v1 exclusions
Rendering and execution Dialects and execution Placeholder and identifier policies, capabilities, adapters, and raw-SQL boundaries
SQL semantic types SQL semantic types Application types, SQL domains, nullability, and compatible operations

A small example

import { eq, from, integer, render, select, table, text, where } from "qubu"

const users = table("users", {
  id: integer(),
  name: text(),
})

const query = select({ id: users.id, name: users.name }, from(users), where(eq(users.id, 7)))

render(query)
// {
// text: 'SELECT "users"."id" AS "id", "users"."name" AS "name" FROM "users" WHERE ("users"."id" = ?)',
// parameters: [7],
// }

The inferred row is { id: number; name: string }. The value 7 stays out of the SQL text and appears in the parameters array in placeholder order.

Find support details

  • Supported features lists package imports and explains which responsibilities stay with your application.
  • Troubleshooting starts from common errors and explains how to fix them.