Exploring the api

This commit is contained in:
Maas-Maarten Zeeman
2011-10-23 19:42:29 +02:00
parent 5a56f14bb7
commit 4bf0747ddc
3 changed files with 116 additions and 21 deletions

View File

@@ -32,6 +32,8 @@ typedef enum {
cmd_unknown, cmd_unknown,
cmd_open, cmd_open,
cmd_exec, cmd_exec,
cmd_prepare,
cmd_step,
cmd_close, cmd_close,
cmd_stop cmd_stop
} command_type; } command_type;
@@ -108,16 +110,20 @@ descruct_esqlite_db(ErlNifEnv *env, void *arg)
esqlite_db *db = (esqlite_db *) arg; esqlite_db *db = (esqlite_db *) arg;
esqlite_command *cmd = command_create(); esqlite_command *cmd = command_create();
/* Send the stop command */ /* Send the stop command
*/
cmd->type = cmd_stop; cmd->type = cmd_stop;
queue_push(db->commands, cmd); queue_push(db->commands, cmd);
queue_send(db->commands, cmd); queue_send(db->commands, cmd);
/* wait for the thread to finish */ /* Wait for the thread to finish
*/
enif_thread_join(db->tid, NULL); enif_thread_join(db->tid, NULL);
enif_thread_opts_destroy(db->opts); enif_thread_opts_destroy(db->opts);
/* the thread is finished... remove the command queue, and close the datbase. */ /* The thread has finished... now remove the command queue, and close
* the datbase (if it was still open).
*/
queue_destroy(db->commands); queue_destroy(db->commands);
if(db->db) if(db->db)
@@ -139,30 +145,37 @@ do_open(ErlNifEnv *env, esqlite_db *db, const ERL_NIF_TERM arg)
if(size <= 0) if(size <= 0)
return make_error_tuple(env, "invalid_filename"); return make_error_tuple(env, "invalid_filename");
/* Open the database.
*/
rc = sqlite3_open(filename, &db->db); rc = sqlite3_open(filename, &db->db);
if(rc == SQLITE_OK) { if(rc != SQLITE_OK) {
fprintf(stderr, "opened %s\n", filename); error = make_error_tuple(env, sqlite3_errmsg(db->db));
return _atom_ok; sqlite3_close(db->db);
db->db = NULL;
return error;
} }
error = make_error_tuple(env, sqlite3_errmsg(db->db)); return _atom_ok;
sqlite3_close(db->db);
db->db = NULL;
return error;
} }
static int static int
the_callback(void *a_param, int argc, char **argv, char **column) the_callback(void *a_param, int argc, char **argv, char **column)
{ {
/* This only returns null terminated strings... */
int i; int i;
fprintf(stderr, "record::::\n");
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
fprintf(stderr, "%s,\t", argv[i]); fprintf(stderr, "%s,\t", argv[i]);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
return 0; return 0;
} }
/*
* The limit of sqlite3_exec is that it can only return null
* terminated string values. If you need different datatypes you
* should use the prepare, bind, step interface.
*/
static ERL_NIF_TERM static ERL_NIF_TERM
do_exec(ErlNifEnv *env, esqlite_db *db, const ERL_NIF_TERM arg) do_exec(ErlNifEnv *env, esqlite_db *db, const ERL_NIF_TERM arg)
{ {
@@ -175,16 +188,54 @@ do_exec(ErlNifEnv *env, esqlite_db *db, const ERL_NIF_TERM arg)
/* Get the query as a binary -- and the end of string -- */ /* Get the query as a binary -- and the end of string -- */
enif_inspect_iolist_as_binary(env, arg, &bin); enif_inspect_iolist_as_binary(env, arg, &bin);
rc = sqlite3_exec(db->db, bin.data, the_callback, NULL, NULL); rc = sqlite3_exec(db->db, (char *) bin.data, the_callback, NULL, NULL);
/* TODO: check rc*/
fprintf(stderr, "do_exec %s: %d\n", bin.data, rc);
return _atom_ok; return _atom_ok;
} }
static ERL_NIF_TERM static ERL_NIF_TERM
do_close(ErlNifEnv *env, esqlite_db *db, const ERL_NIF_TERM arg) do_prepare(ErlNifEnv *env, esqlite_db *conn, const ERL_NIF_TERM arg)
{ {
fprintf(stderr, "do_close\n"); ErlNifBinary bin;
int rc;
if(!conn->db)
return make_error_tuple(env, "database_not_open");
/* Get the query as binary -- and the included end of string -- */
enif_inspect_iolist_as_binary(env, arg, &bin);
fprintf(stderr, "do_prepare\n");
/* return the prepared statement. */
return _atom_ok;
}
static ERL_NIF_TERM
do_step(ErlNifEnv *env, esqlite_db *db, const ERL_NIF_TERM arg)
{
fprintf(stderr, "do_prepare\n");
return _atom_ok;
}
static ERL_NIF_TERM
do_close(ErlNifEnv *env, esqlite_db *conn, const ERL_NIF_TERM arg)
{
int rc;
if(!conn->db)
return make_error_tuple(env, "database_not_open");
rc = sqlite3_close(conn->db);
if(rc != SQLITE_OK)
return make_error_tuple(env, sqlite3_errmsg(conn->db));
conn->db = NULL;
return _atom_ok; return _atom_ok;
} }
@@ -196,6 +247,10 @@ evaluate_command(ErlNifEnv *env, command_type type, esqlite_db *db, const ERL_NI
return do_open(env, db, arg); return do_open(env, db, arg);
case cmd_exec: case cmd_exec:
return do_exec(env, db, arg); return do_exec(env, db, arg);
case cmd_prepare:
return do_prepare(env, db, arg);
case cmd_step:
return do_step(env, db, arg);
case cmd_close: case cmd_close:
return do_close(env, db, arg); return do_close(env, db, arg);
default: default:
@@ -373,6 +428,9 @@ static ErlNifFunc nif_funcs[] = {
{"esqlite_start", 0, start_nif}, {"esqlite_start", 0, start_nif},
{"esqlite_open", 4, esqlite_open_nif}, {"esqlite_open", 4, esqlite_open_nif},
{"esqlite_exec", 4, esqlite_exec_nif}, {"esqlite_exec", 4, esqlite_exec_nif},
{"esqlite_prepare", 4, esqlite_prepare_nif},
{"esqlite_bind", 3, esqlite_bind_named},
{"esqlite_bind", 2, esqlite_bind},
{"esqlite_close", 3, esqlite_close_nif} {"esqlite_close", 3, esqlite_close_nif}
}; };

View File

@@ -55,7 +55,6 @@ close(Db, Timeout) ->
ok = esqlite_close(Db, Ref, self()), ok = esqlite_close(Db, Ref, self()),
receive_answer(Ref, Timeout). receive_answer(Ref, Timeout).
%% ---- Internal ---- %% ---- Internal ----
esqlite_start() -> esqlite_start() ->
exit(nif_library_not_loaded). exit(nif_library_not_loaded).

View File

@@ -22,11 +22,49 @@ open_multiple_different_databases_test() ->
simple_query_test() -> simple_query_test() ->
{ok, Db} = esqlite:open(":memory:"), {ok, Db} = esqlite:open(":memory:"),
esqlite:exec(Db, "begin;"),
esqlite:exec(Db, "create table test_table(one varchar(10), two int);"), esqlite:exec(Db, "create table test_table(one varchar(10), two int);"),
esqlite:exec(Db, ["insert into test_table values(", "\"hello\"", ",", "10" ");"]), esqlite:exec(Db, ["insert into test_table values(", "\"hello1\"", ",", "10" ");"]),
esqlite:exec(Db, ["insert into test_table values(", "\"hello2\"", ",", "11" ");"]),
esqlite:exec(Db, ["insert into test_table values(", "\"hello3\"", ",", "12" ");"]),
esqlite:exec(Db, ["insert into test_table values(", "\"hello4\"", ",", "13" ");"]),
esqlite:exec(Db, "commit;"),
esqlite:exec(Db, "select * from test_table;"), esqlite:exec(Db, "select * from test_table;"),
ok. ok.
prepare_test() ->
{ok, Db} = esqlite:open(":memory:"),
esqlite:exec(Db, "begin;"),
esqlite:exec(Db, "create table test_table(one varchar(10), two int);"),
{ok, Statement} = esqlite:prepare("insert into_test_table(:one, :two)"),
esqlite:bind(Statement, ":one", "hello"),
esqlite:bind(Statement, ":two", 11),
%% of
esqlite:bind(Statement, ["hello", 11]),
{ok, []} = esqlite:execute(Statement),
esqlite:exec(Db, "commit;"),