package caqti
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=483a535f41e2641917fc1832ce4ad15ffc3f4e8283b1b3018a2617349583090a
sha512=6a1222c0c55cb16a9d409980f9f2400340689b87e21aafed2d7459fd7feaeb109c2dfaf77f55f8422fbb7d3772342565ced7fed78a7b77af5aedab5bfd5ae882
doc/caqti/Caqti_request/index.html
Module Caqti_request
Source
Request specification.
A Caqti request is a function to generate a query string from information about the driver, along with type descriptors to encode parameters and decode rows returned from the same query. Requests are passed to Caqti_connection_sig.S.call
or one of its shortcut methods provided by a database connection handle.
The request often represent a prepared query, in which case it is static and can be defined directly in a module scope. However, an optional oneshot
parameter may be passed to indicate a dynamically generated query.
Primitives
A request specification embedding a query generator, parameter encoder, and row decoder.
'a
is the type of the expected parameter bundle.'b
is the type of a returned row.'m
is the possible multiplicities of returned rows.
val create :
?oneshot:bool ->
'a Caqti_type.t ->
'b Caqti_type.t ->
'm Caqti_mult.t ->
(Caqti_driver_info.t -> Caqti_query.t) ->
('a, 'b, 'm) t
create arg_type row_type row_mult f
is a request which takes parameters of type arg_type
, returns rows of type row_type
with multiplicity row_mult
, and which sends query strings generated from the query f di
, where di
is the Caqti_driver_info.t
of the target driver. The driver is responsible for turning parameter references into a form accepted by the database, while other differences must be handled by f
.
- If false (the default), the statement is prepared and a handle is permanently attached to the connection object right before the first time it is executed.
- If true, everything allocated in order to execute the statement is released after use.
In other words, the default is suitable for queries which are bound to static modules. Conversely, you should pass ~oneshot:true
if the query is dynamically generated, whether it is within a function or a dynamic module, since there will otherwise be a memory leak associated with long-lived connections. You might as well also pass ~oneshot:true
if you know that the query will only executed at most once (or a very few times) on each connection.
param_type req
is the type of parameter bundles expected by req
.
row_type req
is the type of rows returned by req
.
row_mult req
indicates how many rows req
may return. This is asserted when constructing the query.
If req
is a prepared query, then query_id req
is Some id
for some id
which uniquely identifies req
, otherwise it is None
.
query req
is the function which generates the query of this request possibly tailored for the given driver.
Convenience Interface
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.
Printing
val make_pp :
?env:(Caqti_driver_info.t -> string -> Caqti_query.t) ->
?driver_info:Caqti_driver_info.t ->
unit ->
Format.formatter ->
('a, 'b, 'm) t ->
unit
make_pp ?env ?driver_info ()
is a pretty-printer for a request, which expands the query using env
and driver_info
.
pp ppf req
prints req
on ppf
in a form suitable for human inspection.
val make_pp_with_param :
?env:(Caqti_driver_info.t -> string -> Caqti_query.t) ->
?driver_info:Caqti_driver_info.t ->
unit ->
Format.formatter ->
(('a, 'b, 'm) t * 'a) ->
unit
make_pp_with_param ?env ?driver_info ()
is a pretty-printer for a request and parameter pair. See make_pp
for the optional arguments. This functions is meant for debugging; the output is neither guaranteed to be consistent across releases nor to contain a complete record of the data. Lost database records cannot be reconstructed from the logs.
Due to concerns about exposure of sensitive data in debug logs, this function only prints the parameter values if CAQTI_DEBUG_PARAM
is set to true
. If you enable it for applications which do not consistenly annotate sensitive parameters with Caqti_type.redacted
, make sure your debug logs are well-secured.
How to Dynamically Assemble Queries and Parameters
In some cases, queries are constructed dynamically, e.g. when translating an expression for searching a database into SQL. In such cases the number of parameters and their types will typically vary, as well. A helper like the following can be used to existentially pack the parameter types along with the corresponding parameter values to allow collecing them incrementally:
module Dynparam = struct
type t = Pack : 'a Caqti_type.t * 'a -> t
let empty = Pack (Caqti_type.unit, ())
let add t x (Pack (t', x')) = Pack (Caqti_type.tup2 t' t, (x', x))
end
Now, given a param : Dynparam.t
and a corresponding query string qs
, one can construct a request and execute it:
let Dynparam.Pack (pt, pv) = param in
let req = Caqti_request.exec ~oneshot:true pt qs in
C.exec req pv
Note that dynamically constructed requests should have ~oneshot:true
unless they are memoized. Also note that it is natural to use create
for dynamically constructed queries, since it accepts the easily composible Caqti_query.t
type instead of plain strings.
This scheme can be specialized for particular use cases, including generation of fragments of the query
, which reduces the risk of wrongly matching up parameters with their uses in the query string.