Query Execution
Execution is the path from a builder call to typed rows. It has four steps.
The flow
Section titled “The flow”sequenceDiagram
participant B as Builder
participant C as Compiler
participant D as Driver
participant DB as Database
B->>C: compilePlan(plan, dialect)
C->>D: { sql, params, columnTypes }
D->>DB: execute(sql, params)
DB-->>D: raw rows
D-->>B: typed rows (decoded)
- Compile —
compilePlan(plan, dialect)→{ sql, params, columnTypes }. - Bind — the driver sends SQL + params to the database.
- Run — the database returns rows (driver-agnostic).
- Decode — the driver uses
columnTypesto decode values (e.g.0/1→boolean) back into theInferTableshape.
Why decode at the driver
Section titled “Why decode at the driver”The plan carries columnTypes, so the driver knows bool columns should become
boolean even though the DB stored 0/1. Your app never sees the raw form.
Immutability along the way
Section titled “Immutability along the way”The builder forks a new plan per method; the compiled output is also derived, never mutated. This is why concurrent queries don’t interfere.
Best practices
Section titled “Best practices”- Await terminal methods (
all,findOne,insert, …) — that’s when execution happens. - Let the driver decode types; don’t re-cast in app code.
Common mistakes
Section titled “Common mistakes”- Calling builder methods and expecting execution (only terminals run).
- Assuming
boolreturns0/1(the driver decodes it).
Related
Section titled “Related”- Compiler & Dialects — the compile step.
- Type-Safety System — the decoded row type.
