add insert function to get last insert rowid
This commit is contained in:
@@ -57,7 +57,8 @@ typedef enum {
|
||||
cmd_step,
|
||||
cmd_column_names,
|
||||
cmd_close,
|
||||
cmd_stop
|
||||
cmd_stop,
|
||||
cmd_insert
|
||||
} command_type;
|
||||
|
||||
typedef struct {
|
||||
@@ -277,6 +278,27 @@ do_exec(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
|
||||
return make_atom(env, "ok");
|
||||
}
|
||||
|
||||
/*
|
||||
* insert action
|
||||
*/
|
||||
static ERL_NIF_TERM
|
||||
do_insert(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
|
||||
{
|
||||
ErlNifBinary bin;
|
||||
int rc;
|
||||
ERL_NIF_TERM eos = enif_make_int(env, 0);
|
||||
|
||||
enif_inspect_iolist_as_binary(env,
|
||||
enif_make_list2(env, arg, eos), &bin);
|
||||
|
||||
rc = sqlite3_exec(conn->db, (char *) bin.data, NULL, NULL, NULL);
|
||||
if(rc != SQLITE_OK)
|
||||
return make_sqlite3_error_tuple(env, rc, conn->db);
|
||||
sqlite3_int64 last_rowid = sqlite3_last_insert_rowid(conn->db);
|
||||
ERL_NIF_TERM last_rowid_term = enif_make_int(env, last_rowid);
|
||||
return make_ok_tuple(env, last_rowid_term);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
static ERL_NIF_TERM
|
||||
@@ -530,6 +552,8 @@ evaluate_command(esqlite_command *cmd, esqlite_connection *conn)
|
||||
return do_column_names(cmd->env, cmd->stmt);
|
||||
case cmd_close:
|
||||
return do_close(cmd->env, conn, cmd->arg);
|
||||
case cmd_insert:
|
||||
return do_insert(cmd->env, conn, cmd->arg);
|
||||
default:
|
||||
return make_error_tuple(cmd->env, "invalid_command");
|
||||
}
|
||||
@@ -673,6 +697,35 @@ esqlite_exec(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
return push_command(env, db, cmd);
|
||||
}
|
||||
|
||||
static ERL_NIF_TERM
|
||||
esqlite_insert(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
esqlite_connection *db;
|
||||
esqlite_command *cmd = NULL;
|
||||
ErlNifPid pid;
|
||||
|
||||
if(argc != 4)
|
||||
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_insert;
|
||||
cmd->ref = enif_make_copy(cmd->env, argv[1]);
|
||||
cmd->pid = pid;
|
||||
cmd->arg = enif_make_copy(cmd->env, argv[3]);
|
||||
|
||||
return push_command(env, db, cmd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare the sql statement
|
||||
@@ -884,6 +937,7 @@ static ErlNifFunc nif_funcs[] = {
|
||||
{"open", 4, esqlite_open},
|
||||
{"exec", 4, esqlite_exec},
|
||||
{"prepare", 4, esqlite_prepare},
|
||||
{"insert", 4, esqlite_insert},
|
||||
{"step", 3, esqlite_step},
|
||||
// TODO: {"esqlite_bind", 3, esqlite_bind_named},
|
||||
{"bind", 4, esqlite_bind},
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
%% higher-level export
|
||||
-export([open/1, open/2,
|
||||
exec/2, exec/3,
|
||||
insert/2,
|
||||
prepare/2, prepare/3,
|
||||
step/1, step/2,
|
||||
bind/2, bind/3,
|
||||
@@ -199,6 +200,20 @@ exec(Sql, {connection, _Ref, Connection}, Timeout) ->
|
||||
ok = esqlite3_nif:exec(Connection, Ref, self(), Sql),
|
||||
receive_answer(Ref, Timeout).
|
||||
|
||||
%% @doc Insert records, returns the last rowid.
|
||||
%%
|
||||
%% @spec insert(iolist(), connection()) -> integer() | {error, error_message()}
|
||||
insert(Sql, Connection) ->
|
||||
insert(Sql, Connection, ?DEFAULT_TIMEOUT).
|
||||
|
||||
%% @doc Insert
|
||||
%%
|
||||
%% @spec insert(iolist(), connection(), timeout()) -> integer() | {error, error_message()}
|
||||
insert(Sql, {connection, _Ref, Connection}, Timeout) ->
|
||||
Ref = make_ref(),
|
||||
ok = esqlite3_nif:insert(Connection, Ref, self(), Sql),
|
||||
receive_answer(Ref, Timeout).
|
||||
|
||||
%% @doc Prepare a statement
|
||||
%%
|
||||
%% @spec prepare(iolist(), connection()) -> {ok, prepared_statement()} | {error, error_message()}
|
||||
|
||||
@@ -22,14 +22,15 @@
|
||||
|
||||
%% low-level exports
|
||||
-export([start/0,
|
||||
open/4,
|
||||
exec/4,
|
||||
prepare/4,
|
||||
step/3,
|
||||
finalize/3,
|
||||
bind/4,
|
||||
column_names/3,
|
||||
close/3
|
||||
open/4,
|
||||
exec/4,
|
||||
insert/4,
|
||||
prepare/4,
|
||||
step/3,
|
||||
finalize/3,
|
||||
bind/4,
|
||||
column_names/3,
|
||||
close/3
|
||||
]).
|
||||
|
||||
-on_load(init/0).
|
||||
@@ -37,9 +38,9 @@
|
||||
init() ->
|
||||
NifName = "esqlite3_nif",
|
||||
NifFileName = case code:priv_dir(esqlite) of
|
||||
{error, bad_name} -> filename:join("priv", NifName);
|
||||
Dir -> filename:join(Dir, NifName)
|
||||
end,
|
||||
{error, bad_name} -> filename:join("priv", NifName);
|
||||
Dir -> filename:join(Dir, NifName)
|
||||
end,
|
||||
ok = erlang:load_nif(NifFileName, 0).
|
||||
|
||||
%% @doc Start a low level thread which will can handle sqlite3 calls.
|
||||
@@ -106,6 +107,11 @@ close(_Db, _Ref, _Dest) ->
|
||||
exit(nif_library_not_loaded).
|
||||
|
||||
|
||||
%% @doc Insert record
|
||||
%%
|
||||
%% @spec insert(connection(), Ref::reference(), Dest::pid(), string()) -> ok | {error, message()}
|
||||
insert(_Db, _Ref, _Dest, _Sql) ->
|
||||
exit(nif_library_not_loaded).
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user