From e4878b20647e2229661bdd2d19465870bab27ba9 Mon Sep 17 00:00:00 2001 From: Tee Teoh Date: Wed, 18 Jun 2008 23:34:09 -0400 Subject: [PATCH] Makefile changes for better compiles. sqlite.erl supports start_link/stop and open/close paradigm. added write_sql creation. --- priv/Makefile | 6 ++-- src/sqlite.erl | 81 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/priv/Makefile b/priv/Makefile index 4ec8355..e3a3ec0 100644 --- a/priv/Makefile +++ b/priv/Makefile @@ -4,11 +4,11 @@ FLAGS=-I$(OTP_DIR)/include -L$(OTP_DIR)/lib #GCC=/opt/local/bin/gcc-apple-4.2 GCC=/usr/bin/gcc -all: erl_comm.c sqlite_port.c - $(GCC) -Wall -o sqlite_port erl_comm.c sqlite_port.c $(FLAGS) $(LIB) +all: obj + $(GCC) -Wall -o sqlite_port $(FLAGS) $(LIB) erl_comm.o sqlite_port.o obj: erl_comm.c sqlite_port.c - $(GCC) -Wall -c $(FLAGS) erl_comm.c sqlite_port.c + $(GCC) -Wall -c $(FLAGS) erl_comm.c sqlite_port.c clean: - rm -f *.o sqlite_port diff --git a/src/sqlite.erl b/src/sqlite.erl index a3731ee..64ae3b5 100644 --- a/src/sqlite.erl +++ b/src/sqlite.erl @@ -12,12 +12,14 @@ %% API -export([open/1, open/2]). -export([start_link/1, start_link/2]). --export([stop/1, close/1]). --export([sql_exec/2]). +-export([stop/0, close/1]). +-export([sql_exec/1, sql_exec/2]). --export([create_table/3]). --export([list_tables/1, table_info/2]). --export([create_table_sql/2]). +-export([create_table/2, create_table/3]). +-export([list_tables/0, list_tables/1, table_info/1, table_info/2]). +-export([write/2, write/3]). + +-export([write_sql/2, write_col_sql/1, write_value_sql/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -33,7 +35,7 @@ %% Description: Starts the server %%-------------------------------------------------------------------- start_link(Db) -> - start_link(Db, [{db, "./" ++ atom_to_list(Db) ++ ".db"}]). + ?MODULE:open(?MODULE, [{db, "./" ++ atom_to_list(Db) ++ ".db"}]). %%-------------------------------------------------------------------- %% Function: start_link(Db, Options) -> {ok,Pid} | ignore | {error,Error} @@ -41,33 +43,56 @@ start_link(Db) -> %% {db, DbFile :: String()} %%-------------------------------------------------------------------- start_link(Db, Options) -> - gen_server:start_link({local, Db}, ?MODULE, Options, []). + Opts = case proplists:get_value(db, Options) of + undefined -> [{db, "./" ++ atom_to_list(Db) ++ ".db"} | Options]; + _ -> Options + end, + ?MODULE:open(?MODULE, Opts). open(Db) -> - ?MODULE:start_link(Db). + ?MODULE:open(Db, [{db, "./" ++ atom_to_list(Db) ++ ".db"}]). open(Db, Options) -> - ?MODULE:start_link(Db, Options). + gen_server:start_link({local, Db}, ?MODULE, Options, []). + close(Db) -> gen_server:call(Db, close). -stop(Db) -> - ?MODULE:close(Db). +stop() -> + ?MODULE:close(?MODULE). +sql_exec(SQL) -> + ?MODULE:sql_exec(?MODULE, SQL). + sql_exec(Db, SQL) -> gen_server:call(Db, {sql_exec, SQL}). +create_table(Tbl, Options) -> + ?MODULE:create_table(?MODULE, Tbl, Options). + create_table(Db, Tbl, Options) -> gen_server:call(Db, {create_table, Tbl, Options}). % returns list or ok +list_tables() -> + ?MODULE:list_tables(?MODULE). + list_tables(Db) -> gen_server:call(Db, list_tables). +table_info(Tbl) -> + ?MODULE:table_info(?MODULE, Tbl). + table_info(Db, Tbl) -> gen_server:call(Db, {table_info, Tbl}). +write(Tbl, Data) -> + ?MODULE:write(?MODULE, Tbl, Data). + +write(Db, Tbl, Data) -> + gen_server:call(Db, {write, Tbl, Data}). + %%==================================================================== %% gen_server callbacks %%==================================================================== @@ -103,10 +128,10 @@ handle_call(list_tables, _From, #state{port = Port} = State) -> Reply = exec(Port, {list_tables, none}), {reply, Reply, State}; handle_call({table_info, Tbl}, _From, #state{port = Port} = State) -> - % make sure we only get table info + % make sure we only get table info. + % SQL Injection warning SQL = io_lib:format("select sql from sqlite_master where tbl_name = '~p' and type='table';", [Tbl]), - Cmd = {sql_exec, SQL}, - [{Info}] = exec(Port, Cmd), + [{Info}] = exec(Port, {sql_exec, SQL}), Reply = parse_table_info(Info), {reply, Reply, State}; handle_call({create_table, Tbl, Options}, _From, #state{port = Port} = State) -> @@ -114,6 +139,10 @@ handle_call({create_table, Tbl, Options}, _From, #state{port = Port} = State) -> Cmd = {sql_exec, SQL}, Reply = exec(Port, Cmd), {reply, Reply, State}; +handle_call({write, Tbl, Data}, _From, #state{port = Port} = State) -> + % insert into t1 (data,num) values ('This is sample data',3); + Reply = ok, + {reply, Reply, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. @@ -200,6 +229,30 @@ create_table_sql(Tbl, [{Name, Type} | Tl]) -> io_lib:format("~p ~s", [Name0, col_type(Type0)]) end, Tl), ", ") ++ ");", lists:flatten(CT ++ Start ++ End). + +% insert into t1 (data,num) values ('This is sample data',3); +write_sql(Tbl, Data) -> + {Cols, Values} = lists:unzip(Data), + lists:flatten(io_lib:format("INSERT INTO ~p (~s) values (~s);", + [Tbl, write_col_sql(Cols), write_value_sql(Values)])). + +% currently only support integer, double/float and strings +write_value_sql(Values) -> + StrValues = lists:map(fun(X) when is_integer(X) -> + integer_to_list(X); + (X) when is_float(X) -> + float_to_list(X); + (X) -> + io_lib:format("'~s'", [X]) + end, Values), + string:join(StrValues, ","). + +write_col_sql(Cols) -> + StrCols = lists:map(fun(X) -> + atom_to_list(X) + end, Cols), + string:join(StrCols, ","). + col_type("INTEGER") -> integer;