Exploring the api
This commit is contained in:
@@ -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}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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;"),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user