diff --git a/c_src/esqlite3_nif.c b/c_src/esqlite3_nif.c index b40f6a5..7653422 100644 --- a/c_src/esqlite3_nif.c +++ b/c_src/esqlite3_nif.c @@ -63,7 +63,8 @@ typedef enum { cmd_column_types, cmd_close, cmd_stop, - cmd_insert + cmd_insert, + cmd_get_autocommit, } command_type; typedef struct { @@ -486,6 +487,16 @@ do_bind(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TERM arg) return make_atom(env, "ok"); } +static ERL_NIF_TERM +do_get_autocommit(ErlNifEnv *env, esqlite_connection *conn) +{ + if(sqlite3_get_autocommit(conn->db) != 0) { + return make_atom(env, "true"); + } else { + return make_atom(env, "false"); + } +} + static ERL_NIF_TERM make_binary(ErlNifEnv *env, const void *bytes, unsigned int size) { @@ -716,6 +727,8 @@ evaluate_command(esqlite_command *cmd, esqlite_connection *conn) return do_close(cmd->env, conn, cmd->arg); case cmd_insert: return do_insert(cmd->env, conn, cmd->arg); + case cmd_get_autocommit: + return do_get_autocommit(cmd->env, conn); default: return make_error_tuple(cmd->env, "invalid_command"); } @@ -951,6 +964,34 @@ esqlite_insert(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, db, cmd); } +static ERL_NIF_TERM +esqlite_get_autocommit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + esqlite_connection *db; + esqlite_command *cmd = NULL; + ErlNifPid pid; + + if(argc != 3) + return enif_make_badarg(env); + if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &db)) + return enif_make_badarg(env); + if(!enif_is_ref(env, argv[1])) + return make_error_tuple(env, "invalid_ref"); + if(!enif_get_local_pid(env, argv[2], &pid)) + return make_error_tuple(env, "invalid_pid"); + + cmd = command_create(); + if(!cmd) + return make_error_tuple(env, "command_create_failed"); + + /* command */ + cmd->type = cmd_get_autocommit; + cmd->ref = enif_make_copy(cmd->env, argv[1]); + cmd->pid = pid; + + return push_command(env, db, cmd); +} + /* * Prepare the sql statement */ @@ -1245,6 +1286,7 @@ static ErlNifFunc nif_funcs[] = { {"changes", 3, esqlite_changes}, {"prepare", 4, esqlite_prepare}, {"insert", 4, esqlite_insert}, + {"get_autocommit", 3, esqlite_get_autocommit}, {"multi_step", 5, esqlite_multi_step}, {"reset", 4, esqlite_reset}, // TODO: {"esqlite_bind", 3, esqlite_bind_named}, diff --git a/src/esqlite3.erl b/src/esqlite3.erl index 23046aa..12b532e 100644 --- a/src/esqlite3.erl +++ b/src/esqlite3.erl @@ -26,6 +26,8 @@ exec/2, exec/3, changes/1, changes/2, insert/2, + get_autocommit/1, + get_autocommit/2, prepare/2, prepare/3, step/1, step/2, reset/1, @@ -293,6 +295,17 @@ insert(Sql, {connection, _Ref, Connection}, Timeout) -> ok = esqlite3_nif:insert(Connection, Ref, self(), Sql), receive_answer(Ref, Timeout). +%% @doc Get autocommit +%% +%% @spec get_autocommit(connection) -> true | false +get_autocommit(Connection) -> + get_autocommit(Connection, ?DEFAULT_TIMEOUT). + +get_autocommit({connection, _Ref, Connection}, Timeout) -> + Ref = make_ref(), + ok = esqlite3_nif:get_autocommit(Connection, Ref, self()), + receive_answer(Ref, Timeout). + %% @doc Prepare a statement %% %% @spec prepare(iolist(), connection()) -> {ok, prepared_statement()} | {error, error_message()} diff --git a/src/esqlite3_nif.erl b/src/esqlite3_nif.erl index 64f8598..0befc27 100644 --- a/src/esqlite3_nif.erl +++ b/src/esqlite3_nif.erl @@ -27,6 +27,7 @@ exec/4, changes/3, insert/4, + get_autocommit/3, prepare/4, multi_step/5, reset/4, @@ -140,3 +141,9 @@ close(_Db, _Ref, _Dest) -> %% @spec insert(connection(), Ref::reference(), Dest::pid(), string()) -> {ok, integer()} | {error, message()} insert(_Db, _Ref, _Dest, _Sql) -> erlang:nif_error(nif_library_not_loaded). + +%% @doc Get automcommit +%% +%% @spec get_autocommit(connection(), Ref::reference(), Dest::pid()) -> true | false +get_autocommit(_Db, _Ref, _Dest) -> + erlang:nif_error(nif_library_not_loaded). diff --git a/test/esqlite_test.erl b/test/esqlite_test.erl index 3a4580f..3b23576 100644 --- a/test/esqlite_test.erl +++ b/test/esqlite_test.erl @@ -20,6 +20,17 @@ open_multiple_different_databases_test() -> {ok, _C2} = esqlite3:open("test2.db"), ok. +get_autocommit_test() -> + {ok, Db} = esqlite3:open(":memory:"), + ok = esqlite3:exec("CREATE TABLE test (id INTEGER PRIMARY KEY, val STRING);", Db), + true = esqlite3:get_autocommit(Db), + ok = esqlite3:exec("BEGIN;", Db), + false = esqlite3:get_autocommit(Db), + ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is a test');", Db), + ok = esqlite3:exec("COMMIT;", Db), + true = esqlite3:get_autocommit(Db), + ok. + update_hook_test() -> {ok, Db} = esqlite3:open(":memory:"), ok = esqlite3:set_update_hook(self(), Db), @@ -32,7 +43,6 @@ update_hook_test() -> ok = receive {delete, "test", 1} -> ok after 150 -> no_message end, ok. - simple_query_test() -> {ok, Db} = esqlite3:open(":memory:"), ok = esqlite3:exec("begin;", Db),