Add function to get the last insert rowid (#62)

* Add function to get the last insert rowid

* Update esqlite3.erl

Co-authored-by: Maas-Maarten Zeeman <mmzeeman@xs4all.nl>
This commit is contained in:
Joe Freeman
2022-01-03 17:05:27 +00:00
committed by GitHub
parent d77b1fa76c
commit 09a9c86097
4 changed files with 72 additions and 0 deletions

View File

@@ -64,6 +64,7 @@ typedef enum {
cmd_close, cmd_close,
cmd_stop, cmd_stop,
cmd_insert, cmd_insert,
cmd_last_insert_rowid,
cmd_get_autocommit, cmd_get_autocommit,
} command_type; } command_type;
@@ -373,6 +374,14 @@ do_insert(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
return make_ok_tuple(env, last_rowid_term); return make_ok_tuple(env, last_rowid_term);
} }
static ERL_NIF_TERM
do_last_insert_rowid(ErlNifEnv *env, esqlite_connection *conn)
{
sqlite3_int64 last_rowid = sqlite3_last_insert_rowid(conn->db);
ERL_NIF_TERM last_rowid_term = enif_make_int64(env, last_rowid);
return make_ok_tuple(env, last_rowid_term);
}
/* /*
*/ */
static ERL_NIF_TERM static ERL_NIF_TERM
@@ -731,6 +740,8 @@ evaluate_command(esqlite_command *cmd, esqlite_connection *conn)
return do_close(cmd->env, conn, cmd->arg); return do_close(cmd->env, conn, cmd->arg);
case cmd_insert: case cmd_insert:
return do_insert(cmd->env, conn, cmd->arg); return do_insert(cmd->env, conn, cmd->arg);
case cmd_last_insert_rowid:
return do_last_insert_rowid(cmd->env, conn);
case cmd_get_autocommit: case cmd_get_autocommit:
return do_get_autocommit(cmd->env, conn); return do_get_autocommit(cmd->env, conn);
default: default:
@@ -968,6 +979,34 @@ esqlite_insert(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return push_command(env, db, cmd); return push_command(env, db, cmd);
} }
static ERL_NIF_TERM
esqlite_last_insert_rowid(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_last_insert_rowid;
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_get_autocommit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) esqlite_get_autocommit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{ {
@@ -1308,6 +1347,7 @@ static ErlNifFunc nif_funcs[] = {
{"changes", 3, esqlite_changes}, {"changes", 3, esqlite_changes},
{"prepare", 4, esqlite_prepare}, {"prepare", 4, esqlite_prepare},
{"insert", 4, esqlite_insert}, {"insert", 4, esqlite_insert},
{"last_insert_rowid", 3, esqlite_last_insert_rowid},
{"get_autocommit", 3, esqlite_get_autocommit}, {"get_autocommit", 3, esqlite_get_autocommit},
{"multi_step", 5, esqlite_multi_step}, {"multi_step", 5, esqlite_multi_step},
{"reset", 4, esqlite_reset}, {"reset", 4, esqlite_reset},

View File

@@ -26,6 +26,7 @@
exec/2, exec/3, exec/4, exec/2, exec/3, exec/4,
changes/1, changes/2, changes/1, changes/2,
insert/2, insert/2,
last_insert_rowid/1,
get_autocommit/1, get_autocommit/1,
get_autocommit/2, get_autocommit/2,
prepare/2, prepare/3, prepare/2, prepare/3,
@@ -380,6 +381,21 @@ insert(Sql, {connection, _Ref, Connection}, Timeout) ->
ok = esqlite3_nif:insert(Connection, Ref, self(), Sql), ok = esqlite3_nif:insert(Connection, Ref, self(), Sql),
receive_answer(Connection, Ref, Timeout). receive_answer(Connection, Ref, Timeout).
%% @doc Get the last insert rowid, using the default timeout.
%%
-spec last_insert_rowid(connection()) -> {ok, rowid()} | {error, _}.
last_insert_rowid(Connection) ->
last_insert_rowid(Connection, ?DEFAULT_TIMEOUT).
%% @doc Get the last insert rowid.
%%
-spec last_insert_rowid(connection(), timeout()) -> {ok, integer()} | {error, _}.
last_insert_rowid({connection, _Ref, Connection}, Timeout) ->
Ref = make_ref(),
ok = esqlite3_nif:last_insert_rowid(Connection, Ref, self()),
receive_answer(Connection, Ref, Timeout).
%% @doc Get autocommit
%% @doc Check if the connection is in auto-commit mode. %% @doc Check if the connection is in auto-commit mode.
%% See: [https://sqlite.org/c3ref/get_autocommit.html] for more details. %% See: [https://sqlite.org/c3ref/get_autocommit.html] for more details.
%% %%

View File

@@ -27,6 +27,7 @@
exec/4, exec/4,
changes/3, changes/3,
insert/4, insert/4,
last_insert_rowid/3,
get_autocommit/3, get_autocommit/3,
prepare/4, prepare/4,
multi_step/5, multi_step/5,
@@ -145,6 +146,12 @@ close(_Db, _Ref, _Dest) ->
insert(_Db, _Ref, _Dest, _Sql) -> insert(_Db, _Ref, _Dest, _Sql) ->
erlang:nif_error(nif_library_not_loaded). erlang:nif_error(nif_library_not_loaded).
%% @doc Get the last insert rowid.
%%
%% @spec insert(connection(), Ref::reference(), Dest::pid()) -> {ok, integer()} | {error, message()}
last_insert_rowid(_Db, _Ref, _Dest) ->
erlang:nif_error(nif_library_not_loaded).
%% @doc Get automcommit %% @doc Get automcommit
%% %%
-spec get_autocommit(esqlite:connection(), reference(), pid()) -> ok | {error, any()}. -spec get_autocommit(esqlite:connection(), reference(), pid()) -> ok | {error, any()}.

View File

@@ -31,6 +31,15 @@ get_autocommit_test() ->
true = esqlite3:get_autocommit(Db), true = esqlite3:get_autocommit(Db),
ok. ok.
last_insert_rowid_test() ->
{ok, Db} = esqlite3:open(":memory:"),
ok = esqlite3:exec("CREATE TABLE test (id INTEGER PRIMARY KEY, val STRING);", Db),
ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is a test');", Db),
{ok, 1} = esqlite3:last_insert_rowid(Db),
ok = esqlite3:exec("INSERT INTO test (val) VALUES ('this is another test');", Db),
{ok, 2} = esqlite3:last_insert_rowid(Db),
ok.
update_hook_test() -> update_hook_test() ->
{ok, Db} = esqlite3:open(":memory:"), {ok, Db} = esqlite3:open(":memory:"),
ok = esqlite3:set_update_hook(self(), Db), ok = esqlite3:set_update_hook(self(), Db),