From 6986d0bbde6dd237258eb3d721efb595787aa32b Mon Sep 17 00:00:00 2001 From: Ulf Wiger Date: Wed, 22 Feb 2012 20:44:07 +0100 Subject: [PATCH] Changed the type of table names to include binaries and strings. Table names get converted into iolists anyway, and in some applications, it is undesireable to have to create atoms for dynamic table names. --- README.md | 55 ++--------------- include/sqlite3.hrl | 1 + src/sqlite3.erl | 142 ++++++++++++++++++++++---------------------- src/sqlite3_lib.erl | 75 +++++++++++++---------- 4 files changed, 121 insertions(+), 152 deletions(-) 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(). %%