Fix foreach and map typespecs. Turned on dialyzer underspecs

This commit is contained in:
Maas-Maarten Zeeman
2022-01-04 16:21:02 +01:00
parent 7c936b1112
commit 612b2e2518
2 changed files with 65 additions and 49 deletions

View File

@@ -55,8 +55,8 @@ CFlags =
{warnings, [ {warnings, [
unmatched_returns, unmatched_returns,
error_handling, error_handling,
race_conditions race_conditions,
% underspecs underspecs
]} ]}
]} ]}
]. ].

View File

@@ -166,17 +166,17 @@ q(Sql, Args, Connection, Timeout) ->
end. end.
%% @doc Execute statement and return a list with the result of F for each row. %% @doc Execute statement and return a list with the result of F for each row.
-spec map(F, sql(), connection()) -> list(Type) when -spec map(Fun, sql(), connection()) -> list(Type) when
F :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), Fun :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type),
Row :: tuple(), Row :: row(),
ColumnNames :: tuple(), ColumnNames :: tuple(),
Type :: any(). Type :: any().
map(F, Sql, Connection) -> map(Fun, Sql, Connection) ->
case prepare(Sql, Connection) of case prepare(Sql, Connection) of
{ok, Statement} -> {ok, Statement} ->
map_s(F, Statement); map_s(Fun, Statement);
{error, _Msg}=Error -> {error, _Msg}=Error ->
throw(Error) Error
end. end.
%% @doc Execute statement, bind args and return a list with the result of F for each row. %% @doc Execute statement, bind args and return a list with the result of F for each row.
@@ -185,89 +185,105 @@ map(F, Sql, Connection) ->
Row :: tuple(), Row :: tuple(),
ColumnNames :: tuple(), ColumnNames :: tuple(),
Type :: any(). Type :: any().
map(F, Sql, [], Connection) -> map(Fun, Sql, [], Connection) ->
map(F, Sql, Connection); map(Fun, Sql, Connection);
map(F, Sql, Args, Connection) -> map(Fun, Sql, Args, Connection) ->
case prepare(Sql, Connection) of case prepare(Sql, Connection) of
{ok, Statement} -> {ok, Statement} ->
ok = bind(Statement, Args), case bind(Statement, Args) of
map_s(F, Statement); ok ->
map_s(Fun, Statement);
{error, _}=Error ->
Error
end;
{error, _Msg}=Error -> {error, _Msg}=Error ->
throw(Error) Error
end. end.
%% @doc Execute statement and call F with each row. %% @doc Execute statement and call F with each row.
-spec foreach(F, sql(), connection()) -> ok when -spec foreach(Fun, sql(), connection()) -> ok when
F :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), Fun :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()),
Row :: tuple(), Row :: tuple(),
ColumnNames :: tuple(). ColumnNames :: tuple().
foreach(F, Sql, Connection) -> foreach(Fun, Sql, Connection) ->
case prepare(Sql, Connection) of case prepare(Sql, Connection) of
{ok, Statement} -> {ok, Statement} ->
foreach_s(F, Statement); foreach_s(Fun, Statement);
{error, _Msg}=Error -> {error, _Msg}=Error ->
throw(Error) Error
end. end.
%% @doc Execute statement, bind args and call F with each row. %% @doc Execute statement, bind args and call F with each row.
-spec foreach(F, sql(), list(), connection()) -> ok when -spec foreach(Fun, sql(), list(), connection()) -> ok when
F :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), Fun :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()),
Row :: tuple(), Row :: row(),
ColumnNames :: tuple(). ColumnNames :: tuple().
foreach(F, Sql, [], Connection) -> foreach(F, Sql, [], Connection) ->
foreach(F, Sql, Connection); foreach(F, Sql, Connection);
foreach(F, Sql, Args, Connection) -> foreach(F, Sql, Args, Connection) ->
case prepare(Sql, Connection) of case prepare(Sql, Connection) of
{ok, Statement} -> {ok, Statement} ->
ok = bind(Statement, Args), case bind(Statement, Args) of
ok ->
foreach_s(F, Statement); foreach_s(F, Statement);
{error, _Msg}=Error -> {error, _Msg}=Error ->
throw(Error) Error
end;
{error, _Msg}=Error ->
Error
end. end.
%% %%
-spec foreach_s(F, statement()) -> ok when -spec foreach_s(Fun, statement()) -> ok when
F :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), Fun :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()),
Row :: tuple(), Row :: row(),
ColumnNames :: tuple(). ColumnNames :: tuple().
foreach_s(F, Statement) when is_function(F, 1) -> foreach_s(Fun, Statement) when is_function(Fun, 1) ->
case try_multi_step(Statement, 1, [], 0) of case try_multi_step(Statement, 1, [], 0) of
{'$done', []} -> ok; {'$done', []} ->
{error, _} = E -> F(E); ok;
{error, _} = Error ->
Error;
{rows, [Row | []]} -> {rows, [Row | []]} ->
F(Row), Fun(Row),
foreach_s(F, Statement) foreach_s(Fun, Statement)
end; end;
foreach_s(F, Statement) when is_function(F, 2) -> foreach_s(Fun, Statement) when is_function(Fun, 2) ->
ColumnNames = column_names(Statement), ColumnNames = column_names(Statement),
case try_multi_step(Statement, 1, [], 0) of case try_multi_step(Statement, 1, [], 0) of
{'$done', []} -> ok; {'$done', []} ->
{error, _} = E -> F([], E); ok;
{error, _} = Error ->
Error;
{rows, [Row | []]} -> {rows, [Row | []]} ->
F(ColumnNames, Row), Fun(ColumnNames, Row),
foreach_s(F, Statement) foreach_s(Fun, Statement)
end. end.
%% %%
-spec map_s(F, statement()) -> list(Type) when -spec map_s(Fun, statement()) -> list(Type) when
F :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), Fun :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type),
Row :: tuple(), Row :: row(),
ColumnNames :: tuple(), ColumnNames :: tuple(),
Type :: term(). Type :: term().
map_s(F, Statement) when is_function(F, 1) -> map_s(Fun, Statement) when is_function(Fun, 1) ->
case try_multi_step(Statement, 1, [], 0) of case try_multi_step(Statement, 1, [], 0) of
{'$done', []} -> []; {'$done', []} ->
{error, _} = E -> F(E); [];
{error, _} = Error ->
Error;
{rows, [Row | []]} -> {rows, [Row | []]} ->
[F(Row) | map_s(F, Statement)] [Fun(Row) | map_s(Fun, Statement)]
end; end;
map_s(F, Statement) when is_function(F, 2) -> map_s(Fun, Statement) when is_function(Fun, 2) ->
ColumnNames = column_names(Statement), ColumnNames = column_names(Statement),
case try_multi_step(Statement, 1, [], 0) of case try_multi_step(Statement, 1, [], 0) of
{'$done', []} -> []; {'$done', []} ->
{error, _} = E -> F([], E); [];
{error, _} = Error ->
Error;
{rows, [Row | []]} -> {rows, [Row | []]} ->
[F(ColumnNames, Row) | map_s(F, Statement)] [Fun(ColumnNames, Row) | map_s(Fun, Statement)]
end. end.
%% %%