Added specs

This commit is contained in:
Maas-Maarten Zeeman
2012-12-26 23:51:54 +01:00
parent 3697633c6b
commit 827a8c1756
3 changed files with 56 additions and 31 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2011 Maas-Maarten Zeeman * Copyright 2011, 2012 Maas-Maarten Zeeman
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -21,8 +21,6 @@
#include <erl_nif.h> #include <erl_nif.h>
#include <string.h> #include <string.h>
#include <stdio.h> /* for debugging */
#include "queue.h" #include "queue.h"
#include "sqlite3.h" #include "sqlite3.h"

View File

@@ -1,9 +1,9 @@
%% @author Maas-Maarten Zeeman <mmzeeman@xs4all.nl> %% @author Maas-Maarten Zeeman <mmzeeman@xs4all.nl>
%% @copyright 2011 Maas-Maarten Zeeman %% @copyright 2011, 2012 Maas-Maarten Zeeman
%% @doc Erlang API for sqlite3 databases %% @doc Erlang API for sqlite3 databases
%% Copyright 2011 Maas-Maarten Zeeman %% Copyright 2011, 2012 Maas-Maarten Zeeman
%% %%
%% Licensed under the Apache License, Version 2.0 (the "License"); %% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License. %% you may not use this file except in compliance with the License.
@@ -33,17 +33,24 @@
-export([q/2, q/3, map/3, foreach/3]). -export([q/2, q/3, map/3, foreach/3]).
-define(DEFAULT_TIMEOUT, infinity). -define(DEFAULT_TIMEOUT, 5000).
%%
-type connection() :: tuple().
-type statement() :: term().
-type sql() :: iolist().
%% @doc Opens a sqlite3 database mentioned in Filename. %% @doc Opens a sqlite3 database mentioned in Filename.
%% %%
%% @spec open(string()) -> {ok, connection()} | {error, error_message()} -spec open(FileName) -> {ok, connection()} | {error, _} when
FileName :: string().
open(Filename) -> open(Filename) ->
open(Filename, ?DEFAULT_TIMEOUT). open(Filename, ?DEFAULT_TIMEOUT).
%% @doc Open a database connection %% @doc Open a database connection
%% %%
%% @spec open(string(), timeout()) -> {ok, connection()} | {error, error_message()} -spec open(Filename, timeout()) -> {ok, connection()} | {error, _} when
Filename :: string().
open(Filename, Timeout) -> open(Filename, Timeout) ->
{ok, Connection} = esqlite3_nif:start(), {ok, Connection} = esqlite3_nif:start(),
@@ -51,51 +58,66 @@ open(Filename, Timeout) ->
ok = esqlite3_nif:open(Connection, Ref, self(), Filename), ok = esqlite3_nif:open(Connection, Ref, self(), Filename),
case receive_answer(Ref, Timeout) of case receive_answer(Ref, Timeout) of
ok -> ok ->
{ok, Connection}; {ok, {connection, make_ref(), Connection}};
{error, _Msg}=Error -> {error, _Msg}=Error ->
Error Error
end. end.
%% @doc Execute a sql statement, returns a list with tuples. %% @doc Execute a sql statement, returns a list with tuples.
-spec q(sql(), connection()) -> list(tuple()).
q(Sql, Connection) -> q(Sql, Connection) ->
q(Sql, [], Connection). q(Sql, [], Connection).
%% @doc Execute statement, bind args and return a list with tuples as result. %% @doc Execute statement, bind args and return a list with tuples as result.
-spec q(sql(), list(), connection()) -> list(tuple()).
q(Sql, [], Connection) -> q(Sql, [], Connection) ->
case prepare(Sql, Connection) of case prepare(Sql, Connection) of
{ok, Statement} -> {ok, Statement} ->
fetchall(Statement); fetchall(Statement);
{error, _Msg}=E -> {error, _Msg}=Error ->
throw(E) throw(Error)
end; end;
q(Sql, Args, Connection) -> q(Sql, Args, Connection) ->
case prepare(Sql, Connection) of case prepare(Sql, Connection) of
{ok, Statement} -> {ok, Statement} ->
ok = bind(Statement, Args), ok = bind(Statement, Args),
fetchall(Statement); fetchall(Statement);
{error, _Msg}=E -> {error, _Msg}=Error ->
throw(E) throw(Error)
end. end.
%% %% @doc
-spec map(F, sql(), 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) ->
case prepare(Sql, Connection) of case prepare(Sql, Connection) of
{ok, Statement} -> {ok, Statement} ->
map_s(F, Statement); map_s(F, Statement);
{error, _Msg}=E -> {error, _Msg}=Error ->
throw(E) throw(Error)
end. end.
%% %% @doc
-spec foreach(F, sql(), connection()) -> ok when
F :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()),
Row :: tuple(),
ColumnNames :: tuple().
foreach(F, Sql, Connection) -> foreach(F, Sql, Connection) ->
case prepare(Sql, Connection) of case prepare(Sql, Connection) of
{ok, Statement} -> {ok, Statement} ->
foreach_s(F, Statement); foreach_s(F, Statement);
{error, _Msg}=E -> {error, _Msg}=Error ->
throw(E) throw(Error)
end. end.
%% %%
-spec foreach_s(F, statement()) -> ok when
F :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()),
Row :: tuple(),
ColumnNames :: tuple().
foreach_s(F, Statement) when is_function(F, 1) -> foreach_s(F, Statement) when is_function(F, 1) ->
case try_step(Statement, 0) of case try_step(Statement, 0) of
'$done' -> ok; '$done' -> ok;
@@ -113,6 +135,11 @@ foreach_s(F, Statement) when is_function(F, 2) ->
end. end.
%% %%
-spec map_s(F, statement()) -> list(Type) when
F :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type),
Row :: tuple(),
ColumnNames :: tuple(),
Type :: term().
map_s(F, Statement) when is_function(F, 1) -> map_s(F, Statement) when is_function(F, 1) ->
case try_step(Statement, 0) of case try_step(Statement, 0) of
'$done' -> []; '$done' -> [];
@@ -128,6 +155,7 @@ map_s(F, Statement) when is_function(F, 2) ->
end. end.
%% %%
-spec fetchone(statement()) -> tuple().
fetchone(Statement) -> fetchone(Statement) ->
case try_step(Statement, 0) of case try_step(Statement, 0) of
'$done' -> ok; '$done' -> ok;
@@ -135,6 +163,7 @@ fetchone(Statement) ->
end. end.
%% %%
-spec fetchall(statement()) -> list(tuple()).
fetchall(Statement) -> fetchall(Statement) ->
case try_step(Statement, 0) of case try_step(Statement, 0) of
'$done' -> '$done' ->
@@ -144,6 +173,7 @@ fetchall(Statement) ->
end. end.
%% Try the step, when the database is busy, %% Try the step, when the database is busy,
-spec try_step(statement(), non_neg_integer()) -> term().
try_step(_Statement, Tries) when Tries > 5 -> try_step(_Statement, Tries) when Tries > 5 ->
throw(too_many_tries); throw(too_many_tries);
try_step(Statement, Tries) -> try_step(Statement, Tries) ->
@@ -164,7 +194,7 @@ exec(Sql, Connection) ->
%% @doc Execute %% @doc Execute
%% %%
%% @spec exec(iolist(), connection(), timeout()) -> integer() | {error, error_message()} %% @spec exec(iolist(), connection(), timeout()) -> integer() | {error, error_message()}
exec(Sql, Connection, Timeout) -> exec(Sql, {connection, _Ref, Connection}, Timeout) ->
Ref = make_ref(), Ref = make_ref(),
ok = esqlite3_nif:exec(Connection, Ref, self(), add_eos(Sql)), ok = esqlite3_nif:exec(Connection, Ref, self(), add_eos(Sql)),
receive_answer(Ref, Timeout). receive_answer(Ref, Timeout).
@@ -178,7 +208,7 @@ prepare(Sql, Connection) ->
%% @doc %% @doc
%% %%
%% @spec(iolist(), connection(), timeout()) -> {ok, prepared_statement()} | {error, error_message()} %% @spec(iolist(), connection(), timeout()) -> {ok, prepared_statement()} | {error, error_message()}
prepare(Sql, Connection, Timeout) -> prepare(Sql, {connection, _Ref, Connection}, Timeout) ->
Ref = make_ref(), Ref = make_ref(),
ok = esqlite3_nif:prepare(Connection, Ref, self(), add_eos(Sql)), ok = esqlite3_nif:prepare(Connection, Ref, self(), add_eos(Sql)),
receive_answer(Ref, Timeout). receive_answer(Ref, Timeout).
@@ -224,13 +254,15 @@ column_names(Stmt, Timeout) ->
%% @doc Close the database %% @doc Close the database
%% %%
%% @spec close(connection()) -> ok | {error, error_message()} %% @spec close(connection()) -> ok | {error, error_message()}
-spec close(connection()) -> ok | {error, _}.
close(Connection) -> close(Connection) ->
close(Connection, ?DEFAULT_TIMEOUT). close(Connection, ?DEFAULT_TIMEOUT).
%% @doc Close the database %% @doc Close the database
%% %%
%% @spec close(connection(), integer()) -> ok | {error, error_message()} %% @spec close(connection(), integer()) -> ok | {error, error_message()}
close(Connection, Timeout) -> -spec close(connection(), timeout()) -> ok | {error, _}.
close({connection, _Ref, Connection}, Timeout) ->
Ref = make_ref(), Ref = make_ref(),
ok = esqlite3_nif:close(Connection, Ref, self()), ok = esqlite3_nif:close(Connection, Ref, self()),
receive_answer(Ref, Timeout). receive_answer(Ref, Timeout).
@@ -246,8 +278,3 @@ receive_answer(Ref, Timeout) ->
after Timeout -> after Timeout ->
throw({error, timeout, Ref}) throw({error, timeout, Ref})
end. end.

View File

@@ -1,9 +1,9 @@
%% @author Maas-Maarten Zeeman <mmzeeman@xs4all.nl> %% @author Maas-Maarten Zeeman <mmzeeman@xs4all.nl>
%% @copyright 2011 Maas-Maarten Zeeman %% @copyright 2011, 2012 Maas-Maarten Zeeman
%% @doc Low level erlang API for sqlite3 databases %% @doc Low level erlang API for sqlite3 databases
%% Copyright 2011 Maas-Maarten Zeeman %% Copyright 2011, 2012 Maas-Maarten Zeeman
%% %%
%% Licensed under the Apache License, Version 2.0 (the "License"); %% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License. %% you may not use this file except in compliance with the License.