Added specs
This commit is contained in:
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user