diff --git a/c_src/esqlite3_nif.c b/c_src/esqlite3_nif.c index 409c251..efa0b48 100644 --- a/c_src/esqlite3_nif.c +++ b/c_src/esqlite3_nif.c @@ -856,7 +856,7 @@ esqlite_bind_blob(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return enif_make_badarg(env); } - if(!enif_inspect_iolist_as_binary(env, argv[1], &blob)) { + if(!enif_inspect_iolist_as_binary(env, argv[2], &blob)) { return enif_make_badarg(env); } @@ -926,8 +926,13 @@ esqlite_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return row; } case SQLITE_DONE: - /* since 3.6.23.1 it is no longer required to do an explict reset. + /* + * Automatically reset the statement after a done so + * column_names will work after the statement is done. + * + * Not resetting the statement can lead to vm crashes. */ + sqlite3_reset(stmt->statement); return make_atom(env, "$done"); case SQLITE_BUSY: return make_atom(env, "$busy"); diff --git a/src/esqlite3.erl b/src/esqlite3.erl index d6f5f0d..e89abd2 100644 --- a/src/esqlite3.erl +++ b/src/esqlite3.erl @@ -43,10 +43,12 @@ bind_int/3, bind_int64/3, bind_double/3, - % bind_text/3, + bind_text/3, bind_blob/3, bind_null/2, + bind/2, + step/1, reset/1, @@ -301,7 +303,9 @@ fetchall1(Statement, Acc) -> E end. -bind(Statement, Args) -> +%% @doc Bind an array of values to a prepared statement +%% +bind(#esqlite3_stmt{}=Statement, Args) when is_list(Args) -> bind1(Statement, 1, Args). bind1(_Statement, _Column, []) -> @@ -310,7 +314,7 @@ bind1(Statement, Column, [Arg | Args]) -> bind_arg(Statement, Column, Arg), bind1(Statement, Column + 1, Args). -% Do automatic conversion +% Bind with automatic tyoe conversion bind_arg(Statement, Column, undefined) -> bind_null(Statement, Column); bind_arg(Statement, Column, null) -> @@ -324,7 +328,19 @@ bind_arg(Statement, Column, Float) when is_float(Float) -> bind_arg(Statement, Column, Bin) when is_binary(Bin) -> bind_text(Statement, Column, Bin); bind_arg(Statement, Column, String) when is_list(String) -> - bind_text(Statement, Column, String). + bind_text(Statement, Column, String); +%% Explicit type binds. +bind_arg(Statement, Column, {int, Value}) -> + bind_int(Statement, Column, Value); +bind_arg(Statement, Column, {int64, Value}) -> + bind_int64(Statement, Column, Value); +bind_arg(Statement, Column, {float, Value}) -> + bind_double(Statement, Column, Value); +bind_arg(Statement, Column, {text, Value}) -> + bind_text(Statement, Column, Value); +bind_arg(Statement, Column, {blob, Value}) -> + bind_blob(Statement, Column, Value). + %% @doc Get the last insert rowid. diff --git a/test/esqlite_test.erl b/test/esqlite_test.erl index c5fe605..bc22e5d 100644 --- a/test/esqlite_test.erl +++ b/test/esqlite_test.erl @@ -208,31 +208,31 @@ bind_test() -> %% Create a prepared statement {ok, Statement} = esqlite3:prepare(Db, "insert into test_table values(?1, ?2)"), - esqlite3:bind(Statement, [one, 2]), + ok = esqlite3:bind(Statement, [one, 2]), + '$done' = esqlite3:step(Statement), + ok = esqlite3:bind(Statement, ["three", 4]), esqlite3:step(Statement), - esqlite3:bind(Statement, ["three", 4]), + ok = esqlite3:bind(Statement, ["five", 6]), esqlite3:step(Statement), - esqlite3:bind(Statement, ["five", 6]), + ok = esqlite3:bind(Statement, [[<<"se">>, $v, "en"], 8]), % iolist bound as text esqlite3:step(Statement), - esqlite3:bind(Statement, [[<<"se">>, $v, "en"], 8]), % iolist bound as text + ok = esqlite3:bind(Statement, [<<"nine">>, 10]), % iolist bound as text esqlite3:step(Statement), - esqlite3:bind(Statement, [<<"nine">>, 10]), % iolist bound as text + ok = esqlite3:bind(Statement, [{blob, [<<"eleven">>, 0]}, 12]), % iolist bound as blob with trailing eos. esqlite3:step(Statement), - esqlite3:bind(Statement, [{blob, [<<"eleven">>, 0]}, 12]), % iolist bound as blob with trailing eos. - esqlite3:step(Statement), - esqlite3:bind(Statement, ["empty", undefined]), % 'undefined' is converted to SQL null + ok = esqlite3:bind(Statement, ["empty", undefined]), % 'undefined' is converted to SQL null esqlite3:step(Statement), %% int64 - esqlite3:bind(Statement, [int64, 308553449069486081]), + ok = esqlite3:bind(Statement, [int64, 308553449069486081]), esqlite3:step(Statement), % %% negative int64 - esqlite3:bind(Statement, [negative_int64, -308553449069486081]), + ok = esqlite3:bind(Statement, [negative_int64, -308553449069486081]), esqlite3:step(Statement), %% utf-8 - esqlite3:bind(Statement, [[<<228,184,138,230,181,183>>], 100]), + ok = esqlite3:bind(Statement, [[<<228,184,138,230,181,183>>], 100]), esqlite3:step(Statement), ?assertEqual([[<<"one">>, 2]],