Adding bind
This commit is contained in:
@@ -228,6 +228,33 @@ do_prepare(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
|
|||||||
return make_ok_tuple(env, esqlite_stmt);
|
return make_ok_tuple(env, esqlite_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ERL_NIF_TERM
|
||||||
|
do_bind(ErlNifEnv *env, sqlite3_stmt *stmt, const ERL_NIF_TERM arg)
|
||||||
|
{
|
||||||
|
int parameter_count = sqlite3_bind_parameter_count(stmt);
|
||||||
|
int i, is_list;
|
||||||
|
ERL_NIF_TERM list, head, tail;
|
||||||
|
unsigned int list_length;
|
||||||
|
|
||||||
|
is_list = enif_get_list_length(env, arg, &list_length);
|
||||||
|
if(!is_list)
|
||||||
|
return make_error_tuple(env, "bad_arg_list");
|
||||||
|
if(parameter_count != list_length)
|
||||||
|
return make_error_tuple(env, "args_wrong_length");
|
||||||
|
|
||||||
|
|
||||||
|
list = arg;
|
||||||
|
for(i = 0; i < list_length; i++) {
|
||||||
|
enif_get_list_cell(env, list, &head, &tail);
|
||||||
|
|
||||||
|
/* TODO: do a bind, based on the type of erlang parameter received */
|
||||||
|
sqlite3_bind_int(stmt, i, i);
|
||||||
|
list = tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _atom_ok;
|
||||||
|
}
|
||||||
|
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
make_binary(ErlNifEnv *env, const void *bytes, unsigned int size)
|
make_binary(ErlNifEnv *env, const void *bytes, unsigned int size)
|
||||||
{
|
{
|
||||||
@@ -290,7 +317,7 @@ make_row(ErlNifEnv *env, sqlite3_stmt *statement)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
do_step(ErlNifEnv *env, esqlite_connection *conn, sqlite3_stmt *stmt)
|
do_step(ErlNifEnv *env, sqlite3_stmt *stmt)
|
||||||
{
|
{
|
||||||
int rc = sqlite3_step(stmt);
|
int rc = sqlite3_step(stmt);
|
||||||
|
|
||||||
@@ -331,7 +358,9 @@ evaluate_command(esqlite_command *cmd, esqlite_connection *conn)
|
|||||||
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:
|
||||||
return do_step(cmd->env, conn, cmd->stmt);
|
return do_step(cmd->env, cmd->stmt);
|
||||||
|
case cmd_bind:
|
||||||
|
return do_bind(cmd->env, cmd->stmt, cmd->arg);
|
||||||
case cmd_close:
|
case cmd_close:
|
||||||
return do_close(cmd->env, conn, cmd->arg);
|
return do_close(cmd->env, conn, cmd->arg);
|
||||||
default:
|
default:
|
||||||
@@ -373,7 +402,7 @@ esqlite_connection_run(void *arg)
|
|||||||
* Start the processing thread
|
* Start the processing thread
|
||||||
*/
|
*/
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
start_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
|
esqlite_start(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
|
||||||
{
|
{
|
||||||
esqlite_connection *conn;
|
esqlite_connection *conn;
|
||||||
ERL_NIF_TERM db_conn;
|
ERL_NIF_TERM db_conn;
|
||||||
@@ -409,7 +438,7 @@ start_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
* Open the database
|
* Open the database
|
||||||
*/
|
*/
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
esqlite_open_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
esqlite_open(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
{
|
{
|
||||||
esqlite_connection *db;
|
esqlite_connection *db;
|
||||||
esqlite_command *cmd = NULL;
|
esqlite_command *cmd = NULL;
|
||||||
@@ -448,7 +477,7 @@ esqlite_open_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
* Execute the sql statement
|
* Execute the sql statement
|
||||||
*/
|
*/
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
esqlite_exec_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
esqlite_exec(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
{
|
{
|
||||||
esqlite_connection *db;
|
esqlite_connection *db;
|
||||||
esqlite_command *cmd = NULL;
|
esqlite_command *cmd = NULL;
|
||||||
@@ -482,11 +511,13 @@ esqlite_exec_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
return _atom_ok;
|
return _atom_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare the sql statement
|
* Prepare the sql statement
|
||||||
*/
|
*/
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
esqlite_prepare_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
esqlite_prepare(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
{
|
{
|
||||||
esqlite_connection *conn;
|
esqlite_connection *conn;
|
||||||
esqlite_command *cmd = NULL;
|
esqlite_command *cmd = NULL;
|
||||||
@@ -520,7 +551,7 @@ esqlite_prepare_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
* Bind a variable to a prepared statement
|
* Bind a variable to a prepared statement
|
||||||
*/
|
*/
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
esqlite_bind_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
esqlite_bind(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
{
|
{
|
||||||
esqlite_statement *stmt;
|
esqlite_statement *stmt;
|
||||||
esqlite_command *cmd = NULL;
|
esqlite_command *cmd = NULL;
|
||||||
@@ -542,6 +573,7 @@ esqlite_bind_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
cmd->type = cmd_bind;
|
cmd->type = cmd_bind;
|
||||||
cmd->ref = enif_make_copy(cmd->env, argv[1]);
|
cmd->ref = enif_make_copy(cmd->env, argv[1]);
|
||||||
cmd->pid = pid;
|
cmd->pid = pid;
|
||||||
|
cmd->stmt = stmt->statement;
|
||||||
cmd->arg = enif_make_copy(cmd->env, argv[3]);
|
cmd->arg = enif_make_copy(cmd->env, argv[3]);
|
||||||
|
|
||||||
if(!stmt->connection)
|
if(!stmt->connection)
|
||||||
@@ -559,7 +591,7 @@ esqlite_bind_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
* Step to a prepared statement
|
* Step to a prepared statement
|
||||||
*/
|
*/
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
esqlite_step_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
esqlite_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
{
|
{
|
||||||
esqlite_statement *stmt;
|
esqlite_statement *stmt;
|
||||||
esqlite_command *cmd = NULL;
|
esqlite_command *cmd = NULL;
|
||||||
@@ -601,7 +633,7 @@ esqlite_step_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
|||||||
* Close the database
|
* Close the database
|
||||||
*/
|
*/
|
||||||
static ERL_NIF_TERM
|
static ERL_NIF_TERM
|
||||||
esqlite_close_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
esqlite_close(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
|
||||||
{
|
{
|
||||||
esqlite_connection *conn;
|
esqlite_connection *conn;
|
||||||
esqlite_command *cmd = NULL;
|
esqlite_command *cmd = NULL;
|
||||||
@@ -658,14 +690,14 @@ on_load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ErlNifFunc nif_funcs[] = {
|
static ErlNifFunc nif_funcs[] = {
|
||||||
{"esqlite_start", 0, start_nif},
|
{"esqlite_start", 0, esqlite_start},
|
||||||
{"esqlite_open", 4, esqlite_open_nif},
|
{"esqlite_open", 4, esqlite_open},
|
||||||
{"esqlite_exec", 4, esqlite_exec_nif},
|
{"esqlite_exec", 4, esqlite_exec},
|
||||||
{"esqlite_prepare", 4, esqlite_prepare_nif},
|
{"esqlite_prepare", 4, esqlite_prepare},
|
||||||
{"esqlite_step", 3, esqlite_step_nif},
|
{"esqlite_step", 3, esqlite_step},
|
||||||
// {"esqlite_bind", 3, esqlite_bind_named},
|
// {"esqlite_bind", 3, esqlite_bind_named},
|
||||||
// {"esqlite_bind", 2, esqlite_bind},
|
{"esqlite_bind", 4, esqlite_bind},
|
||||||
{"esqlite_close", 3, esqlite_close_nif}
|
{"esqlite_close", 3, esqlite_close}
|
||||||
};
|
};
|
||||||
|
|
||||||
ERL_NIF_INIT(esqlite, nif_funcs, on_load, NULL, NULL, NULL);
|
ERL_NIF_INIT(esqlite, nif_funcs, on_load, NULL, NULL, NULL);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
-module(esqlite).
|
-module(esqlite).
|
||||||
-author("Maas-Maarten Zeeman <mmzeeman@xs4all.nl>").
|
-author("Maas-Maarten Zeeman <mmzeeman@xs4all.nl>").
|
||||||
|
|
||||||
-export([open/1, open/2, exec/2, prepare/2, prepare/3, step/1, step/2, exec/3, close/1, close/2]).
|
-export([open/1, open/2, exec/2, prepare/2, prepare/3, step/1, step/2, bind/2, bind/3, exec/3, close/1, close/2]).
|
||||||
|
|
||||||
-on_load(init/0).
|
-on_load(init/0).
|
||||||
|
|
||||||
@@ -65,6 +65,16 @@ step(Stmt, Timeout) ->
|
|||||||
ok = esqlite_step(Stmt, Ref, self()),
|
ok = esqlite_step(Stmt, Ref, self()),
|
||||||
receive_answer(Ref, Timeout).
|
receive_answer(Ref, Timeout).
|
||||||
|
|
||||||
|
%% @doc Bind
|
||||||
|
%%
|
||||||
|
bind(Stmt, Args) ->
|
||||||
|
bind(Stmt, Args, ?DEFAULT_TIMEOUT).
|
||||||
|
|
||||||
|
bind(Stmt, Args, Timeout) ->
|
||||||
|
Ref = make_ref(),
|
||||||
|
ok = esqlite_bind(Stmt, Ref, self(), Args),
|
||||||
|
receive_answer(Ref, Timeout).
|
||||||
|
|
||||||
%% @doc Close the database
|
%% @doc Close the database
|
||||||
%%
|
%%
|
||||||
close(Db) ->
|
close(Db) ->
|
||||||
@@ -91,6 +101,9 @@ esqlite_prepare(_Db, _Ref, _Dest, _Sql) ->
|
|||||||
esqlite_step(_Stmt, _Ref, _Dest) ->
|
esqlite_step(_Stmt, _Ref, _Dest) ->
|
||||||
exit(nif_library_not_loaded).
|
exit(nif_library_not_loaded).
|
||||||
|
|
||||||
|
esqlite_bind(_Stmt, _Ref, _Dest, _Args) ->
|
||||||
|
exit(nif_library_not_loaded).
|
||||||
|
|
||||||
esqlite_close(_Db, _Ref, _Dest) ->
|
esqlite_close(_Db, _Ref, _Dest) ->
|
||||||
exit(nif_library_not_loaded).
|
exit(nif_library_not_loaded).
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,27 @@ prepare_test() ->
|
|||||||
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
bind_test() ->
|
||||||
|
{ok, Db} = esqlite:open(":memory:"),
|
||||||
|
ok = esqlite:exec(Db, "begin;"),
|
||||||
|
ok = esqlite:exec(Db, "create table test_table(one varchar(10), two int);"),
|
||||||
|
ok = esqlite:exec(Db, ["insert into test_table values(", "\"hello1\"", ",", "10" ");"]),
|
||||||
|
ok = esqlite:exec(Db, ["insert into test_table values(", "\"hello2\"", ",", "11" ");"]),
|
||||||
|
ok = esqlite:exec(Db, ["insert into test_table values(", "\"hello3\"", ",", "12" ");"]),
|
||||||
|
ok = esqlite:exec(Db, ["insert into test_table values(", "\"hello4\"", ",", "13" ");"]),
|
||||||
|
ok = esqlite:exec(Db, "commit;"),
|
||||||
|
|
||||||
|
%% Create a prepared statement
|
||||||
|
{ok, Statement} = esqlite:prepare(Db, "insert into test_table values(?, ?)"),
|
||||||
|
esqlite:bind(Statement, ["one", 2]),
|
||||||
|
esqlite:step(Statement),
|
||||||
|
esqlite:bind(Statement, ["three", 4]),
|
||||||
|
esqlite:step(Statement),
|
||||||
|
|
||||||
|
{ok, S1} = esqlite:prepare(Db, "select * from test_table where one = 'one'"),
|
||||||
|
[{"one", 2}] = esqlite:step(S1),
|
||||||
|
ok.
|
||||||
|
|
||||||
exec(Statement) ->
|
exec(Statement) ->
|
||||||
exec(Statement, [], 0).
|
exec(Statement, [], 0).
|
||||||
|
|
||||||
@@ -78,11 +99,11 @@ exec(Statement, Acc, Tries) ->
|
|||||||
|
|
||||||
% api...
|
% api...
|
||||||
|
|
||||||
q(Sql, Connection) ->
|
%% q(Sql, Connection) ->
|
||||||
ok.
|
%% ok.
|
||||||
|
|
||||||
q(Sql, Args, Connection) ->
|
%% q(Sql, Args, Connection) ->
|
||||||
ok.
|
%% ok.
|
||||||
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@@ -99,8 +120,8 @@ q(Sql, Args, Connection) ->
|
|||||||
%% return
|
%% return
|
||||||
%% {ok, Result} -- result kan dan headers, rows of request-id (voor async)
|
%% {ok, Result} -- result kan dan headers, rows of request-id (voor async)
|
||||||
%% {error, ...
|
%% {error, ...
|
||||||
q(Sql, Args, Options, Connection) ->
|
%% q(Sql, Args, Options, Connection) ->
|
||||||
ok.
|
%% ok.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user