diff --git a/README.md b/README.md index 13a6e65..53a37cb 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,12 @@ -# Erlang wrapper for SQLite3 -This library allows you to work with SQLite3 databases from Erlang. -It is compatible with Windows and Linux, and should probably work on other OSes as well. +#The sqlite3 application# -## Compiling -### Linux +##Modules## -1. Install SQLite3 by running `sudo apt-get install sqlite3` or the equivalent for your package manager, or by [compiling from the source](http://source.online.free.fr/Linux_HowToCompileSQLite.html). -2. `make`. + + +
sqlite3
sqlite3_lib
-### Cross-compiling - -If you want to use erlang-sqlite3 on an embedded device, it can be cross-compiled. - -1. Cross-compile [SQLite3](http://www.sqlite.org/cvstrac/wiki?p=HowToCompile) and [Erlang](http://www.erlang.org/doc/installation_guide/INSTALL-CROSS.html). - -2. Change variables and paths in `rebar.cross_compile.config.sample` to the desired values and rename it to `rebar.cross_compile.config`. - -3. `make cross_compile`. - -### Windows with MS Visual C++ - -1. Download both the source amalgamation and the precompiled binary from http://www.sqlite.org/download.html. Extract files `sqlite3.h` from the amalgamation and `sqlite3.def` from the binary. Run this command from Visual Studio command prompt: - - lib /def:sqlite3.def - - to create the import library `sqlite3.lib`. In `rebar.config`, set the correct paths in tuples `{"win32", "CFLAGS", "/Idirectory/containing/sqlite3.h/ /Ic_src /W4 /wd4100 /wd4204"}` and `{"win32", "LDFLAGS", "/path/to/sqlite3.lib"}`. - -2. `nmake`. - -## DLL search path - -Note that on Windows, `sqlite3.dll` usually won't be installed in the system-wide DLL search path. In this case, it should be placed in the working directory of your application. - -## Running the test suite - -### Linux - -`make test` - -### Windows - -1. `nmake tests` - -2. If you get the error `"Error loading sqlite3_drv: The specified module could not be found"`, this is because `sqlite3.dll` isn't in the search path. Copy it to the `.eunit` directory. - -## Example usage - -See tests `src/sqlite3_test.erl` for a starting point. - -## Authors - -See ./AUTHORS diff --git a/include/sqlite3.hrl b/include/sqlite3.hrl index 1c56f53..3516ddf 100644 --- a/include/sqlite3.hrl +++ b/include/sqlite3.hrl @@ -20,6 +20,7 @@ -endif. -define(NULL_ATOM, null). +-type table() :: atom() | binary() | string(). -type sql_value() :: number() | ?NULL_ATOM | iodata() | {blob, binary()}. -type sql_type() :: integer | text | double | real | blob | string(). diff --git a/src/sqlite3.erl b/src/sqlite3.erl index 7804eaa..038aa1d 100644 --- a/src/sqlite3.erl +++ b/src/sqlite3.erl @@ -4,6 +4,8 @@ %%% @copyright 21 Jun 2008 by Tee Teoh %%% @version 1.0.0 %%% @doc Library module for sqlite3 +%%% +%%% @type table() = atom() | binary() | string() %%% @end %%%------------------------------------------------------------------- -module(sqlite3). @@ -301,7 +303,7 @@ columns_timeout(Db, Ref, Timeout) -> gen_server:call(Db, {columns, Ref}, Timeout). %%-------------------------------------------------------------------- -%% @spec create_table(Tbl :: atom(), TblInfo :: table_info()) -> sql_non_query_result() +%% @spec create_table(Tbl :: table(), TblInfo :: table_info()) -> sql_non_query_result() %% @doc %% Creates the Tbl table using TblInfo as the table structure. The %% table structure is a list of {column name, column type} pairs. @@ -310,12 +312,12 @@ columns_timeout(Db, Ref, Timeout) -> %% Returns the result of the create table call. %% @end %%-------------------------------------------------------------------- --spec create_table(atom(), table_info()) -> sql_non_query_result(). +-spec create_table(table(), table_info()) -> sql_non_query_result(). create_table(Tbl, Columns) -> create_table(?MODULE, Tbl, Columns). %%-------------------------------------------------------------------- -%% @spec create_table(Db :: atom(), Tbl :: atom(), Columns) -> sql_non_query_result() +%% @spec create_table(Db :: atom(), Tbl :: table(), Columns) -> sql_non_query_result() %% Columns = table_info() %% @doc %% Creates the Tbl table in Db using Columns as the table structure. @@ -325,12 +327,12 @@ create_table(Tbl, Columns) -> %% Returns the result of the create table call. %% @end %%-------------------------------------------------------------------- --spec create_table(atom(), atom(), table_info()) -> sql_non_query_result(). +-spec create_table(atom(), table(), table_info()) -> sql_non_query_result(). create_table(Db, Tbl, Columns) -> gen_server:call(Db, {create_table, Tbl, Columns}). %%-------------------------------------------------------------------- -%% @spec create_table_timeout(Db :: atom(), Tbl :: atom(), Columns, Timeout :: timeout()) -> sql_non_query_result() +%% @spec create_table_timeout(Db :: atom(), Tbl :: table(), Columns, Timeout :: timeout()) -> sql_non_query_result() %% Columns = table_info() %% @doc %% Creates the Tbl table in Db using Columns as the table structure. @@ -340,12 +342,12 @@ create_table(Db, Tbl, Columns) -> %% Returns the result of the create table call. %% @end %%-------------------------------------------------------------------- --spec create_table_timeout(atom(), atom(), table_info(), timeout()) -> sql_non_query_result(). +-spec create_table_timeout(atom(), table(), table_info(), timeout()) -> sql_non_query_result(). create_table_timeout(Db, Tbl, Columns, Timeout) -> gen_server:call(Db, {create_table, Tbl, Columns}, Timeout). %%-------------------------------------------------------------------- -%% @spec create_table(Db :: atom(), Tbl :: atom(), TblInfo, Constraints) -> sql_non_query_result() +%% @spec create_table(Db :: atom(), Tbl :: table(), TblInfo, Constraints) -> sql_non_query_result() %% Columns = table_info() %% Constraints = [term()] %% @doc @@ -357,13 +359,13 @@ create_table_timeout(Db, Tbl, Columns, Timeout) -> %% Returns the result of the create table call. %% @end %%-------------------------------------------------------------------- --spec create_table(atom(), atom(), table_info(), table_constraints()) -> +-spec create_table(atom(), table(), table_info(), table_constraints()) -> sql_non_query_result(). create_table(Db, Tbl, Columns, Constraints) -> gen_server:call(Db, {create_table, Tbl, Columns, Constraints}). %%-------------------------------------------------------------------- -%% @spec create_table_timeout(Db :: atom(), Tbl :: atom(), TblInfo, Constraints, Timeout) -> sql_non_query_result() +%% @spec create_table_timeout(Db :: atom(), Tbl :: table(), TblInfo, Constraints, Timeout) -> sql_non_query_result() %% Columns = table_info() %% Constraints = [term()] %% @doc @@ -375,145 +377,145 @@ create_table(Db, Tbl, Columns, Constraints) -> %% Returns the result of the create table call. %% @end %%-------------------------------------------------------------------- --spec create_table_timeout(atom(), atom(), table_info(), table_constraints(), timeout()) -> +-spec create_table_timeout(atom(), table(), table_info(), table_constraints(), timeout()) -> sql_non_query_result(). create_table_timeout(Db, Tbl, Columns, Constraints, Timeout) -> gen_server:call(Db, {create_table, Tbl, Columns, Constraints}, Timeout). %%-------------------------------------------------------------------- -%% @spec list_tables() -> [atom()] +%% @spec list_tables() -> [table()] %% @doc %% Returns a list of tables. %% @end %%-------------------------------------------------------------------- --spec list_tables() -> [atom()]. +-spec list_tables() -> [table()]. list_tables() -> list_tables(?MODULE). %%-------------------------------------------------------------------- -%% @spec list_tables(Db :: atom()) -> [atom()] +%% @spec list_tables(Db :: atom()) -> [table()] %% @doc %% Returns a list of tables for Db. %% @end %%-------------------------------------------------------------------- --spec list_tables(atom()) -> [atom()]. +-spec list_tables(atom()) -> [table()]. list_tables(Db) -> gen_server:call(Db, list_tables). %%-------------------------------------------------------------------- -%% @spec list_tables_timeout(Db :: atom(), Timeout :: timeout()) -> [atom()] +%% @spec list_tables_timeout(Db :: atom(), Timeout :: timeout()) -> [table()] %% @doc %% Returns a list of tables for Db. %% @end %%-------------------------------------------------------------------- --spec list_tables_timeout(atom(), timeout()) -> [atom()]. +-spec list_tables_timeout(atom(), timeout()) -> [table()]. list_tables_timeout(Db, Timeout) -> gen_server:call(Db, list_tables, Timeout). %%-------------------------------------------------------------------- -%% @spec table_info(Tbl :: atom()) -> table_info() +%% @spec table_info(Tbl :: table()) -> table_info() %% @doc %% Returns table schema for Tbl. %% @end %%-------------------------------------------------------------------- --spec table_info(atom()) -> table_info(). +-spec table_info(table()) -> table_info(). table_info(Tbl) -> table_info(?MODULE, Tbl). %%-------------------------------------------------------------------- -%% @spec table_info(Db :: atom(), Tbl :: atom()) -> table_info() +%% @spec table_info(Db :: atom(), Tbl :: table()) -> table_info() %% @doc %% Returns table schema for Tbl in Db. %% @end %%-------------------------------------------------------------------- --spec table_info(atom(), atom()) -> table_info(). +-spec table_info(atom(), table()) -> table_info(). table_info(Db, Tbl) -> gen_server:call(Db, {table_info, Tbl}). %%-------------------------------------------------------------------- -%% @spec table_info_timeout(Db :: atom(), Tbl :: atom(), Timeout :: timeout()) -> table_info() +%% @spec table_info_timeout(Db :: atom(), Tbl :: table(), Timeout :: timeout()) -> table_info() %% @doc %% Returns table schema for Tbl in Db. %% @end %%-------------------------------------------------------------------- --spec table_info_timeout(atom(), atom(), timeout()) -> table_info(). +-spec table_info_timeout(atom(), table(), timeout()) -> table_info(). table_info_timeout(Db, Tbl, Timeout) -> gen_server:call(Db, {table_info, Tbl}, Timeout). %%-------------------------------------------------------------------- -%% @spec write(Tbl :: atom(), Data) -> sql_non_query_result() +%% @spec write(Tbl :: table(), Data) -> sql_non_query_result() %% Data = [{Column :: atom(), Value :: sql_value()}] %% @doc %% Write Data into Tbl table. Value must be of the same type as %% determined from table_info/2. %% @end %%-------------------------------------------------------------------- --spec write(atom(), [{atom(), sql_value()}]) -> sql_non_query_result(). +-spec write(table(), [{atom(), sql_value()}]) -> sql_non_query_result(). write(Tbl, Data) -> write(?MODULE, Tbl, Data). %%-------------------------------------------------------------------- -%% @spec write(Db :: atom(), Tbl :: atom(), Data) -> sql_non_query_result() +%% @spec write(Db :: atom(), Tbl :: table(), Data) -> sql_non_query_result() %% Data = [{Column :: atom(), Value :: sql_value()}] %% @doc %% Write Data into Tbl table in Db database. Value must be of the %% same type as determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec write(atom(), atom(), [{atom(), sql_value()}]) -> sql_non_query_result(). +-spec write(atom(), table(), [{atom(), sql_value()}]) -> sql_non_query_result(). write(Db, Tbl, Data) -> gen_server:call(Db, {write, Tbl, Data}). %%-------------------------------------------------------------------- -%% @spec write_timeout(Db :: atom(), Tbl :: atom(), Data, Timeout :: timeout()) -> sql_non_query_result() +%% @spec write_timeout(Db :: atom(), Tbl :: table(), Data, Timeout :: timeout()) -> sql_non_query_result() %% Data = [{Column :: atom(), Value :: sql_value()}] %% @doc %% Write Data into Tbl table in Db database. Value must be of the %% same type as determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec write_timeout(atom(), atom(), [{atom(), sql_value()}], timeout()) -> sql_non_query_result(). +-spec write_timeout(atom(), table(), [{atom(), sql_value()}], timeout()) -> sql_non_query_result(). write_timeout(Db, Tbl, Data, Timeout) -> gen_server:call(Db, {write, Tbl, Data}, Timeout). %%-------------------------------------------------------------------- -%% @spec write_many(Tbl :: atom(), Data) -> [sql_result()] +%% @spec write_many(Tbl :: table(), Data) -> [sql_result()] %% Data = [[{Column :: atom(), Value :: sql_value()}]] %% @doc %% Write all records in Data into table Tbl. Value must be of the %% same type as determined from table_info/2. %% @end %%-------------------------------------------------------------------- --spec write_many(atom(), [[{atom(), sql_value()}]]) -> [sql_result()]. +-spec write_many(table(), [[{atom(), sql_value()}]]) -> [sql_result()]. write_many(Tbl, Data) -> write_many(?MODULE, Tbl, Data). %%-------------------------------------------------------------------- -%% @spec write_many(Db :: atom(), Tbl :: atom(), Data) -> [sql_result()] +%% @spec write_many(Db :: atom(), Tbl :: table(), Data) -> [sql_result()] %% Data = [[{Column :: atom(), Value :: sql_value()}]] %% @doc %% Write all records in Data into table Tbl in database Db. Value %% must be of the same type as determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec write_many(atom(), atom(), [[{atom(), sql_value()}]]) -> [sql_result()]. +-spec write_many(atom(), table(), [[{atom(), sql_value()}]]) -> [sql_result()]. write_many(Db, Tbl, Data) -> gen_server:call(Db, {write_many, Tbl, Data}). %%-------------------------------------------------------------------- -%% @spec write_many_timeout(Db :: atom(), Tbl :: atom(), Data, Timeout :: timeout()) -> [sql_result()] +%% @spec write_many_timeout(Db :: atom(), Tbl :: table(), Data, Timeout :: timeout()) -> [sql_result()] %% Data = [[{Column :: atom(), Value :: sql_value()}]] %% @doc %% Write all records in Data into table Tbl in database Db. Value %% must be of the same type as determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec write_many_timeout(atom(), atom(), [[{atom(), sql_value()}]], timeout()) -> [sql_result()]. +-spec write_many_timeout(atom(), table(), [[{atom(), sql_value()}]], timeout()) -> [sql_result()]. write_many_timeout(Db, Tbl, Data, Timeout) -> gen_server:call(Db, {write_many, Tbl, Data}, Timeout). %%-------------------------------------------------------------------- -%% @spec update(Tbl :: atom(), {Key :: atom(), Value}, Data) -> sql_non_query_result() +%% @spec update(Tbl :: table(), {Key :: atom(), Value}, Data) -> sql_non_query_result() %% Value = any() %% Data = [{Column :: atom(), Value :: sql_value()}] %% @doc @@ -521,12 +523,12 @@ write_many_timeout(Db, Tbl, Data, Timeout) -> %% value in Key with Data. %% @end %%-------------------------------------------------------------------- --spec update(atom(), {atom(), sql_value()}, [{atom(), sql_value()}]) -> sql_non_query_result(). +-spec update(table(), {atom(), sql_value()}, [{atom(), sql_value()}]) -> sql_non_query_result(). update(Tbl, {Key, Value}, Data) -> update(?MODULE, Tbl, {Key, Value}, Data). %%-------------------------------------------------------------------- -%% @spec update(Db :: atom(), Tbl :: atom(), {Key :: atom(), Value}, Data) -> sql_non_query_result() +%% @spec update(Db :: atom(), Tbl :: table(), {Key :: atom(), Value}, Data) -> sql_non_query_result() %% Value = sql_value() %% Data = [{Column :: atom(), Value :: sql_value()}] %% @doc @@ -534,13 +536,13 @@ update(Tbl, {Key, Value}, Data) -> %% matches the value in Key with Data. %% @end %%-------------------------------------------------------------------- --spec update(atom(), atom(), {atom(), sql_value()}, [{atom(), sql_value()}]) -> +-spec update(atom(), table(), {atom(), sql_value()}, [{atom(), sql_value()}]) -> sql_non_query_result(). update(Db, Tbl, {Key, Value}, Data) -> gen_server:call(Db, {update, Tbl, Key, Value, Data}). %%-------------------------------------------------------------------- -%% @spec update_timeout(Db :: atom(), Tbl :: atom(), {Key :: atom(), Value}, Data, Timeout :: timeout()) -> sql_non_query_result() +%% @spec update_timeout(Db :: atom(), Tbl :: table(), {Key :: atom(), Value}, Data, Timeout :: timeout()) -> sql_non_query_result() %% Value = sql_value() %% Data = [{Column :: atom(), Value :: sql_value()}] %% @doc @@ -548,53 +550,53 @@ update(Db, Tbl, {Key, Value}, Data) -> %% matches the value in Key with Data. %% @end %%-------------------------------------------------------------------- --spec update_timeout(atom(), atom(), {atom(), sql_value()}, [{atom(), sql_value()}], timeout()) -> +-spec update_timeout(atom(), table(), {atom(), sql_value()}, [{atom(), sql_value()}], timeout()) -> sql_non_query_result(). update_timeout(Db, Tbl, {Key, Value}, Data, Timeout) -> gen_server:call(Db, {update, Tbl, Key, Value, Data}, Timeout). %%-------------------------------------------------------------------- -%% @spec read_all(Db :: atom(), Table :: atom()) -> sql_result() +%% @spec read_all(Db :: atom(), Table :: table()) -> sql_result() %% @doc %% Reads all rows from Table in Db. %% @end %%-------------------------------------------------------------------- --spec read_all(atom(), atom()) -> sql_result(). +-spec read_all(atom(), table()) -> sql_result(). read_all(Db, Tbl) -> gen_server:call(Db, {read, Tbl}). %%-------------------------------------------------------------------- -%% @spec read_all_timeout(Db :: atom(), Table :: atom(), Timeout :: timeout()) -> sql_result() +%% @spec read_all_timeout(Db :: atom(), Table :: table(), Timeout :: timeout()) -> sql_result() %% @doc %% Reads all rows from Table in Db. %% @end %%-------------------------------------------------------------------- --spec read_all_timeout(atom(), atom(), timeout()) -> sql_result(). +-spec read_all_timeout(atom(), table(), timeout()) -> sql_result(). read_all_timeout(Db, Tbl, Timeout) -> gen_server:call(Db, {read, Tbl}, Timeout). %%-------------------------------------------------------------------- -%% @spec read_all(Db :: atom(), Table :: atom(), Columns :: [atom()]) -> sql_result() +%% @spec read_all(Db :: atom(), Table :: table(), Columns :: [atom()]) -> sql_result() %% @doc %% Reads Columns in all rows from Table in Db. %% @end %%-------------------------------------------------------------------- --spec read_all(atom(), atom(), [atom()]) -> sql_result(). +-spec read_all(atom(), table(), [atom()]) -> sql_result(). read_all(Db, Tbl, Columns) -> gen_server:call(Db, {read, Tbl, Columns}). %%-------------------------------------------------------------------- -%% @spec read_all_timeout(Db :: atom(), Table :: atom(), Columns :: [atom()], Timeout :: timeout()) -> sql_result() +%% @spec read_all_timeout(Db :: atom(), Table :: table(), Columns :: [atom()], Timeout :: timeout()) -> sql_result() %% @doc %% Reads Columns in all rows from Table in Db. %% @end %%-------------------------------------------------------------------- --spec read_all_timeout(atom(), atom(), [atom()], timeout()) -> sql_result(). +-spec read_all_timeout(atom(), table(), [atom()], timeout()) -> sql_result(). read_all_timeout(Db, Tbl, Columns, Timeout) -> gen_server:call(Db, {read, Tbl, Columns}, Timeout). %%-------------------------------------------------------------------- -%% @spec read(Tbl :: atom(), Key) -> sql_result() +%% @spec read(Tbl :: table(), Key) -> sql_result() %% Key = {Column :: atom(), Value :: sql_value()} %% @doc %% Reads a row from Tbl table such that the Value matches the @@ -602,12 +604,12 @@ read_all_timeout(Db, Tbl, Columns, Timeout) -> %% from table_info/2. %% @end %%-------------------------------------------------------------------- --spec read(atom(), {atom(), sql_value()}) -> sql_result(). +-spec read(table(), {atom(), sql_value()}) -> sql_result(). read(Tbl, Key) -> read(?MODULE, Tbl, Key). %%-------------------------------------------------------------------- -%% @spec read(Db :: atom(), Tbl :: atom(), Key) -> sql_result() +%% @spec read(Db :: atom(), Tbl :: table(), Key) -> sql_result() %% Key = {Column :: atom(), Value :: sql_value()} %% @doc %% Reads a row from Tbl table in Db database such that the Value @@ -615,14 +617,14 @@ read(Tbl, Key) -> %% as determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec read(atom(), atom(), {atom(), sql_value()}) -> sql_result(). +-spec read(atom(), table(), {atom(), sql_value()}) -> sql_result(). read(Db, Tbl, {Column, Value}) -> gen_server:call(Db, {read, Tbl, Column, Value}). %%-------------------------------------------------------------------- %% @spec read(Db, Tbl, Key, Columns) -> [any()] %% Db = atom() -%% Tbl = atom() +%% Tbl = table() %% Key = {Column :: atom(), Value :: sql_value()} %% Columns = [atom()] %% @doc @@ -631,12 +633,12 @@ read(Db, Tbl, {Column, Value}) -> %% determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec read(atom(), atom(), {atom(), sql_value()}, [atom()]) -> sql_result(). +-spec read(atom(), table(), {atom(), sql_value()}, [atom()]) -> sql_result(). read(Db, Tbl, {Key, Value}, Columns) -> gen_server:call(Db, {read, Tbl, Key, Value, Columns}). %%-------------------------------------------------------------------- -%% @spec read_timeout(Db :: atom(), Tbl :: atom(), Key, Timeout :: timeout()) -> sql_result() +%% @spec read_timeout(Db :: atom(), Tbl :: table(), Key, Timeout :: timeout()) -> sql_result() %% Key = {Column :: atom(), Value :: sql_value()} %% @doc %% Reads a row from Tbl table in Db database such that the Value @@ -644,14 +646,14 @@ read(Db, Tbl, {Key, Value}, Columns) -> %% as determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec read_timeout(atom(), atom(), {atom(), sql_value()}, timeout()) -> sql_result(). +-spec read_timeout(atom(), table(), {atom(), sql_value()}, timeout()) -> sql_result(). read_timeout(Db, Tbl, {Column, Value}, Timeout) -> gen_server:call(Db, {read, Tbl, Column, Value}, Timeout). %%-------------------------------------------------------------------- %% @spec read_timeout(Db, Tbl, Key, Columns, Timeout :: timeout()) -> [any()] %% Db = atom() -%% Tbl = atom() +%% Tbl = table() %% Key = {Column :: atom(), Value :: sql_value()} %% Columns = [atom()] %% @doc @@ -660,12 +662,12 @@ read_timeout(Db, Tbl, {Column, Value}, Timeout) -> %% determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec read_timeout(atom(), atom(), {atom(), sql_value()}, [atom()], timeout()) -> sql_result(). +-spec read_timeout(atom(), table(), {atom(), sql_value()}, [atom()], timeout()) -> sql_result(). read_timeout(Db, Tbl, {Key, Value}, Columns, Timeout) -> gen_server:call(Db, {read, Tbl, Key, Value, Columns}, Timeout). %%-------------------------------------------------------------------- -%% @spec delete(Tbl :: atom(), Key) -> any() +%% @spec delete(Tbl :: table(), Key) -> any() %% Key = {Column :: atom(), Value :: sql_value()} %% @doc %% Delete a row from Tbl table in Db database such that the Value @@ -673,12 +675,12 @@ read_timeout(Db, Tbl, {Key, Value}, Columns, Timeout) -> %% Value must have the same type as determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec delete(atom(), {atom(), sql_value()}) -> sql_non_query_result(). +-spec delete(table(), {atom(), sql_value()}) -> sql_non_query_result(). delete(Tbl, Key) -> delete(?MODULE, Tbl, Key). %%-------------------------------------------------------------------- -%% @spec delete_timeout(Db :: atom(), Tbl :: atom(), Key, Timeout :: timeout()) -> sql_non_query_result() +%% @spec delete_timeout(Db :: atom(), Tbl :: table(), Key, Timeout :: timeout()) -> sql_non_query_result() %% Key = {Column :: atom(), Value :: sql_value()} %% @doc %% Delete a row from Tbl table in Db database such that the Value @@ -686,12 +688,12 @@ delete(Tbl, Key) -> %% Value must have the same type as determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec delete_timeout(atom(), atom(), {atom(), any()}, timeout()) -> sql_non_query_result(). +-spec delete_timeout(atom(), table(), {atom(), any()}, timeout()) -> sql_non_query_result(). delete_timeout(Db, Tbl, Key, Timeout) -> gen_server:call(Db, {delete, Tbl, Key}, Timeout). %%-------------------------------------------------------------------- -%% @spec delete(Db :: atom(), Tbl :: atom(), Key) -> sql_non_query_result() +%% @spec delete(Db :: atom(), Tbl :: table(), Key) -> sql_non_query_result() %% Key = {Column :: atom(), Value :: sql_value()} %% @doc %% Delete a row from Tbl table in Db database such that the Value @@ -699,37 +701,37 @@ delete_timeout(Db, Tbl, Key, Timeout) -> %% Value must have the same type as determined from table_info/3. %% @end %%-------------------------------------------------------------------- --spec delete(atom(), atom(), {atom(), any()}) -> sql_non_query_result(). +-spec delete(atom(), table(), {atom(), any()}) -> sql_non_query_result(). delete(Db, Tbl, Key) -> gen_server:call(Db, {delete, Tbl, Key}). %%-------------------------------------------------------------------- -%% @spec drop_table(Tbl :: atom()) -> sql_non_query_result() +%% @spec drop_table(Tbl :: table()) -> sql_non_query_result() %% @doc %% Drop the table Tbl. %% @end %%-------------------------------------------------------------------- --spec drop_table(atom()) -> sql_non_query_result(). +-spec drop_table(table()) -> sql_non_query_result(). drop_table(Tbl) -> drop_table(?MODULE, Tbl). %%-------------------------------------------------------------------- -%% @spec drop_table(Db :: atom(), Tbl :: atom()) -> sql_non_query_result() +%% @spec drop_table(Db :: atom(), Tbl :: table()) -> sql_non_query_result() %% @doc %% Drop the table Tbl from Db database. %% @end %%-------------------------------------------------------------------- --spec drop_table(atom(), atom()) -> sql_non_query_result(). +-spec drop_table(atom(), table()) -> sql_non_query_result(). drop_table(Db, Tbl) -> gen_server:call(Db, {drop_table, Tbl}). %%-------------------------------------------------------------------- -%% @spec drop_table_timeout(Db :: atom(), Tbl :: atom(), Timeout :: timeout()) -> sql_non_query_result() +%% @spec drop_table_timeout(Db :: atom(), Tbl :: table(), Timeout :: timeout()) -> sql_non_query_result() %% @doc %% Drop the table Tbl from Db database. %% @end %%-------------------------------------------------------------------- --spec drop_table_timeout(atom(), atom(), timeout()) -> sql_non_query_result(). +-spec drop_table_timeout(atom(), table(), timeout()) -> sql_non_query_result(). drop_table_timeout(Db, Tbl, Timeout) -> gen_server:call(Db, {drop_table, Tbl}, Timeout). diff --git a/src/sqlite3_lib.erl b/src/sqlite3_lib.erl index f3e2979..9695fa2 100644 --- a/src/sqlite3_lib.erl +++ b/src/sqlite3_lib.erl @@ -4,6 +4,8 @@ %%% @copyright 21 Jun 2008 by Tee Teoh %%% @version 1.0.0 %%% @doc Library module for sqlite3 +%%% +%%% @type table() = atom() | binary() | string(). %%% @end %%%------------------------------------------------------------------- -module(sqlite3_lib). @@ -192,8 +194,8 @@ read_cols_sql(Columns) -> map_intersperse(fun atom_to_list/1, Columns, ", "). %%-------------------------------------------------------------------- -%% @spec create_table_sql(Tbl :: atom(), ColumnData) -> iolist() -%% Tbl = atom() +%% @spec create_table_sql(Tbl :: table(), ColumnData) -> iolist() +%% Tbl = table() %% ColumnData = {Column, Type} | {Column, Type, Constraints} %% Column = atom() %% Type = atom() @@ -201,14 +203,14 @@ read_cols_sql(Columns) -> %% @doc Generates a table create stmt in SQL. %% @end %%-------------------------------------------------------------------- --spec create_table_sql(atom(), table_info()) -> iolist(). +-spec create_table_sql(table(), table_info()) -> iolist(). create_table_sql(Tbl, Columns) -> - ["CREATE TABLE ", atom_to_list(Tbl), " (", + ["CREATE TABLE ", to_iolist(Tbl), " (", map_intersperse(fun column_sql_for_create_table/1, Columns, ", "), ");"]. %%-------------------------------------------------------------------- -%% @spec create_table_sql(Tbl :: atom(), ColumnData, TableConstraints) -> iolist() -%% Tbl = atom() +%% @spec create_table_sql(Tbl :: table(), ColumnData, TableConstraints) -> iolist() +%% Tbl = table() %% ColumnData = {Column, Type} | {Column, Type, Constraints} %% Column = atom() %% Type = atom() @@ -217,16 +219,16 @@ create_table_sql(Tbl, Columns) -> %% @doc Generates a table create stmt in SQL. %% @end %%-------------------------------------------------------------------- --spec create_table_sql(atom(), table_info(), table_constraints()) -> iolist(). +-spec create_table_sql(table(), table_info(), table_constraints()) -> iolist(). create_table_sql(Tbl, Columns, TblConstraints) -> - ["CREATE TABLE ", atom_to_list(Tbl), " (", + ["CREATE TABLE ", to_iolist(Tbl), " (", map_intersperse(fun column_sql_for_create_table/1, Columns, ", "), ", ", table_constraint_sql(TblConstraints), ");"]. %%-------------------------------------------------------------------- %% @spec update_sql(Tbl, Key, Value, Data) -> iolist() -%% Tbl = atom() +%% Tbl = table() %% Key = atom() %% Value = sql_value() %% Data = [{Column :: atom(), Value :: sql_value()}] @@ -236,65 +238,65 @@ create_table_sql(Tbl, Columns, TblConstraints) -> %% record with matching Value. %% @end %%-------------------------------------------------------------------- --spec update_sql(atom(), atom(), sql_value(), [{atom(), sql_value()}]) -> iolist(). +-spec update_sql(table(), atom(), sql_value(), [{atom(), sql_value()}]) -> iolist(). update_sql(Tbl, Key, Value, Data) -> - ["UPDATE ", atom_to_list(Tbl), " SET ", update_set_sql(Data), + ["UPDATE ", to_iolist(Tbl), " SET ", update_set_sql(Data), " WHERE ", atom_to_list(Key), " = ", value_to_sql(Value), ";"]. %%-------------------------------------------------------------------- %% @spec write_sql(Tbl, Data) -> iolist() -%% Tbl = atom() +%% Tbl = table() %% Data = [{ColName :: atom(), Value :: sql_value()}] %% @doc Taking Data as list of column names and values pairs it creates the %% proper insertion SQL stmt. %% @end %%-------------------------------------------------------------------- --spec write_sql(atom(), [{atom(), sql_value()}]) -> iolist(). +-spec write_sql(table(), [{atom(), sql_value()}]) -> iolist(). write_sql(Tbl, Data) -> {Cols, Values} = lists:unzip(Data), - ["INSERT INTO ", atom_to_list(Tbl), " (", write_col_sql(Cols), + ["INSERT INTO ", to_iolist(Tbl), " (", write_col_sql(Cols), ") values (", write_value_sql(Values), ");"]. %%-------------------------------------------------------------------- %% @spec read_sql(Tbl) -> iolist() -%% Tbl = atom() +%% Tbl = table() %% @doc Returns all records from table Tbl. %% @end %%-------------------------------------------------------------------- --spec read_sql(atom()) -> iolist(). +-spec read_sql(table()) -> iolist(). read_sql(Tbl) -> - ["SELECT * FROM ", atom_to_list(Tbl), ";"]. + ["SELECT * FROM ", to_iolist(Tbl), ";"]. %%-------------------------------------------------------------------- %% @spec read_sql(Tbl, Columns) -> iolist() -%% Tbl = atom() +%% Tbl = table() %% Columns = [atom()] %% @doc %% Returns only specified Columns of all records from table Tbl. %% @end %%-------------------------------------------------------------------- --spec read_sql(atom(), [atom()]) -> iolist(). +-spec read_sql(table(), [atom()]) -> iolist(). read_sql(Tbl, Columns) -> ["SELECT ", read_cols_sql(Columns), " FROM ", - atom_to_list(Tbl), ";"]. + to_iolist(Tbl), ";"]. %%-------------------------------------------------------------------- %% @spec read_sql(Tbl, Key, Value) -> iolist() -%% Tbl = atom() +%% Tbl = table() %% Key = atom() %% Value = sql_value() %% @doc Using Key as the column name searches for the record with %% matching Value. %% @end %%-------------------------------------------------------------------- --spec read_sql(atom(), atom(), sql_value()) -> iolist(). +-spec read_sql(table(), atom(), sql_value()) -> iolist(). read_sql(Tbl, Key, Value) -> - ["SELECT * FROM ", atom_to_list(Tbl), " WHERE ", atom_to_list(Key), + ["SELECT * FROM ", to_iolist(Tbl), " WHERE ", atom_to_list(Key), " = ", value_to_sql(Value), ";"]. %%-------------------------------------------------------------------- %% @spec read_sql(Tbl, Key, Value, Columns) -> iolist() -%% Tbl = atom() +%% Tbl = table() %% Key = atom() %% Value = sql_value() %% Columns = [atom()] @@ -303,35 +305,35 @@ read_sql(Tbl, Key, Value) -> %% matching Value and returns only specified Columns. %% @end %%-------------------------------------------------------------------- --spec read_sql(atom(), atom(), sql_value(), [atom()]) -> iolist(). +-spec read_sql(table(), atom(), sql_value(), [atom()]) -> iolist(). read_sql(Tbl, Key, Value, Columns) -> ["SELECT ", read_cols_sql(Columns), " FROM ", - atom_to_list(Tbl), " WHERE ", atom_to_list(Key), " = ", + to_iolist(Tbl), " WHERE ", atom_to_list(Key), " = ", value_to_sql(Value), ";"]. %%-------------------------------------------------------------------- %% @spec delete_sql(Tbl, Key, Value) -> iolist() -%% Tbl = atom() +%% Tbl = table() %% Key = atom() %% Value = sql_value() %% @doc Using Key as the column name searches for the record with %% matching Value then deletes that record. %% @end %%-------------------------------------------------------------------- --spec delete_sql(atom(), atom(), sql_value()) -> iolist(). +-spec delete_sql(table(), atom(), sql_value()) -> iolist(). delete_sql(Tbl, Key, Value) -> - ["DELETE FROM ", atom_to_list(Tbl), " WHERE ", atom_to_list(Key), + ["DELETE FROM ", to_iolist(Tbl), " WHERE ", atom_to_list(Key), " = ", value_to_sql(Value), ";"]. %%-------------------------------------------------------------------- %% @spec drop_table_sql(Tbl) -> iolist() -%% Tbl = atom() +%% Tbl = table() %% @doc Drop the table Tbl from the database %% @end %%-------------------------------------------------------------------- --spec drop_table_sql(atom()) -> iolist(). +-spec drop_table_sql(table()) -> iolist(). drop_table_sql(Tbl) -> - ["DROP TABLE ", atom_to_list(Tbl), ";"]. + ["DROP TABLE ", to_iolist(Tbl), ";"]. %%==================================================================== %% Internal functions @@ -418,6 +420,15 @@ indexed_column_sql({ColumnName, asc}) -> [atom_to_list(ColumnName), " ASC"]; indexed_column_sql({ColumnName, desc}) -> [atom_to_list(ColumnName), " DESC"]; indexed_column_sql(ColumnName) -> atom_to_list(ColumnName). +to_iolist(A) when is_atom(A) -> + atom_to_list(A); +to_iolist(L) when is_list(L) -> + iolist_to_binary(L); +to_iolist(B) when is_binary(B) -> + B. + + + %%-------------------------------------------------------------------- %% @type sql_value() = number() | 'null' | iodata(). %%