Small changes

This commit is contained in:
Maas-Maarten Zeeman
2011-10-26 00:59:27 +02:00
parent f21f022eb7
commit e7089bc099
3 changed files with 129 additions and 27 deletions

View File

@@ -40,6 +40,7 @@ typedef enum {
cmd_open,
cmd_exec,
cmd_prepare,
cmd_bind,
cmd_step,
cmd_close,
cmd_stop
@@ -47,11 +48,12 @@ typedef enum {
typedef struct {
command_type type;
ErlNifEnv *env;
ERL_NIF_TERM ref;
ErlNifPid pid;
ERL_NIF_TERM arg;
sqlite3_stmt *stmt;
} esqlite_command;
static ERL_NIF_TERM
@@ -104,6 +106,7 @@ command_create()
cmd->type = cmd_unknown;
cmd->ref = 0;
cmd->arg = 0;
cmd->stmt = NULL;
return cmd;
}
@@ -159,9 +162,6 @@ do_open(ErlNifEnv *env, esqlite_connection *db, const ERL_NIF_TERM arg)
int rc;
ERL_NIF_TERM error;
if(db->db)
return make_error_tuple(env, "database_already_open");
size = enif_get_string(env, arg, filename, MAX_PATHNAME, ERL_NIF_LATIN1);
if(size <= 0)
return make_error_tuple(env, "invalid_filename");
@@ -202,9 +202,6 @@ do_exec(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
ErlNifBinary bin;
int rc;
if(!conn->db)
return make_error_tuple(env, "database_not_open");
/* Get the query as a binary -- and the end of string -- */
enif_inspect_iolist_as_binary(env, arg, &bin);
@@ -224,9 +221,6 @@ do_prepare(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
const char *tail;
int rc;
if(!conn->db)
return make_error_tuple(env, "database_not_open");
/* Get the query as a binary -- and the end of string -- */
enif_inspect_iolist_as_binary(env, arg, &bin);
@@ -242,7 +236,6 @@ do_prepare(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
/* Keep a reference to the connection */
enif_keep_resource(conn);
stmt->connection = conn;
stmt->statement = NULL;
esqlite_stmt = enif_make_resource(env, stmt);
enif_release_resource(stmt);
@@ -251,8 +244,17 @@ do_prepare(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
}
static ERL_NIF_TERM
do_step(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
do_step(ErlNifEnv *env, esqlite_connection *conn, sqlite3_stmt *stmt)
{
int rc;
fprintf(stderr, "step\n");
rc = sqlite3_step(stmt);
fprintf(stderr, "step returned: %d\n", rc);
fprintf(stderr, "nu columns: %d\n", sqlite3_column_count(stmt));
return _atom_ok;
}
@@ -260,10 +262,7 @@ static ERL_NIF_TERM
do_close(ErlNifEnv *env, esqlite_connection *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));
@@ -273,19 +272,22 @@ do_close(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg)
}
static ERL_NIF_TERM
evaluate_command(ErlNifEnv *env, command_type type, esqlite_connection *db, const ERL_NIF_TERM arg)
evaluate_command(ErlNifEnv *env, command_type type, esqlite_connection *conn, sqlite3_stmt *stmt, const ERL_NIF_TERM arg)
{
if(!conn->db)
make_error_tuple(env, "database_not_open");
switch(type) {
case cmd_open:
return do_open(env, db, arg);
return do_open(env, conn, arg);
case cmd_exec:
return do_exec(env, db, arg);
return do_exec(env, conn, arg);
case cmd_prepare:
return do_prepare(env, db, arg);
return do_prepare(env, conn, arg);
case cmd_step:
return do_step(env, db, arg);
return do_step(env, conn, stmt);
case cmd_close:
return do_close(env, db, arg);
return do_close(env, conn, arg);
default:
return make_error_tuple(env, "invalid_command");
}
@@ -308,7 +310,7 @@ esqlite_connection_run(void *arg)
} else {
enif_send(NULL, &cmd->pid, cmd->env,
enif_make_tuple2(cmd->env, cmd->ref,
evaluate_command(cmd->env, cmd->type, db, cmd->arg)));
evaluate_command(cmd->env, cmd->type, db, cmd->stmt, cmd->arg)));
}
command_destroy(cmd);
@@ -465,6 +467,87 @@ esqlite_prepare_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return _atom_ok;
}
/*
* Bind a variable to a prepared statement
*/
static ERL_NIF_TERM
esqlite_bind_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
esqlite_statement *stmt;
esqlite_command *cmd = NULL;
ErlNifPid pid;
if(argc != 4)
return enif_make_badarg(env);
if(!enif_get_resource(env, argv[0], esqlite_statement_type, (void **) &stmt))
return enif_make_badarg(env);
if(!enif_is_ref(env, argv[1]))
return make_error_tuple(env, "invalid_ref");
if(!enif_get_local_pid(env, argv[2], &pid))
return make_error_tuple(env, "invalid_pid");
cmd = command_create();
if(!cmd)
return make_error_tuple(env, "command_create_failed");
cmd->type = cmd_bind;
cmd->ref = enif_make_copy(cmd->env, argv[1]);
cmd->pid = pid;
cmd->arg = enif_make_copy(cmd->env, argv[3]);
if(!stmt->connection)
return make_error_tuple(env, "no_connection");
if(!stmt->connection->commands)
return make_error_tuple(env, "no_command_queue");
if(!queue_push(stmt->connection->commands, cmd))
return make_error_tuple(env, "command_push_failed");
return _atom_ok;
}
/*
* Step to a prepared statement
*/
static ERL_NIF_TERM
esqlite_step_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
esqlite_statement *stmt;
esqlite_command *cmd = NULL;
ErlNifPid pid;
if(argc != 3)
return enif_make_badarg(env);
if(!enif_get_resource(env, argv[0], esqlite_statement_type, (void **) &stmt))
return enif_make_badarg(env);
if(!enif_is_ref(env, argv[1]))
return make_error_tuple(env, "invalid_ref");
if(!enif_get_local_pid(env, argv[2], &pid))
return make_error_tuple(env, "invalid_pid");
if(!stmt->statement)
return make_error_tuple(env, "no_prepared_statement");
cmd = command_create();
if(!cmd)
return make_error_tuple(env, "command_create_failed");
cmd->type = cmd_step;
cmd->ref = enif_make_copy(cmd->env, argv[1]);
cmd->pid = pid;
cmd->stmt = stmt->statement;
if(!stmt->connection)
return make_error_tuple(env, "no_connection");
if(!stmt->connection->commands)
return make_error_tuple(env, "no_command_queue");
if(!queue_push(stmt->connection->commands, cmd))
return make_error_tuple(env, "command_push_failed");
return _atom_ok;
}
/*
* Close the database
*/
@@ -530,8 +613,9 @@ static ErlNifFunc nif_funcs[] = {
{"esqlite_open", 4, esqlite_open_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_step", 3, esqlite_step_nif},
// {"esqlite_bind", 3, esqlite_bind_named},
// {"esqlite_bind", 2, esqlite_bind},
{"esqlite_close", 3, esqlite_close_nif}
};