1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
[@@@alert "-caqti_private"]
module Log = (val Logs.src_log (Logs.Src.create "caqti"))
type prepare_policy =
| Direct
| Dynamic
| Static
type ('a, 'b, +'m) t = {
id: int option;
prepare_policy: prepare_policy;
queries: Dialect.t -> Query.t list;
param_type: 'a Row_type.t;
row_type: 'b Row_type.t;
row_mult: 'm Row_mult.t;
} constraint 'm = [< `Zero | `One | `Many]
let last_id = Shims.Atomic.make (-1)
let unit_to_unit_type = Request_type.Infix.(-->.) Row_type.unit Row_type.unit
let create_prim prepare_policy (param_type, row_type, row_mult) queries =
let queries = Shims.memo_if_safe ~cap:8 (fun _ -> queries) in
let id =
(match prepare_policy with
| Direct -> None
| Static | Dynamic -> Some (Shims.Atomic.fetch_and_add last_id 1))
in
{id; prepare_policy; queries; param_type; row_type; row_mult}
let create prepare_policy request_type query =
create_prim prepare_policy request_type (fun d -> [query d])
let create_multi prepare_policy queries =
create_prim prepare_policy unit_to_unit_type queries
let prepare_policy request = request.prepare_policy
let param_type request = request.param_type
let row_type request = request.row_type
let row_mult request = request.row_mult
let query_id request = request.id
let queries request = request.queries
let empty_subst _ = raise Not_found
let default_dialect = Dialect.create_unknown ~purpose:`Printing ()
let rec pp_queries ppf = function
| [] -> ()
| [q] -> Query.pp ppf q
| q :: qs ->
Format.pp_open_hvbox ppf 0;
Query.pp ppf q;
Format.pp_print_char ppf ';';
Format.pp_print_space ppf ();
pp_queries ppf qs;
Format.pp_close_box ppf ()
let make_pp ?(dialect = default_dialect) ?(subst = empty_subst) () ppf req =
let queries = List.map (Query.expand subst) (req.queries dialect) in
Format.fprintf ppf "(%a -->%s %a) {|%a|}"
Row_type.pp req.param_type
(match Row_mult.expose req.row_mult with
| `Zero -> "."
| `One -> ""
| `Zero_or_one -> "?"
| `Zero_or_more -> "*")
Row_type.pp req.row_type
pp_queries queries
let pp ppf = make_pp () ppf
let pp_with_param_enabled =
(match Sys.getenv "CAQTI_DEBUG_PARAM" with
| "true" -> true
| "false" -> false
| s ->
Log.err (fun f ->
f "Invalid value %s for CAQTI_DEBUG_PARAM, assuming false." s);
false
| exception Not_found -> false)
let make_pp_with_param ?dialect ?subst () ppf (req, param) =
let pp = make_pp ?subst ?dialect () in
pp ppf req;
if pp_with_param_enabled then
Format.fprintf ppf " %a" (Row.pp req.param_type) param
type liveness_witness = int option
let liveness_witness request =
assert (request.id <> None);
request.id