From 661e417c908b8922db7efe87444fcb0580be373b Mon Sep 17 00:00:00 2001 From: Maas-Maarten Zeeman Date: Mon, 29 Oct 2012 23:57:27 +0100 Subject: [PATCH] Better error responses. Fixes #1 --- c_src/esqlite3_nif.c | 65 +++++++++++++++++++++++++++++++++++++------ src/esqlite3.erl | 4 +-- test/esqlite_test.erl | 14 ++++------ 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/c_src/esqlite3_nif.c b/c_src/esqlite3_nif.c index dcc2ccd..42d4440 100644 --- a/c_src/esqlite3_nif.c +++ b/c_src/esqlite3_nif.c @@ -95,11 +95,60 @@ make_error_tuple(ErlNifEnv *env, const char *reason) return enif_make_tuple2(env, make_atom(env, "error"), make_atom(env, reason)); } -static ERL_NIF_TERM -make_sqlite3_error_tuple(ErlNifEnv *env, const char *msg) +static const char * +get_sqlite3_return_code_msg(int r) { + switch(r) { + case SQLITE_OK: return "ok"; + case SQLITE_ERROR : return "error"; + case SQLITE_INTERNAL: return "internal"; + case SQLITE_PERM: return "perm"; + case SQLITE_ABORT: return "abort"; + case SQLITE_BUSY: return "busy"; + case SQLITE_LOCKED: return "locked"; + case SQLITE_NOMEM: return "nomem"; + case SQLITE_READONLY: return "readonly"; + case SQLITE_INTERRUPT: return "interrupt"; + case SQLITE_IOERR: return "ioerror"; + case SQLITE_CORRUPT: return "corrupt"; + case SQLITE_NOTFOUND: return "notfound"; + case SQLITE_FULL: return "full"; + case SQLITE_CANTOPEN: return "cantopen"; + case SQLITE_PROTOCOL: return "protocol"; + case SQLITE_EMPTY: return "empty"; + case SQLITE_SCHEMA: return "schema"; + case SQLITE_TOOBIG: return "toobig"; + case SQLITE_CONSTRAINT: return "constraint"; + case SQLITE_MISMATCH: return "mismatch"; + case SQLITE_MISUSE: return "misuse"; + case SQLITE_NOLFS: return "nolfs"; + case SQLITE_AUTH: return "auth"; + case SQLITE_FORMAT: return "format"; + case SQLITE_RANGE: return "range"; + case SQLITE_NOTADB: return "notadb"; + case SQLITE_ROW: return "row"; + case SQLITE_DONE: return "done"; + } + return "unknown"; +} + +static const char * +get_sqlite3_error_msg(int error_code, sqlite3 *db) +{ + if(error_code == SQLITE_MISUSE) + return "Sqlite3 was invoked incorrectly."; + + return sqlite3_errmsg(db); +} + +static ERL_NIF_TERM +make_sqlite3_error_tuple(ErlNifEnv *env, int error_code, sqlite3 *db) +{ + const char *error_code_msg = get_sqlite3_return_code_msg(error_code); + const char *msg = get_sqlite3_error_msg(error_code, db); + return enif_make_tuple2(env, make_atom(env, "error"), - enif_make_tuple2(env, make_atom(env, "sqlite3_error"), + enif_make_tuple2(env, make_atom(env, error_code_msg), enif_make_string(env, msg, ERL_NIF_LATIN1))); } @@ -193,7 +242,7 @@ do_open(ErlNifEnv *env, esqlite_connection *db, const ERL_NIF_TERM arg) */ rc = sqlite3_open(filename, &db->db); if(rc != SQLITE_OK) { - error = make_sqlite3_error_tuple(env, sqlite3_errmsg(db->db)); + error = make_sqlite3_error_tuple(env, rc, db->db); sqlite3_close(db->db); db->db = NULL; @@ -215,7 +264,7 @@ do_exec(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) rc = sqlite3_exec(conn->db, (char *) bin.data, NULL, NULL, NULL); if(rc != SQLITE_OK) - return make_sqlite3_error_tuple(env, sqlite3_errmsg(conn->db)); + return make_sqlite3_error_tuple(env, rc, conn->db); return make_atom(env, "ok"); } @@ -239,7 +288,7 @@ do_prepare(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) rc = sqlite3_prepare_v2(conn->db, (char *) bin.data, bin.size, &(stmt->statement), &tail); if(rc != SQLITE_OK) - return make_sqlite3_error_tuple(env, sqlite3_errmsg(conn->db)); + return make_sqlite3_error_tuple(env, rc, conn->db); enif_keep_resource(conn); stmt->connection = conn; @@ -307,7 +356,7 @@ do_bind(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TERM arg) if(r == -1) return make_error_tuple(env, "wrong_type"); if(r != SQLITE_OK) - return make_sqlite3_error_tuple(env, sqlite3_errmsg(db)); + return make_sqlite3_error_tuple(env, r, db); list = tail; } @@ -421,7 +470,7 @@ do_close(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) rc = sqlite3_close(conn->db); if(rc != SQLITE_OK) - return make_sqlite3_error_tuple(env, sqlite3_errmsg(conn->db)); + return make_sqlite3_error_tuple(env, rc, conn->db); conn->db = NULL; return make_atom(env, "ok"); diff --git a/src/esqlite3.erl b/src/esqlite3.erl index 4444b3b..ec33fb1 100644 --- a/src/esqlite3.erl +++ b/src/esqlite3.erl @@ -52,8 +52,8 @@ open(Filename, Timeout) -> case receive_answer(Ref, Timeout) of ok -> {ok, Connection}; - Other -> - {error, Other} + {error, _Msg}=Error -> + Error end. %% @doc Execute a sql statement, returns a list with tuples. diff --git a/test/esqlite_test.erl b/test/esqlite_test.erl index 6d5c54e..57c83d8 100644 --- a/test/esqlite_test.erl +++ b/test/esqlite_test.erl @@ -140,16 +140,14 @@ map_test() -> [{one,"hello4"},{two,13}]] = esqlite3:map(Assoc, "select * from test_table", Db), ok. + +error1_msg_test() -> + {ok, Db} = esqlite3:open(":memory:"), + {error, {error, _Msg1}} = esqlite3:exec("dit is geen sql", Db), + {error, {cantopen, _Msg2}} = esqlite3:open("/dit/bestaat/niet"), + ok. -%%gen_db_test() -> - %% {ok, Conn} = gen_db:open(sqlite, ":memory:"), - %% [] = gen_db:execute("create table some_shit(hole_one varchar(10), hole_two int);", [], Conn), - %% [] = gen_db:execute("insert into some_shit values('dung', 100);", Conn), - %% [] = gen_db:execute("insert into some_shit values(?, ?);", ["manure", 1000], Conn), - %% ok. - -