Skip to content

Commit

Permalink
[sqlite] print extended error codes on errors
Browse files Browse the repository at this point in the history
Summary:
Since v5.2.0, Sqlite ocaml bindings provide access to extended error codes. This means it's now possible to surface much more specific error messaging. For example, the basic error code for failing to open a database is `SQLITE_CANTOPEN (14)`, but there are many more extended error codes associated to this
```
SQLITE_CANTOPEN_CONVPATH (1038)
SQLITE_CANTOPEN_DIRTYWAL (1294)
SQLITE_CANTOPEN_FULLPATH (782)
SQLITE_CANTOPEN_ISDIR (526)
SQLITE_CANTOPEN_NOTEMPDIR (270)
SQLITE_CANTOPEN_SYMLINK (1550)
```
The ocaml bindings only surface the numerical code, not the string description, so we print that together with the textual description of the basic code.

Reviewed By: geralt-encore

Differential Revision:
D67187200

Privacy Context Container: L1208441

fbshipit-source-id: b0bebae73a371373cba06c14aa1e31f93cac8820
  • Loading branch information
ngorogiannis authored and facebook-github-bot committed Dec 13, 2024
1 parent 45e93a9 commit 1255eae
Showing 1 changed file with 12 additions and 8 deletions.
20 changes: 12 additions & 8 deletions infer/src/base/SqliteUtils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module F = Format
module L = Logging

exception Error of string
Expand All @@ -13,12 +14,16 @@ exception DataTooBig

let error fmt = Format.kasprintf (fun err -> raise (Error err)) fmt

let pp_db_error fmt db =
F.fprintf fmt "(%s [%d])" (Sqlite3.errmsg db) (Sqlite3.extended_errcode_int db)


let check_result_code db ~log rc =
match (rc : Sqlite3.Rc.t) with
| OK | ROW ->
()
| _ as err ->
error "%s: %s (%s)" log (Sqlite3.Rc.to_string err) (Sqlite3.errmsg db)
error "%s: %s %a" log (Sqlite3.Rc.to_string err) pp_db_error db


let exec db ~log ~stmt =
Expand All @@ -27,15 +32,15 @@ let exec db ~log ~stmt =
PerfEvent.log_begin_event logger ~name:"sql exec" ~arguments:[("stmt", `String log)] () ) ;
let rc = Sqlite3.exec db stmt in
PerfEvent.(log (fun logger -> log_end_event logger ())) ;
try check_result_code db ~log rc with Error err -> error "exec: %s (%s)" err (Sqlite3.errmsg db)
try check_result_code db ~log rc with Error err -> error "exec: %s %a" err pp_db_error db


let finalize db ~log stmt =
try check_result_code db ~log (Sqlite3.finalize stmt) with
| Error err ->
error "finalize: %s (%s)" err (Sqlite3.errmsg db)
error "finalize: %s %a" err pp_db_error db
| Sqlite3.Error err ->
error "finalize: %s: %s (%s)" log err (Sqlite3.errmsg db)
error "finalize: %s: %s %a" log err pp_db_error db


let result_fold_rows ?finalize:(do_finalize = true) db ~log stmt ~init ~f =
Expand All @@ -47,7 +52,7 @@ let result_fold_rows ?finalize:(do_finalize = true) db ~log stmt ~init ~f =
| DONE ->
accum
| err ->
L.die InternalError "%s: %s (%s)" log (Sqlite3.Rc.to_string err) (Sqlite3.errmsg db)
L.die InternalError "%s: %s %a" log (Sqlite3.Rc.to_string err) pp_db_error db
in
if do_finalize then protect ~finally:(fun () -> finalize db ~log stmt) ~f:(fun () -> aux init stmt)
else aux init stmt
Expand Down Expand Up @@ -86,9 +91,8 @@ 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) ) )
(F.asprintf "closing: %s %a" (Sqlite3.errcode db |> Sqlite3.Rc.to_string) pp_db_error db)
)


(* an underapproximation of the maximum path length allowed in sqlite *)
Expand Down

0 comments on commit 1255eae

Please sign in to comment.