Page
Library
Module
Module type
Parameter
Class
Class type
Source
Please note that this is not the first or only PGSQL bindings for OCaml. Here are the others which you may want to consider:
PG'OCAML is different than the above bindings:
PGOCaml
) provided is synchronous. But it also supports any asynchronous interface that implements the PGOCaml_generic.THREAD
signature.PG'OCaml uses environment variables (or in-code parameters, which are [ill advised] (https://hackernoon.com/how-to-use-environment-variables-keep-your-secret-keys-safe-secure-8b1a7877d69c)) to connect to your database both at compile-time and at runtime.
Variable | Default | Additional information |
---|---|---|
| If this starts with a | |
|
| This is also the default PostgreSQL port. |
| The username of the current user, or | |
| falls back on | |
| empty string | |
| no profiling | Indicates the file to write profiling information to. If it doesn't exist, don't profile |
|
| If set to |
| nothing | Points to a file containing custom type conversions |
The PPX aims to be more or less a carbon copy of the former extension.
let () =
let dbh = PGOCaml.connect () in
let insert name salary =
[%pgsql dbh "insert into employees (name, salary) VALUES ($name, $salary)"]
in
ignore(insert "Chris" 1_000.0);
let get name =
[%pgsql dbh "select salary from employees where name = $name"]
in
let () = [%pgsql dbh
"execute"
"CREATE TEMP TABLE IF NOT EXISTS employees (
name TEXT PRIMARY KEY,
salary FLOAT)"]
in
let name = "Chris" in
let salary = get name
|> List.hd
|> function
| Some(x) -> x
| None -> raise(Failure "The database is probably broken.")
in
Printf.printf "%s's salary is %.02f\n" name salary;
PGOCaml.close(dbh)
The PPX allows you to specify that queries returning results should be returned as objects, rather than tuples.
let%lwt res =
[%pgsql.object dbh "SELECT * FROM employees"]
in
List.iter
(fun row ->
Printf.printf "%s makes $%f\n" row#name row#salary)
res
The PPX now also supports ${...}
expansions.
(* where [e] is a row returned by a [pgsql.object] query *)
let%lwt incr_sal e =
[%pgsql dbh "UPDATE employees SET salary = ${e#salary +. 1.0}"]
You may wish to print all the fields of an object for debugging purposes.
let%lwt rows = [%pgsql.object dbh "show" "SELECT * FROM employees"] in
List.iter
(fun row -> print_endline row#show)
rows
The above code will not work if one of the selected fields is named show
. The PPX allows one to explicitly name the pretty-printer method as follows:
let%lwt rows = [%pgsql.object dbh "show=pp" "SELECT * FROM employees"] in
List.iter
(fun row -> print_endline row#pp)
rows
It's important to note that the show
directive causes values to be printed in the same format used by the Postgres API, so things like Calendar.t
values and custom converters (see below) may not work as expected.
Custom serializers and deserializers may be provided in a configuration file specified by PGCUSTOM_CONVERTERS_CONFIG
(see above). An example configuration file follows:
( ( ( Or
( (Rule (typnam userid)) ; userid is a fully abstract type
(Rule (colnam userid))
)
)
( (serialize Userid.to_string)
(deserialize Userid.from_string)
)
)
( ( Or
( (Rule (typnam cash_money)) ; for strings beginning with a $ and possibly needing to be trimmed
(And ; there exists a column elsewhere also named salary, but it has a different type
( (Rule (typnam float))
(Rule (colnam salary))
)
)
)
)
( (serialize "fun x -> String.(sub x 1 (length x - 1)) |> String.trim")
(deserialize "fun x -> \"$\" ^ x")
)
)
)
In case you're working on a large project, and don't want to write many convoluted rules to play nicely with your existing database structure, you can selectively enable custom serialization for individual queries:
let rows =
[%pgsql.object
dbh
"load_custom_from=tests_ppx/config.sexp"
"show"
"SELECT * FROM customtable"]
in
...
PG'OCaml's PPX is not given type information by the compiler, so it will sometimes have trouble figuring the correct types for arguments. While one may find a parameter's serializer based in its name, this is not ideal, particularly when using ${...}
parameters. In cases like this, you may use a syntax similar to OCaml's native type constraint:
let () = [%pgsql dbh "INSERT INTO users VALUES ${u : userid}"] in
...
Please note that the ${u : userid}
above will NOT be compiled into an OCaml type constraint. Its only effect is to supply userid
as the typnam
to the serializer resolver.
PG'OCaml (C) Copyright 2005-2009 Merjis Ltd, Richard W.M. Jones (rich@annexia.org) and other authors (see CONTRIBUTORS.txt for details).
This software is distributed under the GNU LGPL with OCaml linking exception. Please see the file COPYING.LIB for full license.
For an example, please see tests