You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
2.4 KiB
81 lines
2.4 KiB
(*
|
|
* Copyright (c) 2017 - present Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*)
|
|
open! IStd
|
|
module L = Logging
|
|
|
|
exception Error of string
|
|
|
|
let error ~fatal fmt =
|
|
(if fatal then Format.kasprintf (fun err -> raise (Error err)) else L.internal_error) fmt
|
|
|
|
|
|
let check_sqlite_error ?(fatal= false) ~log rc =
|
|
match (rc : Sqlite3.Rc.t) with
|
|
| OK | ROW ->
|
|
()
|
|
| _ as err ->
|
|
error ~fatal "%s: %s" log (Sqlite3.Rc.to_string err)
|
|
|
|
|
|
let exec db ~log ~stmt =
|
|
(* Call [check_sqlite_error] with [fatal:true] and catch exceptions to rewrite the error message. This avoids allocating the error string when not needed. *)
|
|
try check_sqlite_error ~fatal:true ~log (Sqlite3.exec db stmt)
|
|
with Error err -> error ~fatal:true "exec: %s" err
|
|
|
|
|
|
let finalize ~log stmt =
|
|
try check_sqlite_error ~fatal:true ~log (Sqlite3.finalize stmt) with
|
|
| Error err ->
|
|
error ~fatal:true "finalize: %s" err
|
|
| Sqlite3.Error err ->
|
|
error ~fatal:true "finalize: %s: %s" log err
|
|
|
|
|
|
let sqlite_result_rev_list_step ?finalize:(do_finalize = true) ~log stmt =
|
|
let rec aux rev_results =
|
|
match Sqlite3.step stmt with
|
|
| Sqlite3.Rc.ROW ->
|
|
(* the operation returned a result, get it *)
|
|
let value = Some (Sqlite3.column stmt 0) in
|
|
aux (value :: rev_results)
|
|
| DONE ->
|
|
rev_results
|
|
| err ->
|
|
L.die InternalError "%s: %s" log (Sqlite3.Rc.to_string err)
|
|
in
|
|
if do_finalize then protect ~finally:(fun () -> finalize ~log stmt) ~f:(fun () -> aux [])
|
|
else aux []
|
|
|
|
|
|
let sqlite_result_step ?finalize ~log stmt =
|
|
match sqlite_result_rev_list_step ?finalize ~log stmt with
|
|
| [] ->
|
|
None
|
|
| [x] ->
|
|
x
|
|
| l ->
|
|
L.die InternalError "%s: zero or one result expected, got %d instead" log (List.length l)
|
|
|
|
|
|
let sqlite_unit_step ?finalize ~log stmt =
|
|
match sqlite_result_rev_list_step ?finalize ~log stmt with
|
|
| [] ->
|
|
()
|
|
| l ->
|
|
L.die InternalError "%s: exactly zero result expected, got %d instead" log (List.length l)
|
|
|
|
|
|
let db_close db =
|
|
if not (Sqlite3.db_close db) then
|
|
raise
|
|
(Error
|
|
(Printf.sprintf "closing: %s (%s)"
|
|
(Sqlite3.errcode db |> Sqlite3.Rc.to_string)
|
|
(Sqlite3.errmsg db)))
|