diff --git a/src/esqlite3.erl b/src/esqlite3.erl index a03cb48..be33f40 100644 --- a/src/esqlite3.erl +++ b/src/esqlite3.erl @@ -40,7 +40,7 @@ column_types/1, column_types/2, close/1, close/2]). --export([q/2, q/3, q/4, map/3, foreach/3]). +-export([q/2, q/3, q/4, map/3, map/4, foreach/3, foreach/4]). -define(DEFAULT_TIMEOUT, 5000). -define(DEFAULT_CHUNK_SIZE, 5000). @@ -123,7 +123,7 @@ q(Sql, Args, Connection, Timeout) -> throw(Error) end. -%% @doc +%% @doc Execute statement and return a list with the result of F for each row. -spec map(F, sql(), connection()) -> list(Type) when F :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), Row :: tuple(), @@ -137,7 +137,24 @@ map(F, Sql, Connection) -> throw(Error) end. -%% @doc +%% @doc Execute statement, bind args and return a list with the result of F for each row. +-spec map(F, sql(), list(), connection()) -> list(Type) when + F :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), + Row :: tuple(), + ColumnNames :: tuple(), + Type :: any(). +map(F, Sql, [], Connection) -> + map(F, Sql, Connection); +map(F, Sql, Args, Connection) -> + case prepare(Sql, Connection) of + {ok, Statement} -> + ok = bind(Statement, Args), + map_s(F, Statement); + {error, _Msg}=Error -> + throw(Error) + end. + +%% @doc Execute statement and call F with each row. -spec foreach(F, sql(), connection()) -> ok when F :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), Row :: tuple(), @@ -150,6 +167,22 @@ foreach(F, Sql, Connection) -> throw(Error) end. +%% @doc Execute statement, bind args and call F with each row. +-spec foreach(F, sql(), list(), connection()) -> ok when + F :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), + Row :: tuple(), + ColumnNames :: tuple(). +foreach(F, Sql, [], Connection) -> + foreach(F, Sql, Connection); +foreach(F, Sql, Args, Connection) -> + case prepare(Sql, Connection) of + {ok, Statement} -> + ok = bind(Statement, Args), + foreach_s(F, Statement); + {error, _Msg}=Error -> + throw(Error) + end. + %% -spec foreach_s(F, statement()) -> ok when F :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), diff --git a/test/esqlite_test.erl b/test/esqlite_test.erl index d7758c0..c2dfe26 100644 --- a/test/esqlite_test.erl +++ b/test/esqlite_test.erl @@ -294,6 +294,31 @@ foreach_test() -> ok. +bind_for_foreach_test() -> + {ok, Db} = esqlite3:open(":memory:"), + ok = esqlite3:exec("begin;", Db), + ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), + ok = esqlite3:exec(["insert into test_table values(", "\"hello1\"", ",", "10" ");"], Db), + ok = esqlite3:exec(["insert into test_table values(", "\"hello2\"", ",", "11" ");"], Db), + ok = esqlite3:exec(["insert into test_table values(", "\"hello3\"", ",", "12" ");"], Db), + ok = esqlite3:exec(["insert into test_table values(", "\"hello4\"", ",", "13" ");"], Db), + ok = esqlite3:exec("commit;", Db), + + F = fun(Row) -> + case Row of + {Key, Value} -> + put(Key, Value); + _ -> + ok + end + end, + + esqlite3:foreach(F, "select * from test_table where one = ?;", ["hello1"], Db), + + 10 = get(<<"hello1">>), + + ok. + map_test() -> {ok, Db} = esqlite3:open(":memory:"), ok = esqlite3:exec("begin;", Db), @@ -321,6 +346,31 @@ map_test() -> ok. +bind_for_map_test() -> + {ok, Db} = esqlite3:open(":memory:"), + ok = esqlite3:exec("begin;", Db), + ok = esqlite3:exec("create table test_table(one varchar(10), two int);", Db), + ok = esqlite3:exec(["insert into test_table values(", "\"hello1\"", ",", "10" ");"], Db), + ok = esqlite3:exec(["insert into test_table values(", "\"hello2\"", ",", "11" ");"], Db), + ok = esqlite3:exec(["insert into test_table values(", "\"hello3\"", ",", "12" ");"], Db), + ok = esqlite3:exec(["insert into test_table values(", "\"hello4\"", ",", "13" ");"], Db), + ok = esqlite3:exec("commit;", Db), + + F = fun(Row) -> Row end, + + [{<<"hello1">>,10}] + = esqlite3:map(F, "select * from test_table where one = ?", ["hello1"], Db), + + %% Test that when the row-names are added.. + Assoc = fun(Names, Row) -> + lists:zip(tuple_to_list(Names), tuple_to_list(Row)) + end, + + [[{one,<<"hello1">>},{two,10}]] = esqlite3:map(Assoc, "select * from test_table where one = ?", ["hello1"], Db), + + ok. + + error1_msg_test() -> {ok, Db} = esqlite3:open(":memory:"),