diff --git a/priv/sqlite3_drv.c b/priv/sqlite3_drv.c index 770c3c1..e35656f 100644 --- a/priv/sqlite3_drv.c +++ b/priv/sqlite3_drv.c @@ -64,17 +64,13 @@ static void outputv(ErlDrvData handle, ErlIOVec *ev) { sqlite3_drv_t* driver_data = (sqlite3_drv_t*) handle; ErlDrvBinary* data = ev->binv[1]; - int command = data->orig_bytes[1]; - fprintf(stderr, "Command: %d\n", command); + int command = data->orig_bytes[0]; switch(command) { - case CMD_LIST_TABLES: - list_tables(driver_data, ev); - break; - case CMD_SQL_EXEC: sql_exec(driver_data, ev); + break; // // // case CMD_GET: // // get(driver_data, ev); @@ -94,40 +90,57 @@ static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data) } -static void list_tables(sqlite3_drv_t *drv, ErlIOVec *ev) { +static int callback(void *data, int argc, char **argv, char **azColName) +{ + sqlite3_drv_t *drv = (sqlite3_drv_t *)data; + int i; + + // ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"), + // ERL_DRV_STRING, error_reason, strlen(error_reason), + // ERL_DRV_TUPLE, 2}; + // + // driver_output_term(drv->port, spec, sizeof(spec) / sizeof(spec[0])); + + + + // record_list = malloc(argc * sizeof(ETERM *)); + + fprintf(stderr, "runs %d\n", argc); + for (i = 0; i < argc; i++) { + fprintf(stderr, "%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); + } + fprintf(stderr, "\n"); + fflush(stderr); + + // result = erl_cons(erl_mk_tuple(record_list, argc), result); + + // free(record_list); + return 0; } + static void sql_exec(sqlite3_drv_t *drv, ErlIOVec *ev) { ErlDrvBinary* input = ev->binv[1]; char *command = input->orig_bytes + 1; int command_size = input->orig_size - 1; - int status; + int status; + char *error = NULL; - fprintf(stderr, "Exec: %s\n", command); + fprintf(stderr, "Exec: %*s\n", command_size, command); - //int status = sqlite3_exec(drv->db, command + status = sqlite3_exec(drv->db, command, callback, drv, &error); - if(status == 0) { - // Insert went OK - // Prepare return value to Erlang VM, returns atom 'ok' - ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok")}; - - // Return the value to the Erlang VM - driver_output_term(drv->port, spec, sizeof(spec) / sizeof(spec[0])); - } else { - // There was an error return {error, Reason} - char * error_reason; - - error_reason = "unkown"; - - // Returns tuple {error, Reason} + if(status != SQLITE_OK) { ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("error"), - ERL_DRV_ATOM, driver_mk_atom(error_reason), + ERL_DRV_STRING, error, strlen(error), ERL_DRV_TUPLE, 2}; driver_output_term(drv->port, spec, sizeof(spec) / sizeof(spec[0])); } + if (error) { + sqlite3_free(error); + } } #if 0 diff --git a/priv/sqlite3_drv.h b/priv/sqlite3_drv.h index 6a97d28..f96ddf8 100644 --- a/priv/sqlite3_drv.h +++ b/priv/sqlite3_drv.h @@ -10,7 +10,6 @@ #define DB_PATH "./store.db" // Binary commands between Erlang VM and Driver -#define CMD_LIST_TABLES 1 #define CMD_SQL_EXEC 2 // #define CMD_DEL 3 @@ -30,7 +29,6 @@ static ErlDrvData start(ErlDrvPort port, char* cmd); static void stop(ErlDrvData handle); static void outputv(ErlDrvData handle, ErlIOVec *ev); static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data); -static void list_tables(sqlite3_drv_t *drv, ErlIOVec *ev); static void sql_exec(sqlite3_drv_t *drv, ErlIOVec *ev); // static void get(bdb_drv_t *bdb_drv, ErlIOVec *ev); // static void del(bdb_drv_t *bdb_drv, ErlIOVec *ev); diff --git a/priv/sqlite_port.c b/priv/sqlite_port.c index 764913d..b14e119 100644 --- a/priv/sqlite_port.c +++ b/priv/sqlite_port.c @@ -39,10 +39,6 @@ static int callback(void *notUsed, int argc, char **argv, char **azColName) ETERM **record_list; int i; - if (result == 0) { - result = erl_mk_empty_list(); - } - record_list = malloc(argc * sizeof(ETERM *)); fprintf(log, "runs %d\n", argc); diff --git a/src/sqlite3.erl b/src/sqlite3.erl index 05e248f..50999e6 100644 --- a/src/sqlite3.erl +++ b/src/sqlite3.erl @@ -360,7 +360,7 @@ handle_call({sql_exec, SQL}, _From, #state{port = Port} = State) -> Reply = exec(Port, {sql_exec, SQL}), {reply, Reply, State}; handle_call(list_tables, _From, #state{port = Port} = State) -> - Reply = exec(Port, {list_tables, none}), + Reply = exec(Port, {sql_exec, "select * from sqlite_master where type='table';"}), {reply, Reply, State}; handle_call({table_info, Tbl}, _From, #state{port = Port} = State) -> % make sure we only get table info. @@ -449,13 +449,14 @@ code_change(_OldVsn, State, _Extra) -> %%% Internal functions %%-------------------------------------------------------------------- +-define(SQL_EXEC_COMMAND, 2). + create_cmd(Dbase) -> "sqlite3_port " ++ Dbase. -exec(Port, {sql_exec, Cmd}) -> - port_command(Port, <<2, (list_to_binary(Cmd))/binary>>), - receive - {Port, {data, Data}} when is_binary(Data) -> +wait_result(Port) -> + receive + {Port, {data, Data}} when is_binary(Data) -> List = binary_to_term(Data), if is_list(List) -> lists:reverse(List); @@ -463,21 +464,12 @@ exec(Port, {sql_exec, Cmd}) -> end; _ -> ok - end; - -exec(Port, Cmd) -> - port_command(Port, term_to_binary(Cmd)), - receive - {Port, {data, Data}} when is_binary(Data) -> - List = binary_to_term(Data), - if is_list(List) -> - lists:reverse(List); - true -> List - end; - _ -> - ok - end. + end. +exec(Port, {sql_exec, Cmd}) -> + port_command(Port, <>), + wait_result(Port). + parse_table_info(Info) -> [_, Tail] = string:tokens(Info, "()"),