@@ -16,32 +16,31 @@ let host = ref None
1616let port = ref None
1717let user = ref None
1818let password = ref None
19- let database = ref ( Some " ocsipersist" )
19+ let database = ref " ocsipersist"
2020let unix_domain_socket_dir = ref None
21+ let hashtbl_size = ref 8
2122
22- let connect () = PGOCaml. connect
23+ let make_hashtbl () = Hashtbl. create ! hashtbl_size
24+
25+ let connect () =
26+ lwt dbhandle = PGOCaml. connect
2327 ?host:! host
2428 ?port:! port
2529 ?user:! user
2630 ?password:! password
27- ?database:! database
31+ ?database:( Some ! database)
2832 ?unix_domain_socket_dir:! unix_domain_socket_dir
29- ()
33+ () in
34+ PGOCaml. set_private_data dbhandle @@ make_hashtbl () ;
35+ Lwt. return dbhandle
3036
3137let (>>) f g = f >> = fun _ -> g
3238
33- let pool : (string, bool ) Hashtbl.t PGOCaml.t Lwt_pool.t =
39+ let pool : (string, unit ) Hashtbl.t PGOCaml.t Lwt_pool.t =
3440 Lwt_pool. create 16 ~validate: PGOCaml. alive connect
3541
3642let use_pool f = Lwt_pool. use pool (fun db -> f db)
3743
38- let exec db query params =
39- PGOCaml. prepare db ~query () >>
40- let params = params |> List. map @@ fun x -> Some (PGOCaml. string_of_bytea x) in
41- PGOCaml. execute db ~params ()
42-
43- let (@.) f g = fun x -> f (g x) (* function composition *)
44-
4544let key_value_of_row = function
4645 | [Some key; Some value] -> (PGOCaml. bytea_of_string key, PGOCaml. bytea_of_string value)
4746 | _ -> raise Ocsipersist_error
@@ -54,6 +53,33 @@ let one = function
5453let marshal value = Marshal. to_string value []
5554let unmarshal str = Marshal. from_string str 0
5655
56+ let prepare db query =
57+ let hashtbl = PGOCaml. private_data db in
58+ (* Get a unique name for this query using an MD5 digest. *)
59+ let name = Digest. to_hex (Digest. string query) in
60+ (* Have we prepared this statement already? If not, do so. *)
61+ let is_prepared = Hashtbl. mem hashtbl name in
62+ lwt () = if is_prepared then Lwt. return () else begin
63+ PGOCaml. prepare db ~name ~query () >>
64+ Lwt. return @@ Hashtbl. add hashtbl name ()
65+ end in
66+ Lwt. return name
67+
68+ let exec db query params =
69+ lwt name = prepare db query in
70+ let params = params |> List. map @@ fun x -> Some (PGOCaml. string_of_bytea x) in
71+ PGOCaml. execute db ~name ~params ()
72+
73+ let cursor db query params f =
74+ lwt name = prepare db query in
75+ let params = params |> List. map @@ fun x -> Some (PGOCaml. string_of_bytea x) in
76+ PGOCaml. cursor db ~name ~params @@
77+ fun row -> let (key,value) = key_value_of_row row in f
78+ (PGOCaml. bytea_of_string key)
79+ (unmarshal @@ PGOCaml. bytea_of_string value)
80+
81+ let (@.) f g = fun x -> f (g x) (* function composition *)
82+
5783let create_table db table =
5884 let query = sprintf " CREATE TABLE IF NOT EXISTS %s \
5985 (key TEXT, value BYTEA, PRIMARY KEY(key))" table
@@ -64,6 +90,7 @@ let insert db table key value =
6490 ON CONFLICT ( key ) DO UPDATE SET value = $2 " table
6591 in exec db query [key; marshal value] >> Lwt. return ()
6692
93+
6794type store = string
6895
6996type 'a t = {
@@ -77,7 +104,7 @@ let open_store store = use_pool @@ fun db ->
77104let make_persistent_lazy_lwt ~store ~name ~default = use_pool @@ fun db ->
78105 let query = sprintf " SELECT value FROM %s WHERE key = $1 " store in
79106 lwt result = exec db query [name] in
80- lwt _ = begin match result with
107+ lwt () = begin match result with
81108 | [] ->
82109 lwt default = default () in
83110 insert db store name default
@@ -129,11 +156,7 @@ let length table = use_pool @@ fun db ->
129156
130157let iter_step f table = use_pool @@ fun db ->
131158 let query = sprintf " SELECT * FROM %s " table in
132- PGOCaml. prepare db ~query () >>
133- PGOCaml. cursor db ~params: [] @@
134- fun row -> let (key,value) = key_value_of_row row in f
135- (PGOCaml. bytea_of_string key)
136- (unmarshal @@ PGOCaml. bytea_of_string value)
159+ cursor db query [] f
137160
138161let iter_table = iter_step
139162
@@ -162,8 +185,13 @@ let parse_global_config = function
162185 end
163186 | ("user" , u ) -> user := Some u
164187 | ("password" , pw ) -> password := Some pw
165- | ("database" , db ) -> database := Some db
188+ | ("database" , db ) -> database := db
166189 | ("unix_domain_socket_dir" , udsd ) -> unix_domain_socket_dir := Some udsd
190+ | ("hashtbl_size" , hts ) -> begin
191+ try hashtbl_size := int_of_string hts
192+ with Failure _ -> raise @@ Ocsigen_extensions. Error_in_config_file
193+ " hashtbl_size is not an integer"
194+ end
167195 | _ -> raise @@ Ocsigen_extensions. Error_in_config_file
168196 " Unexpected attribute for <database> in Ocsipersist config"
169197 in ignore @@ List. map parse_attr attrs; ()
0 commit comments