a database layer insipred by caqti and ecto
OCaml 97.0%
Shell 1.7%
Dune 0.3%
Standard ML 0.1%
Other 0.9%
20 1 3

Clone this repository

https://tangled.org/gdiazlo.tngl.sh/repodb
git@tangled.org:gdiazlo.tngl.sh/repodb

For self-hosted knots, clone URLs may differ based on your setup.

README.md

repodb#

An Ecto-inspired database toolkit for OCaml.

repodb tries to bring Elixir's Ecto ideas to OCaml: type-safe queries, composable changesets, and clean separation between your domain and the database.

Features#

  • Schemas - Define your data structures with typed fields
  • Changesets - Validate and track changes before persisting
  • Query DSL - Build type-safe queries with a composable API
  • Repo - Clean abstraction over database operations
  • Associations - Define relationships (has_many, belongs_to, many_to_many)
  • Preloading - Efficiently load associations, avoiding N+1 queries
  • Multi - Compose multiple operations in a single transaction
  • Migrations - Version your database schema
  • Connection Pool - Scheduler-agnostic, lock-free connection pooling
  • CQRS - Transparent read/write splitting with replica support
  • Multi-Server Pool - Round-robin load balancing across database servers

Quick Example#

(* Define a schema *)
let users_table = Schema.table "users"

type user = { id : int; name : string; email : string; age : int }

let name_field =
  Field.make ~table_name:"users" ~name:"name" ~ty:Types.string
    ~get:(fun u -> u.name) ~set:(fun v u -> { u with name = v }) ()

(* Create and validate a changeset *)
let empty_user = { id = 0; name = ""; email = ""; age = 0 }

let changeset =
  Changeset.create empty_user
  |> Changeset.cast [("name", "Alice"); ("email", "alice@example.com")]
       ~fields:[name_field; email_field]
  |> Changeset.validate_required [name_field; email_field]
  |> Changeset.validate_format email_field ~pattern:"^[^@]+@[^@]+$"

(* Build and execute queries *)
let query =
  Query.(from users_table
    |> where Expr.(raw "age" > int 18)
    |> order_by ~direction:Desc (Expr.raw "created_at")
    |> limit 10)

let users = Repo.all_query conn query ~decode:decode_user

Documentation#

Packages#

Package Description
repodb Core library with schemas, changesets, queries
repodb-sqlite SQLite driver
repodb-postgresql PostgreSQL driver

Installation#

opam install repodb repodb-sqlite   # or repodb-postgresql

Philosophy#

repodb follows Ecto's philosophy:

  1. Explicit over implicit - No magic, every operation is visible
  2. Composable - Small functions that combine well
  3. Separation of concerns - Domain logic separate from persistence
  4. Fail fast - Validate early with changesets

License#

ISC License