From 135715bf0ae4bc8901c2d352e55e0d71a4bc21f1 Mon Sep 17 00:00:00 2001 From: Maas-Maarten Zeeman Date: Sun, 22 May 2022 22:19:30 +0200 Subject: [PATCH] Added extra function to return a map with error information --- c_src/esqlite3_nif.c | 41 ++++++++++++++++++++++++++++++++++++++++- src/esqlite3.erl | 12 +++++++++++- src/esqlite3_nif.erl | 10 ++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/c_src/esqlite3_nif.c b/c_src/esqlite3_nif.c index fcf44a7..e082db2 100644 --- a/c_src/esqlite3_nif.c +++ b/c_src/esqlite3_nif.c @@ -282,7 +282,8 @@ make_extended_error_tuple(ErlNifEnv *env, int code) { /* internal use only */ return make_two_atom_tuple(env, "ok", "symlink"); } - return enif_make_tuple2(env, make_atom(env, "error"), enif_make_int(env, code)); + + return enif_make_tuple2(env, make_atom(env, "code"), enif_make_int(env, code)); } static const char * @@ -614,6 +615,42 @@ esqlite_close(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return make_atom(env, "ok"); } +/* + * Return a description of the last occurred error. + */ +static ERL_NIF_TERM +esqlite_error_info(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + esqlite3 *conn; + int rc; + + if(argc != 1) { + return enif_make_badarg(env); + } + + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) { + return enif_make_badarg(env); + } + + if(conn->db == NULL) { + enif_make_badarg(env); + } + + int code = sqlite3_extended_errcode(conn->db); + int extended_code = sqlite3_extended_errcode(conn->db); + const char *errstr = sqlite3_errstr(extended_code); + const char *errmsg = sqlite3_errmsg(conn->db); + + ERL_NIF_TERM info = enif_make_new_map(env); + enif_make_map_put(env, info, make_atom(env, "errcode"), enif_make_int(env, code), &info); + enif_make_map_put(env, info, make_atom(env, "extended_errcode"), enif_make_int(env, extended_code), &info); + enif_make_map_put(env, info, make_atom(env, "errstr"), make_binary(env, errstr, strlen(errstr)), &info); + enif_make_map_put(env, info, make_atom(env, "errmsg"), make_binary(env, errmsg, strlen(errmsg)), &info); + enif_make_map_put(env, info, make_atom(env, "error_offset"), enif_make_int(env, sqlite3_error_offset(conn->db)), &info); + + return info; +} + void update_callback(void *arg, int sqlite_operation_type, char const *sqlite_database, char const *sqlite_table, sqlite3_int64 sqlite_rowid) { @@ -1431,6 +1468,8 @@ static ErlNifFunc nif_funcs[] = { {"open", 1, esqlite_open, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"close", 1, esqlite_close, ERL_NIF_DIRTY_JOB_IO_BOUND}, + {"error_info", 1, esqlite_error_info}, + /* * Other interesting additions... trace. * wal_hook triggered after every commit. diff --git a/src/esqlite3.erl b/src/esqlite3.erl index fc650dc..2c5aafb 100644 --- a/src/esqlite3.erl +++ b/src/esqlite3.erl @@ -19,7 +19,10 @@ %% higher-level export -export([ - open/1, close/1, + open/1, + close/1, + + error_info/1, %% db connection functions set_update_hook/2, @@ -136,6 +139,13 @@ open(Filename) -> close(#esqlite3{db=Connection}) -> esqlite3_nif:close(Connection). +%% @doc Return a description of the last occurred error. +-spec error_info(Connection) -> ErrorMsg + when Connection :: esqlite3(), + ErrorMsg :: undefined | binary(). +error_info(#esqlite3{db=Connection}) -> + esqlite3_nif:error_info(Connection). + %% @doc Subscribe to database notifications. When rows are inserted deleted %% or updates, the process will receive messages: diff --git a/src/esqlite3_nif.erl b/src/esqlite3_nif.erl index e9232ec..58e7496 100644 --- a/src/esqlite3_nif.erl +++ b/src/esqlite3_nif.erl @@ -22,6 +22,7 @@ -export([ open/1, close/1, + error_info/1, set_update_hook/2, @@ -89,6 +90,15 @@ open(_Filename) -> close(_Db) -> erlang:nif_error(nif_library_not_loaded). +%% @doc Get an error messages for the last occurred error. +%% +-spec error_info(Connection) -> ErrorMsg + when Connection :: esqlite3(), + ErrorMsg :: map(). +error_info(_Db) -> + erlang:nif_error(nif_library_not_loaded). + + %% @doc Set an update hook %% -spec set_update_hook(Connection, Pid) -> Result