Module Caqti_request.Infix

The following operators provides a more visually appealing way of expressing requests. They are implemented in terms of create and Caqti_query.of_string_exn, meaning the the query string arguments accepts The Syntax of Query Templates.

The ?oneshot argument defaults to false, so when not constructing one-shot queries, the full application (pt -->! rt) f can be written pt -->! rt @@ f, which motivates the (@:-) and (@@:-) shortcuts.

In the simplest case you can use this module directly together with Caqti_type:

let bounds_upto_req =
  let open Caqti_type.Std in
  let open Caqti_request.Infix in
  tup2 int32 float -->! option (tup2 float float) @:-
  "SELECT min(y), max(y) FROM samples WHERE series_id = ? AND x < ?"

For more complex applications it may be convenient to provide a custom module, to avoid the double open and to customize the operators, e.g.

module Caqtireq = struct
  include Caqti_type.Std
  include Caqti_type_calendar (* if needed, link caqti-type-calendar *)
  include Caqti_request.Infix

  (* Any additional types. *)
  let password = redacted string
  let uri =
    custom ~encode:(fun x -> Ok (Uri.to_string x))
           ~decode:(fun s -> Ok (Uri.of_string s)) string

  (* Optionally define a custom environment providing two schema names.
   * The references should only be assigned at startup. *)
  let myapp_schema = ref "myapp"
  let mylib_schema = ref "mylib"
  let env = function
   | "" -> Caqti_query.L !myapp_schema
   | "mylib" -> Caqti_query.L !mylib_schema
   | _ -> raise Not_found

  (* Since we have a custom environment, override the definitions of the
   * following operators to perform the substitution. *)
  let (@:-) t qs =
    let q = Caqti_query.expand env (Caqti_query.of_string_exn qs) in
    t (fun _ -> q)
  let (@@:-) t qsf =
    t (fun driver_info ->
      let qs = qsf (Caqti_driver_info.dialect_tag driver_info) in
      Caqti_query.expand env (Caqti_query.of_string_exn qs))
end

If you don't like using global references, or you need to work with different enviroments for different connections, you should instead pass the environment function when connecting to the database. We can now simplify and schema-qualify the previous request,

let bounds_upto_req =
  let open Caqtireq in
  tup2 int32 float -->! option (tup2 float float) @:-
  "SELECT min(y), max(y) FROM $.samples WHERE series_id = ? AND x < ?"

Constructors for Driver-Independent Requests also provides alternative arrow operators for this common case, which allows using short-from local open,

let bounds_upto_req =
  Caqtireq.(tup2 int32 float ->! option (tup2 float float))
  "SELECT min(y), max(y) FROM $.samples WHERE series_id = ? AND x < ?"

Constructors for Driver-Independent Requests

val (->.) : 'a Caqti_type.t -> unit Caqti_type.t -> ?oneshot:bool -> string -> ( 'a, unit, [ `Zero ] ) t

(pt ->. Caqti_type.unit) ?oneshot s is the request which sends the equery string s, encodes parameters according to pt, and expects no result rows. See create for the meaning of oneshot.

val (->!) : 'a Caqti_type.t -> 'b Caqti_type.t -> ?oneshot:bool -> string -> ( 'a, 'b, [ `One ] ) t

(pt ->! rt) ?oneshot s is the request which sends the query string s, encodes parameters according to pt, and decodes a single result row according to rt. See create for the meaning of oneshot.

val (->?) : 'a Caqti_type.t -> 'b Caqti_type.t -> ?oneshot:bool -> string -> ( 'a, 'b, [ `Zero | `One ] ) t

(pt ->? rt) ?oneshot s is the request which sends the query string s, encodes parameters according to pt, and decodes zero or one result row according to rt. See create for the meaning of oneshot.

val (->*) : 'a Caqti_type.t -> 'b Caqti_type.t -> ?oneshot:bool -> string -> ( 'a, 'b, [ `Zero | `One | `Many ] ) t

(pt ->* rt) ?oneshot s is the request which sends the query string s, encodes parameters according to pt, and decodes any number of result rows according to rt. See create for the meaning of oneshot.

Constructors for Driver-Dependent Requests

The below arrow operators takes a function instead of a string as their third argument. The function receives information about the current driver and returns a Caqti_query.t. This is the most general way of providing the query string.

As an alternative to using plain application (or @@) for the third positional argument, additional application operators are provided for convenience.

val (-->.) : 'a Caqti_type.t -> unit Caqti_type.t -> ?oneshot:bool -> ( Caqti_driver_info.t -> Caqti_query.t ) -> ( 'a, unit, [ `Zero ] ) t

(pt -->. Caqti_type.unit) ?oneshot f is the request which sends the query string returned by f, encodes parameters according to pt, and expects no result rows. See create for the meaning of oneshot.

val (-->!) : 'a Caqti_type.t -> 'b Caqti_type.t -> ?oneshot:bool -> ( Caqti_driver_info.t -> Caqti_query.t ) -> ( 'a, 'b, [ `One ] ) t

(pt -->! rt) ?oneshot f is the request which sends the query string returned by f, encodes parameters according to pt, and decodes a single result row according to rt. See create for the meaning of oneshot.

val (-->?) : 'a Caqti_type.t -> 'b Caqti_type.t -> ?oneshot:bool -> ( Caqti_driver_info.t -> Caqti_query.t ) -> ( 'a, 'b, [ `Zero | `One ] ) t

(pt -->? rt) ?oneshot f is the request which sends the query string returned by f, encodes parameters according to pt, and decodes zero or one result row according to rt. See create for the meaning of oneshot.

val (-->*) : 'a Caqti_type.t -> 'b Caqti_type.t -> ?oneshot:bool -> ( Caqti_driver_info.t -> Caqti_query.t ) -> ( 'a, 'b, [ `Zero | `One | `Many ] ) t

(pt -->* rt) ?oneshot f is the request which sends the query string returned by f, encodes parameters according to pt, and decodes any number of result rows according to rt. See create for the meaning of oneshot.

val (@:-) : ( ( Caqti_driver_info.t -> Caqti_query.t ) -> ( 'a, 'b, 'm ) t ) -> string -> ( 'a, 'b, 'm ) t

Applies a dialect-independent query string which is parsed with Caqti_query.of_string_exn. Composition with arrow operators from this section, gives the corresponding operators from Constructors for Driver-Independent Requests.

val (@@:-) : ( ( Caqti_driver_info.t -> Caqti_query.t ) -> ( 'a, 'b, 'm ) t ) -> ( Caqti_driver_info.dialect_tag -> string ) -> ( 'a, 'b, 'm ) t

Applies a dialect-dependent query string which is parsed with Caqti_query.of_string_exn.