Add esqlite3:changes/3 function to get nr of affected rows

This commit is contained in:
Arjan Scherpenisse
2014-06-15 00:14:11 +02:00
parent 3847315586
commit 476c34e1e3
4 changed files with 78 additions and 1 deletions

View File

@@ -52,6 +52,7 @@ typedef enum {
cmd_unknown, cmd_unknown,
cmd_open, cmd_open,
cmd_exec, cmd_exec,
cmd_changes,
cmd_prepare, cmd_prepare,
cmd_bind, cmd_bind,
cmd_step, cmd_step,
@@ -280,6 +281,18 @@ do_exec(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
return make_atom(env, "ok"); return make_atom(env, "ok");
} }
/*
* Nr of changes
*/
static ERL_NIF_TERM
do_changes(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
{
int changes = sqlite3_changes(conn->db);
ERL_NIF_TERM changes_term = enif_make_int64(env, changes);
return make_ok_tuple(env, changes_term);
}
/* /*
* insert action * insert action
*/ */
@@ -544,6 +557,8 @@ evaluate_command(esqlite_command *cmd, esqlite_connection *conn)
return do_open(cmd->env, conn, cmd->arg); return do_open(cmd->env, conn, cmd->arg);
case cmd_exec: case cmd_exec:
return do_exec(cmd->env, conn, cmd->arg); return do_exec(cmd->env, conn, cmd->arg);
case cmd_changes:
return do_changes(cmd->env, conn, cmd->arg);
case cmd_prepare: case cmd_prepare:
return do_prepare(cmd->env, conn, cmd->arg); return do_prepare(cmd->env, conn, cmd->arg);
case cmd_step: case cmd_step:
@@ -699,6 +714,37 @@ esqlite_exec(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return push_command(env, db, cmd); return push_command(env, db, cmd);
} }
/*
* Count the nr of changes of last statement
*/
static ERL_NIF_TERM
esqlite_changes(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_changes;
cmd->ref = enif_make_copy(cmd->env, argv[1]);
cmd->pid = pid;
return push_command(env, db, cmd);
}
static ERL_NIF_TERM static ERL_NIF_TERM
esqlite_insert(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) esqlite_insert(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{ {
@@ -940,6 +986,7 @@ static ErlNifFunc nif_funcs[] = {
{"start", 0, esqlite_start}, {"start", 0, esqlite_start},
{"open", 4, esqlite_open}, {"open", 4, esqlite_open},
{"exec", 4, esqlite_exec}, {"exec", 4, esqlite_exec},
{"changes", 3, esqlite_changes},
{"prepare", 4, esqlite_prepare}, {"prepare", 4, esqlite_prepare},
{"insert", 4, esqlite_insert}, {"insert", 4, esqlite_insert},
{"step", 3, esqlite_step}, {"step", 3, esqlite_step},

View File

@@ -23,8 +23,9 @@
%% higher-level export %% higher-level export
-export([open/1, open/2, -export([open/1, open/2,
exec/2, exec/3, exec/2, exec/3,
changes/1, changes/2,
insert/2, insert/2,
prepare/2, prepare/3, prepare/2, prepare/3,
step/1, step/2, step/1, step/2,
bind/2, bind/3, bind/2, bind/3,
fetchone/1, fetchone/1,
@@ -200,6 +201,16 @@ exec(Sql, {connection, _Ref, Connection}, Timeout) ->
ok = esqlite3_nif:exec(Connection, Ref, self(), Sql), ok = esqlite3_nif:exec(Connection, Ref, self(), Sql),
receive_answer(Ref, Timeout). receive_answer(Ref, Timeout).
%% @doc Return the number of affected rows of last statement.
changes(Connection) ->
changes(Connection, ?DEFAULT_TIMEOUT).
%% @doc Return the number of affected rows of last statement.
changes({connection, _Ref, Connection}, Timeout) ->
Ref = make_ref(),
ok = esqlite3_nif:changes(Connection, Ref, self()),
receive_answer(Ref, Timeout).
%% @doc Insert records, returns the last rowid. %% @doc Insert records, returns the last rowid.
%% %%
%% @spec insert(iolist(), connection()) -> {ok, integer()} | {error, error_message()} %% @spec insert(iolist(), connection()) -> {ok, integer()} | {error, error_message()}

View File

@@ -24,6 +24,7 @@
-export([start/0, -export([start/0,
open/4, open/4,
exec/4, exec/4,
changes/3,
insert/4, insert/4,
prepare/4, prepare/4,
step/3, step/3,
@@ -70,6 +71,14 @@ open(_Db, _Ref, _Dest, _Filename) ->
exec(_Db, _Ref, _Dest, _Sql) -> exec(_Db, _Ref, _Dest, _Sql) ->
exit(nif_library_not_loaded). exit(nif_library_not_loaded).
%% @doc Get the number of affected rows of last statement
%%
%% When the statement is executed Dest will receive message {Ref, answer()}
%% with answer() integer | {error, reason()}
%%
changes(_Db, _Ref, _Dest) ->
exit(nif_library_not_loaded).
%% @doc %% @doc
%% %%
%% @spec prepare(connection(), reference(), pid(), string()) -> ok | {error, message()} %% @spec prepare(connection(), reference(), pid(), string()) -> ok | {error, message()}

View File

@@ -25,11 +25,20 @@ simple_query_test() ->
ok = esqlite3:exec("begin;", Db), ok = esqlite3:exec("begin;", Db),
ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db),
ok = esqlite3:exec(["insert into test_table values(", "\"hello1\"", ",", "10" ");"], Db), ok = esqlite3:exec(["insert into test_table values(", "\"hello1\"", ",", "10" ");"], Db),
{ok, 1} = esqlite3:changes(Db),
ok = esqlite3:exec(["insert into test_table values(", "\"hello2\"", ",", "11" ");"], Db), ok = esqlite3:exec(["insert into test_table values(", "\"hello2\"", ",", "11" ");"], Db),
{ok, 1} = esqlite3:changes(Db),
ok = esqlite3:exec(["insert into test_table values(", "\"hello3\"", ",", "12" ");"], Db), ok = esqlite3:exec(["insert into test_table values(", "\"hello3\"", ",", "12" ");"], Db),
{ok, 1} = esqlite3:changes(Db),
ok = esqlite3:exec(["insert into test_table values(", "\"hello4\"", ",", "13" ");"], Db), ok = esqlite3:exec(["insert into test_table values(", "\"hello4\"", ",", "13" ");"], Db),
{ok, 1} = esqlite3:changes(Db),
ok = esqlite3:exec("commit;", Db), ok = esqlite3:exec("commit;", Db),
ok = esqlite3:exec("select * from test_table;", Db), ok = esqlite3:exec("select * from test_table;", Db),
ok = esqlite3:exec("delete from test_table;", Db),
{ok, 4} = esqlite3:changes(Db),
ok. ok.
prepare_test() -> prepare_test() ->
@@ -39,6 +48,7 @@ prepare_test() ->
{ok, Statement} = esqlite3:prepare("insert into test_table values(\"one\", 2)", Db), {ok, Statement} = esqlite3:prepare("insert into test_table values(\"one\", 2)", Db),
'$done' = esqlite3:step(Statement), '$done' = esqlite3:step(Statement),
{ok, 1} = esqlite3:changes(Db),
ok = esqlite3:exec(["insert into test_table values(", "\"hello4\"", ",", "13" ");"], Db), ok = esqlite3:exec(["insert into test_table values(", "\"hello4\"", ",", "13" ");"], Db),