Skip to content

Typed SQL queries and migrations for Postgres and SQLite, on OCaml 5.

You write the SQL. You declare its parameters and rows once, and that one declaration binds the values going in and decodes the rows coming out.

Terminal window
opam repo add hypha https://github.com/hyphatech/opam-repository.git
opam install rowtype rowtype-postgres rowtype-migrate
module S = Rowtype
type user = { id : int; name : string }
let user =
S.map (S.t2 S.int S.text)
~parse:(fun (id, name) -> { id; name })
~print:(fun u -> (u.id, u.name))
let add_user =
S.find ~params:S.text ~row:S.int
"insert into users (name) values ($1) returning id"
let find_user =
S.find_opt ~params:S.int ~row:user "select id, name from users where id = $1"

Checked against your database

Every statement described by the database from a test, without running it, so a renamed column fails a test instead of a request.

Postgres and SQLite

The same statements run on both.

Migrations in the box

Plain SQL files and one command for every dialect, a library’s own migrations included.

Failures you can act on

A refused write names its constraint, and a lost write is told from one never sent.

Any size

Rows read in the memory of one, and loads through COPY.