commit 91ff5f6a881ed793eb6d159b8213385c74d79426 Author: Tee Teoh Date: Mon Jun 2 16:43:16 2008 -0400 Not compiling copy because of a silly linker problem on the mac diff --git a/priv/Makefile b/priv/Makefile new file mode 100644 index 0000000..47c8650 --- /dev/null +++ b/priv/Makefile @@ -0,0 +1,13 @@ +OTP_DIR=/opt/local/lib/erlang/lib/erl_interface-3.5.5.3 +LIB=-lsqlite3 -lerl_interface -lei +FLAGS=-I$(OTP_DIR)/include -L$(OTP_DIR)/lib +GCC=/opt/local/bin/gcc-apple-4.2 + +all: erl_comm.c sqlite_port.c + $(GCC) -Wall -o sqlite_port erl_comm.c sqlite_port.c $(FLAGS) $(LIB) + +obj: 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/priv/erl_comm.c b/priv/erl_comm.c new file mode 100644 index 0000000..c27770c --- /dev/null +++ b/priv/erl_comm.c @@ -0,0 +1,62 @@ +/* erl_comm.c */ +#include +#include +#include + +#include "erl_comm.h" + +int read_exact(byte *buf, int len); +int write_exact(byte *buf, int len); + +int +read_cmd(byte *buf) +{ + int len; + + if (read_exact(buf, 2) != 2) + return(-1); + len = (buf[0] << 8) | buf[1]; + return read_exact(buf, len); +} + +int +write_cmd(byte *buf, int len) +{ + byte li; + + li = (len >> 8) & 0xff; + write_exact(&li, 1); + + li = len & 0xff; + write_exact(&li, 1); + + return write_exact(buf, len); +} + +int +read_exact(byte *buf, int len) +{ + int i, got=0; + + do { + if ((i = read(0, buf+got, len-got)) <= 0) + return(i); + got += i; + } while (got +#include +#include +#include + +#include "erl_comm.h" +#include "erl_interface.h" +#include "ei.h" + +int main(int argc, char **argv) +{ + ETERM *tuplep, *intp; + ETERM *fnp, *argp; + int res; + byte buf[100]; + long allocated, freed; + + sqlite3 *db; + char *zErrMsg = 0; + int rc; + + rc = sqlite3_open(argv[1], &db); + if (rc) { + sqlite3_close(db); + exit(1); + } + + erl_init(NULL, 0); + + while (read_cmd(buf) > 0) { + tuplep = erl_decode(buf); + fnp = erl_element(1, tuplep); + argp = erl_element(2, tuplep); + + if (strncmp((const char *)ERL_ATOM_PTR(fnp), "close", 5) == 0) { + sqlite3_close(db); + break; + } else if (strncmp((const char *)ERL_ATOM_PTR(fnp), "bar", 3) == 0) { + res = ERL_INT_VALUE(argp); + } + + intp = erl_mk_int(res); + erl_encode(intp, buf); + write_cmd(buf, erl_term_len(intp)); + + erl_free_compound(tuplep); + erl_free_term(fnp); + erl_free_term(argp); + erl_free_term(intp); + } + + return 0; +} + + + +static int callback(void *notUsed, int argc, char **argv, char **azColName) { + int i; + printf("runs %d\n", argc); + for (i = 1; i < argc; i++) { + printf("%s = %s\n", azColName[i], argv[1] ? argv[1] : "NULL"); + } + printf("\n"); + return 0; +} + +/* + rc = sqlite3_exec(db, "SELECT * from t1;", callback, 0, &zErrMsg); + if (rc != SQLITE_OK) { + fprintf(stderr, "SQL Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + sqlite3_close(db); +*/ diff --git a/src/sqlite.erl b/src/sqlite.erl new file mode 100644 index 0000000..6d7de13 --- /dev/null +++ b/src/sqlite.erl @@ -0,0 +1,63 @@ +%%%------------------------------------------------------------------- +%%% File : sqlite.erl +%%% Author : Tee Teoh +%%% Description : +%%% +%%% Created : 31 May 2008 by Tee Teoh +%%%------------------------------------------------------------------- +-module(sqlite). + +-behaviour(gen_server). + +%% API +-export([start_link/1]). +-export([stop/1, close/1]). +-export([sql_exec/2]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-record(state, {port, ops = []}). + +%%==================================================================== +%% API +%%==================================================================== +%%-------------------------------------------------------------------- +%% Function: start_link(Db) -> {ok,Pid} | ignore | {error,Error} +%% Description: Starts the server +%%-------------------------------------------------------------------- +start_link(Db) -> + start_link(Db, [{db, "./" ++ atom_to_list(Db) ++ ".db"}]). + +%%-------------------------------------------------------------------- +%% Function: start_link(Db, Options) -> {ok,Pid} | ignore | {error,Error} +%% Description: Starts the server. +%% {db, DbFile :: String()} +%%-------------------------------------------------------------------- +start_link(Db, Options) -> + gen_server:start_link({local, Db}, ?MODULE, [], Options). + +close(Db) -> + gen_server:call(Db, close). + +stop(Db) -> + close(Db). + +sql_exec(Db, SQL) -> + gen_server:call(Db, {sql_exec, SQL}). +%%==================================================================== +%% gen_server callbacks +%%==================================================================== + +%%-------------------------------------------------------------------- +%% Function: init(Args) -> {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%% Description: Initiates the server +%%-------------------------------------------------------------------- +init(Options) -> + Dbase = proplist:get_value(db, Options), + Port = open_port({spawn, create_cmd(Dbase) + "sqlite_port " ++ Dbase.