diff --git a/c_src/esqlite_nif.c b/c_src/esqlite_nif.c index f306478..0ac8430 100644 --- a/c_src/esqlite_nif.c +++ b/c_src/esqlite_nif.c @@ -10,6 +10,7 @@ #include "queue.h" #include "sqlite3.h" +#define MAX_ATOM_LENGTH 255 /* from atom.h, not exposed in erlang include */ #define MAX_PATHNAME 512 /* unfortunately not in sqlite.h. */ static ErlNifResourceType *esqlite_connection_type = NULL; @@ -232,9 +233,12 @@ bind_cell(ErlNifEnv *env, const ERL_NIF_TERM cell, sqlite3_stmt *stmt, unsigned { int the_int; double the_double; + char the_atom[MAX_ATOM_LENGTH+1]; + ErlNifBinary the_blob; /* erlang atom undefined -> sqlite null + erlang atom (not undefined) -> sqlite text erlang int -> sqlite int erlang double -> sqlite double erlang iolist -> sqlite blob @@ -244,7 +248,6 @@ bind_cell(ErlNifEnv *env, const ERL_NIF_TERM cell, sqlite3_stmt *stmt, unsigned /* TODO: check the error codes! */ /* TODO check for atom undefined */ - if(enif_get_int(env, cell, &the_int)) { sqlite3_bind_int(stmt, i, the_int); return; @@ -255,7 +258,22 @@ bind_cell(ErlNifEnv *env, const ERL_NIF_TERM cell, sqlite3_stmt *stmt, unsigned return; } - /* + if(enif_get_atom(env, cell, the_atom, sizeof(the_atom), ERL_NIF_LATIN1)) { + if(strcmp("undefined", the_atom) == 0) { + sqlite3_bind_null(stmt, i); + return; + } + + sqlite3_bind_text(stmt, i, the_atom, strlen(the_atom), SQLITE_TRANSIENT); + return; + } + + if(enif_inspect_iolist_as_binary(env, cell, &the_blob)) { + sqlite3_bind_blob(stmt, i, the_blob.data, the_blob.size, SQLITE_TRANSIENT); + return; + } + + /* */ sqlite3_bind_int(stmt, i, i); } @@ -273,11 +291,13 @@ do_bind(ErlNifEnv *env, sqlite3_stmt *stmt, const ERL_NIF_TERM arg) return make_error_tuple(env, "bad_arg_list"); if(parameter_count != list_length) return make_error_tuple(env, "args_wrong_length"); + + sqlite3_reset(stmt); list = arg; - for(i = 0; i < list_length; i++) { + for(i=0; i < list_length; i++) { enif_get_list_cell(env, list, &head, &tail); - bind_cell(env, head, stmt, i); + bind_cell(env, head, stmt, i+1); list = tail; } diff --git a/test/esqlite_test.erl b/test/esqlite_test.erl index 58b07f9..973b611 100644 --- a/test/esqlite_test.erl +++ b/test/esqlite_test.erl @@ -59,16 +59,28 @@ bind_test() -> ok = esqlite:exec(Db, "commit;"), %% Create a prepared statement - {ok, Statement} = esqlite:prepare(Db, "insert into test_table values(?, ?)"), - esqlite:bind(Statement, ["one", 2]), + {ok, Statement} = esqlite:prepare(Db, "insert into test_table values(?1, ?2)"), + esqlite:bind(Statement, [one, 2]), esqlite:step(Statement), - esqlite:bind(Statement, ["three", 4]), + 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), + [{"one", 2}] = q(Db, "select * from test_table where two = 2"), + [{"three", 4}] = q(Db, "select * from test_table where two = 4"), ok. + +%% Handy functions... +%% + +q(Db, Sql) when is_list(Sql) -> + {ok, Statement} = esqlite:prepare(Db, Sql), + exec(Statement). +q(Db, Sql, Args) when is_list(Sql) -> + {ok, Statement} = esqlite:prepare(Db, Sql), + esqlite:bind(Statement, Args), + exec(Statement). + exec(Statement) -> exec(Statement, [], 0).