Library
Module
Module type
Parameter
Class
Class type
Use this module for PostgreSQL database queries.
Note: does not support batch_insert
out of the box because PostgreSQL uses numbered placeholders, which makes it much more difficult to parse out and modify the insert query with the correct number of placeholders.
include Fun_sql.Sql with type db = Postgresql.connection
type db = Postgresql.connection
The database connection or file, etc.
val placeholder : Format.formatter -> int -> unit
A generic way to write placeholders for different database drivers' prepared statement parameters.
ℹ️ Placeholders are 0-indexed.
The main function through which queries are run is the query
function. This function always creates a prepared statement for each partial call to query db sql
. This prepared statement can then be called with the actual arguments (if any) and the resultset row decoder:
let add_person =
query db (sql "insert into people (name, age) values (%a, %a)" placeholder 0 placeholder 1)
let add_person name age = add_person ~args:Arg.[text name; int age] unit
val exec_script : db -> string -> unit
exec_script db sql
executes the sql
script (possibly made up of multiple statements) in the database db
. Note that it ignores any rows returned by any of the statements.
The script must not have a trailing semicolon.
These encode OCaml data as data to be bound to the query statement.
module Arg : sig ... end
val unit : unit ret
unit
indicates that the query doesn't return any meaningful output.
ret decode
is a custom return type encoding for a resultset into a sequence of values of the type decoded by decode
.
decode
constructs a value of the custom type if possible, else raises Failure
.
Note that the sequence rows of the resultset is unfolded as it is read from the database. It can only be traversed once, with e.g. List.of_seq
or Seq.iter
. If traversed multiple times, it will raise Failure
.
val int : int -> row -> int
val bool : int -> row -> bool
val int64 : int -> row -> int64
val float : int -> row -> float
val text : int -> row -> string
Also handles values of all other types. Use this when SQLite can change the exact type of value it returns at runtime, e.g. for very large numbers it can return text.
include Fun_sql.S
with type db := db
and type arg := arg
and type 'a ret := 'a ret
val sql : ('a, Format.formatter, unit, string) format4 -> 'a
Helper to construct SQL query strings using placeholder
s.
val migrate : db -> string -> unit
migrate db dir
applies the SQL migration scripts in dir
on the given database db
, keeping track of those that have already been applied.
To apply the migrations in the correct order, the migration scripts must be given filenames that are sorted in lexicographical order of the desired migration order, e.g. 0000_0001_init.sql
will be applied before 0000_0002_sec.sql
, and so on.
Note that this uses exec_script
internally, which means the migration scripts must not have trailing semicolons either.
Any files with extensions other than .sql
are ignored.
val transaction : db -> (unit -> 'r) -> 'r
transaction db f
runs f ()
inside a transaction in the db
. If the operation succeeds, it commits the transaction and returns its result. If it fails with an exception, it rolls back the transaction and re-raises the exception.
val only : 'a Seq.t -> 'a
only seq
is the first and only element of seq
. This is a convenience function because all queries return seqs but sometimes we want only a single item, otherwise it should be an error.
Use this in preference to calculating the length of the seq
, which would force the entire data structure.
val optional : 'a Seq.t -> 'a option
optional seq
is Some a
if a
is the first and only element of seq
, or None
if seq
is empty.