From 6c5e13ced3336c13fb8f671f9115611d7722ad4f Mon Sep 17 00:00:00 2001 From: Maas-Maarten Zeeman Date: Tue, 17 May 2022 22:09:25 +0200 Subject: [PATCH] Changed open/close and prepare --- c_src/esqlite3_nif.c | 568 +++++++++++++------------ c_src/queue.c | 195 --------- c_src/queue.h | 24 -- rebar.config.script | 2 +- src/esqlite.app.src | 2 +- src/esqlite3.erl | 964 +++++++++++++++++++++---------------------- src/esqlite3_nif.erl | 187 +++++---- 7 files changed, 856 insertions(+), 1086 deletions(-) delete mode 100644 c_src/queue.c delete mode 100644 c_src/queue.h diff --git a/c_src/esqlite3_nif.c b/c_src/esqlite3_nif.c index 11ec062..13a2057 100644 --- a/c_src/esqlite3_nif.c +++ b/c_src/esqlite3_nif.c @@ -23,31 +23,31 @@ #include #include -#include "queue.h" #define MAX_ATOM_LENGTH 255 /* from atom.h, not exposed in erlang include */ #define MAX_SQLITE_NAME_LENGTH 255 /* Maximum name length. Using longer will return misuse */ #define MAX_PATHNAME 512 /* unfortunately not in sqlite.h. */ -static ErlNifResourceType *esqlite_connection_type = NULL; -static ErlNifResourceType *esqlite_statement_type = NULL; -static ErlNifResourceType *esqlite_backup_type = NULL; +static ErlNifResourceType *esqlite3_type = NULL; +static ErlNifResourceType *esqlite3_stmt_type = NULL; +static ErlNifResourceType *esqlite3_backup_type = NULL; /* database connection context */ typedef struct { sqlite3 *db; -} esqlite_connection; +} esqlite3; /* prepared statement */ typedef struct { sqlite3_stmt *statement; -} esqlite_statement; +} esqlite3_stmt; /* data associated with ongoing backup */ typedef struct { sqlite3_backup *backup; -} esqlite_backup; +} esqlite3_backup; +/* typedef enum { cmd_unknown, cmd_open, @@ -72,6 +72,7 @@ typedef enum { cmd_last_insert_rowid, cmd_get_autocommit, } command_type; +*/ static ERL_NIF_TERM atom_esqlite3; @@ -172,25 +173,25 @@ make_sqlite3_error_tuple(ErlNifEnv *env, int error_code, sqlite3 *db) * */ static void -destruct_esqlite_connection(ErlNifEnv *env, void *arg) +destruct_esqlite3(ErlNifEnv *env, void *arg) { - esqlite_connection *db = (esqlite_connection *) arg; + esqlite3 *db = (esqlite3 *) arg; sqlite3_close_v2(db->db); db->db = NULL; } static void -destruct_esqlite_statement(ErlNifEnv *env, void *arg) +destruct_esqlite3_stmt(ErlNifEnv *env, void *arg) { - esqlite_statement *stmt = (esqlite_statement *) arg; + esqlite3_stmt *stmt = (esqlite3_stmt *) arg; sqlite3_finalize(stmt->statement); stmt->statement = NULL; } static void -destruct_esqlite_backup(ErlNifEnv *env, void *arg) +destruct_esqlite3_backup(ErlNifEnv *env, void *arg) { - esqlite_backup *backup = (esqlite_backup *) arg; + esqlite3_backup *backup = (esqlite3_backup *) arg; if(backup->backup) { sqlite3_backup_finish(backup->backup); @@ -199,38 +200,11 @@ destruct_esqlite_backup(ErlNifEnv *env, void *arg) backup->backup = NULL; } -static ERL_NIF_TERM -do_open(ErlNifEnv *env, esqlite_connection *db, const ERL_NIF_TERM arg) -{ - char filename[MAX_PATHNAME]; - unsigned int size; - int rc; - ERL_NIF_TERM error; - - size = enif_get_string(env, arg, filename, MAX_PATHNAME, ERL_NIF_LATIN1); - if(size <= 0) - return make_error_tuple(env, "invalid_filename"); - - /* Open the database. - */ - rc = sqlite3_open(filename, &db->db); - if(rc != SQLITE_OK) { - error = make_sqlite3_error_tuple(env, rc, db->db); - sqlite3_close_v2(db->db); - db->db = NULL; - - return error; - } - - sqlite3_busy_timeout(db->db, 2000); - - return make_atom(env, "ok"); -} - +/* void update_callback(void *arg, int sqlite_operation_type, char const *sqlite_database, char const *sqlite_table, sqlite3_int64 sqlite_rowid) { - esqlite_connection *db = (esqlite_connection *)arg; + esqlite3 *db = (esqlite3 *)arg; esqlite_command *cmd = NULL; ERL_NIF_TERM type, table, rowid; @@ -263,9 +237,11 @@ update_callback(void *arg, int sqlite_operation_type, char const *sqlite_databas push_command(cmd->env, db, cmd); } +*/ +/* static ERL_NIF_TERM -do_set_update_hook(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) +do_set_update_hook(ErlNifEnv *env, esqlite3 *conn, const ERL_NIF_TERM arg) { if(!enif_get_local_pid(env, arg, &conn->notification_pid)) { return make_error_tuple(env, "invalid_pid"); @@ -279,11 +255,11 @@ do_set_update_hook(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM return make_atom(env, "ok"); } +*/ /* - */ static ERL_NIF_TERM -do_exec(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) +do_exec(ErlNifEnv *env, esqlite3 *conn, const ERL_NIF_TERM arg) { ErlNifBinary bin; int rc; @@ -299,12 +275,12 @@ do_exec(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) return make_atom(env, "ok"); } + */ /* * Nr of changes - */ static ERL_NIF_TERM -do_changes(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) +do_changes(ErlNifEnv *env, esqlite3 *conn, const ERL_NIF_TERM arg) { if(!conn->db) { return make_error_tuple(env, "closed"); @@ -315,12 +291,12 @@ do_changes(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) return make_ok_tuple(env, changes_term); } + */ /* * insert action -*/ static ERL_NIF_TERM -do_insert(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) +do_insert(ErlNifEnv *env, esqlite3 *conn, const ERL_NIF_TERM arg) { ErlNifBinary bin; int rc; @@ -337,12 +313,12 @@ do_insert(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) ERL_NIF_TERM last_rowid_term = enif_make_int64(env, last_rowid); return make_ok_tuple(env, last_rowid_term); } +*/ /* * Return the last inserted rowid - */ static ERL_NIF_TERM -do_last_insert_rowid(ErlNifEnv *env, esqlite_connection *conn) +do_last_insert_rowid(ErlNifEnv *env, esqlite3 *conn) { if(!conn->db) { return make_error_tuple(env, "closed"); @@ -354,39 +330,9 @@ do_last_insert_rowid(ErlNifEnv *env, esqlite_connection *conn) return make_ok_tuple(env, last_rowid_term); } -/* - * Compile a sql statement */ -static ERL_NIF_TERM -do_prepare(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) -{ - ErlNifBinary bin; - esqlite_statement *stmt; - ERL_NIF_TERM esqlite_stmt; - const char *tail; - int rc; - ERL_NIF_TERM eos = enif_make_int(env, 0); - - if(!enif_inspect_iolist_as_binary(env, enif_make_list2(env, arg, eos), &bin)) { - return make_error_tuple(env, "no_iodata"); - } - - stmt = enif_alloc_resource(esqlite_statement_type, sizeof(esqlite_statement)); - if(!stmt) - return make_error_tuple(env, "no_memory"); - - rc = sqlite3_prepare_v2(conn->db, (char *) bin.data, bin.size, &(stmt->statement), &tail); - if(rc != SQLITE_OK) { - enif_release_resource(stmt); - return make_sqlite3_error_tuple(env, rc, conn->db); - } - - esqlite_stmt = enif_make_resource(env, stmt); - enif_release_resource(stmt); - - return make_ok_tuple(env, esqlite_stmt); -} +/* static int bind_cell(ErlNifEnv *env, const ERL_NIF_TERM cell, sqlite3_stmt *stmt, unsigned int i) { @@ -419,23 +365,23 @@ bind_cell(ErlNifEnv *env, const ERL_NIF_TERM cell, sqlite3_stmt *stmt, unsigned return sqlite3_bind_text(stmt, i, the_atom, strlen(the_atom), SQLITE_TRANSIENT); } - /* Bind as text assume it is utf-8 encoded text */ + // Bind as text assume it is utf-8 encoded text if(enif_inspect_iolist_as_binary(env, cell, &the_blob)) { return sqlite3_bind_text(stmt, i, (char *) the_blob.data, the_blob.size, SQLITE_TRANSIENT); } - /* Check for blob tuple */ + // Check for blob tuple if(enif_get_tuple(env, cell, &arity, &tuple)) { if(arity != 2) return -1; - /* length 2! */ + // length 2! if(enif_get_atom(env, tuple[0], the_atom, sizeof(the_atom), ERL_NIF_LATIN1)) { - /* its a blob... */ + // its a blob... if(0 == strncmp("blob", the_atom, strlen("blob"))) { - /* with a iolist as argument */ + // with a iolist as argument if(enif_inspect_iolist_as_binary(env, tuple[1], &the_blob)) { - /* kaboom... get the blob */ + // kaboom... get the blob return sqlite3_bind_blob(stmt, i, the_blob.data, the_blob.size, SQLITE_TRANSIENT); } } @@ -444,7 +390,9 @@ bind_cell(ErlNifEnv *env, const ERL_NIF_TERM cell, sqlite3_stmt *stmt, unsigned return -1; } +*/ +/* static ERL_NIF_TERM do_bind(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TERM arg) { @@ -474,9 +422,11 @@ do_bind(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TERM arg) return make_atom(env, "ok"); } +*/ +/* static ERL_NIF_TERM -do_get_autocommit(ErlNifEnv *env, esqlite_connection *conn) +do_get_autocommit(ErlNifEnv *env, esqlite3 *conn) { if(!conn->db) { return make_error_tuple(env, "closed"); @@ -488,7 +438,9 @@ do_get_autocommit(ErlNifEnv *env, esqlite_connection *conn) return make_atom(env, "false"); } +*/ +/* static ERL_NIF_TERM make_binary(ErlNifEnv *env, const void *bytes, unsigned int size) { @@ -505,7 +457,9 @@ make_binary(ErlNifEnv *env, const void *bytes, unsigned int size) return term; } +*/ +/* static ERL_NIF_TERM make_cell(ErlNifEnv *env, sqlite3_stmt *statement, unsigned int i) { @@ -529,7 +483,9 @@ make_cell(ErlNifEnv *env, sqlite3_stmt *statement, unsigned int i) return make_atom(env, "should_not_happen"); } } +*/ +/* static ERL_NIF_TERM make_row(ErlNifEnv *env, sqlite3_stmt *statement, ERL_NIF_TERM *array, int size) { @@ -541,7 +497,9 @@ make_row(ErlNifEnv *env, sqlite3_stmt *statement, ERL_NIF_TERM *array, int size) return enif_make_tuple_from_array(env, array, size); } +*/ +/* static ERL_NIF_TERM do_multi_step(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TERM arg) { @@ -575,24 +533,26 @@ do_multi_step(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TER status = make_atom(env, "$busy"); break; case SQLITE_DONE: - /* - * Automatically reset the statement after a done so - * column_names will work after the statement is done. - * - * Not resetting the statement can lead to vm crashes. - */ + // + // Automatically reset the statement after a done so + // column_names will work after the statement is done. + // + // Not resetting the statement can lead to vm crashes. + // sqlite3_reset(stmt); status = make_atom(env, "$done"); break; default: - /* We use prepare_v2, so any error code can be returned. */ + // We use prepare_v2, so any error code can be returned. return make_sqlite3_error_tuple(env, rc, db); } enif_free(rowBuffer); return enif_make_tuple2(env, status, rows); } +*/ +/* static ERL_NIF_TERM do_reset(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt) { @@ -602,7 +562,9 @@ do_reset(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt) return make_atom(env, "ok"); } +*/ +/* static ERL_NIF_TERM do_column_names(ErlNifEnv *env, sqlite3_stmt *stmt) { @@ -635,7 +597,9 @@ do_column_names(ErlNifEnv *env, sqlite3_stmt *stmt) enif_free(array); return column_names; } +*/ +/* static ERL_NIF_TERM do_column_types(ErlNifEnv *env, sqlite3_stmt *stmt) { @@ -667,7 +631,9 @@ do_column_types(ErlNifEnv *env, sqlite3_stmt *stmt) enif_free(array); return column_types; } +*/ +/* static ERL_NIF_TERM do_backup_init(ErlNifEnv *env, sqlite3 *db, const ERL_NIF_TERM arg) { @@ -677,8 +643,8 @@ do_backup_init(ErlNifEnv *env, sqlite3 *db, const ERL_NIF_TERM arg) unsigned int size; char dst_name[MAX_SQLITE_NAME_LENGTH]; char src_name[MAX_SQLITE_NAME_LENGTH]; - esqlite_connection *src; - esqlite_backup *esqlite_backup; + esqlite3 *src; + esqlite3_backup *esqlite3_backup; ERL_NIF_TERM erl_backup_term; if(db == NULL) { @@ -696,7 +662,7 @@ do_backup_init(ErlNifEnv *env, sqlite3 *db, const ERL_NIF_TERM arg) if(size <= 0) return make_error_tuple(env, "invalid_dst_name"); - if(!enif_get_resource(env, elements[1], esqlite_connection_type, (void **) &src)) { + if(!enif_get_resource(env, elements[1], esqlite3_type, (void **) &src)) { return make_error_tuple(env, "invalid_src_db"); } if(!src->db) { @@ -712,26 +678,28 @@ do_backup_init(ErlNifEnv *env, sqlite3 *db, const ERL_NIF_TERM arg) return make_sqlite3_error_tuple(env, sqlite3_errcode(db), db); } - esqlite_backup = enif_alloc_resource(esqlite_backup_type, sizeof(esqlite_backup)); - if(!esqlite_backup) { + esqlite3_backup = enif_alloc_resource(esqlite3_backup_type, sizeof(esqlite3_backup)); + if(!esqlite3_backup) { // Release backup resouces (void) sqlite3_backup_finish(backup); return make_error_tuple(env, "no_memory"); } - esqlite_backup->backup = backup; - erl_backup_term = enif_make_resource(env, esqlite_backup); - enif_release_resource(esqlite_backup); + esqlite3_backup->backup = backup; + erl_backup_term = enif_make_resource(env, esqlite3_backup); + enif_release_resource(esqlite3_backup); return make_ok_tuple(env, erl_backup_term); } +*/ +/* static ERL_NIF_TERM do_backup_step(ErlNifEnv *env, sqlite3 *db, const ERL_NIF_TERM arg) { int tuple_arity; const ERL_NIF_TERM *elements; - esqlite_backup *esqlite_backup; + esqlite3_backup *esqlite3_backup; int n_page = 0; int rc; @@ -746,10 +714,10 @@ do_backup_step(ErlNifEnv *env, sqlite3 *db, const ERL_NIF_TERM arg) return make_error_tuple(env, "invalid_tuple"); } - if(!enif_get_resource(env, elements[0], esqlite_backup_type, (void **) &esqlite_backup)) { + if(!enif_get_resource(env, elements[0], esqlite3_backup_type, (void **) &esqlite3_backup)) { return make_error_tuple(env, "invalid"); } - if(!esqlite_backup->backup) { + if(!esqlite3_backup->backup) { return make_error_tuple(env, "backup"); } @@ -757,7 +725,7 @@ do_backup_step(ErlNifEnv *env, sqlite3 *db, const ERL_NIF_TERM arg) return make_error_tuple(env, "n_page"); } - rc = sqlite3_backup_step(esqlite_backup->backup, n_page); + rc = sqlite3_backup_step(esqlite3_backup->backup, n_page); if(rc == SQLITE_DONE) { return make_atom(env, "done"); } @@ -768,63 +736,128 @@ do_backup_step(ErlNifEnv *env, sqlite3 *db, const ERL_NIF_TERM arg) return make_atom(env, "ok"); } +*/ +/* static ERL_NIF_TERM do_backup_remaining(ErlNifEnv *env, const ERL_NIF_TERM arg) { - esqlite_backup *esqlite_backup; + esqlite3_backup *esqlite3_backup; int remaining; ERL_NIF_TERM remaining_term; - if(!enif_get_resource(env, arg, esqlite_backup_type, (void **) &esqlite_backup)) { + if(!enif_get_resource(env, arg, esqlite3_backup_type, (void **) &esqlite3_backup)) { return make_error_tuple(env, "invalid"); } - remaining = sqlite3_backup_remaining(esqlite_backup->backup); + remaining = sqlite3_backup_remaining(esqlite3_backup->backup); remaining_term = enif_make_int64(env, remaining); return make_ok_tuple(env, remaining_term); } +*/ +/* static ERL_NIF_TERM do_backup_pagecount(ErlNifEnv *env, const ERL_NIF_TERM arg) { - esqlite_backup *esqlite_backup; + esqlite3_backup *esqlite3_backup; int pagecount; ERL_NIF_TERM pagecount_term; - if(!enif_get_resource(env, arg, esqlite_backup_type, (void **) &esqlite_backup)) { + if(!enif_get_resource(env, arg, esqlite3_backup_type, (void **) &esqlite3_backup)) { return make_error_tuple(env, "invalid"); } - pagecount = sqlite3_backup_pagecount(esqlite_backup->backup); + pagecount = sqlite3_backup_pagecount(esqlite3_backup->backup); pagecount_term = enif_make_int64(env, pagecount); return make_ok_tuple(env, pagecount_term); } +*/ +/* static ERL_NIF_TERM do_backup_finish(ErlNifEnv *env, const ERL_NIF_TERM arg) { - esqlite_backup *esqlite_backup; + esqlite3_backup *esqlite3_backup; - if(!enif_get_resource(env, arg, esqlite_backup_type, (void **) &esqlite_backup)) { + if(!enif_get_resource(env, arg, esqlite3_backup_type, (void **) &esqlite3_backup)) { return make_error_tuple(env, "invalid"); } - if(esqlite_backup->backup) { - (void) sqlite3_backup_finish(esqlite_backup->backup); - esqlite_backup->backup = NULL; + if(esqlite3_backup->backup) { + (void) sqlite3_backup_finish(esqlite3_backup->backup); + esqlite3_backup->backup = NULL; } return make_atom(env, "ok"); } +*/ +/* + * Open the database + */ static ERL_NIF_TERM -do_close(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) +esqlite_open(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { + esqlite3 *conn; + char filename[MAX_PATHNAME]; + + if(argc != 1) { + return enif_make_badarg(env); + } + + if(!sqlite3_threadsafe()) { + return enif_raise_exception(env, make_atom(env, "not_thread_safe")); + } + + int size = enif_get_string(env, argv[1], filename, MAX_PATHNAME, ERL_NIF_LATIN1); + if(size <= 0) { + return make_error_tuple(env, "invalid_filename"); + } + + /* Initialize the resource */ + conn = enif_alloc_resource(esqlite3_type, sizeof(esqlite3)); + if(!conn) { + return enif_raise_exception(env, make_atom(env, "no_memory")); + } + + /* Open the database. + */ + int rc = sqlite3_open(filename, &conn->db); + if(rc != SQLITE_OK) { + ERL_NIF_TERM error = make_sqlite3_error_tuple(env, rc, conn->db); + sqlite3_close_v2(conn->db); + enif_release_resource(conn); + return error; + } + + /* Set a standard busy timeout of 2 seconds */ + sqlite3_busy_timeout(conn->db, 2000); + + ERL_NIF_TERM db_conn = enif_make_resource(env, conn); + enif_release_resource(conn); + + return make_ok_tuple(env, db_conn); +} + +/* + * Close the database + */ +static ERL_NIF_TERM +esqlite_close(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + esqlite3 *conn; int rc; + if(argc != 1) { + return enif_make_badarg(env); + } + + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) + return enif_make_badarg(env); + rc = sqlite3_close_v2(conn->db); if(rc != SQLITE_OK) return make_sqlite3_error_tuple(env, rc, conn->db); @@ -834,68 +867,65 @@ do_close(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) } /* - * Open the database + * Prepare the sql statement */ static ERL_NIF_TERM -esqlite_open(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +esqlite_prepare(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; + esqlite3 *conn; - if(argc != 1) { + if(argc != 2) + return enif_make_badarg(env); + + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) + return enif_make_badarg(env); + + ErlNifBinary bin; + esqlite3_stmt *stmt; + ERL_NIF_TERM esqlite_stmt; + const char *tail; + int rc; + ERL_NIF_TERM eos = enif_make_int(env, 0); + + if(!enif_inspect_iolist_as_binary(env, enif_make_list2(env, argv[1], eos), &bin)) { return enif_make_badarg(env); } - if(!sqlite3_threadsafe()) { - return enif_raise_exception(env, make_atom(env, "not_thread_safe")); - } - - size = enif_get_string(env, argv[1], filename, MAX_PATHNAME, ERL_NIF_LATIN1); - if(size <= 0) - return make_error_tuple(env, "invalid_filename"); - - /* Initialize the resource */ - conn = enif_alloc_resource(esqlite_connection_type, sizeof(esqlite_connection)); - if(!conn) { + stmt = enif_alloc_resource(esqlite3_stmt_type, sizeof(esqlite3_stmt)); + if(!stmt) { return enif_raise_exception(env, make_atom(env, "no_memory")); } - char filename[MAX_PATHNAME]; - unsigned int size; - int rc; - ERL_NIF_TERM error; - - /* Open the database. - */ - rc = sqlite3_open(filename, conn->db); + rc = sqlite3_prepare_v2(conn->db, (char *) bin.data, bin.size, &(stmt->statement), &tail); if(rc != SQLITE_OK) { - error = make_sqlite3_error_tuple(env, rc, db); - sqlite3_close_v2(conn->db); - enif_release_resource(conn); - return error; + enif_release_resource(stmt); + return make_sqlite3_error_tuple(env, rc, conn->db); } - /* Set a standard busy timeout of 2 seconds */ - sqlite3_busy_timeout(conn->db, 2000); - - ERL_NIF_TERM = db_conn = enif_make_resource(env, conn); - enif_release_resource(conn); + esqlite_stmt = enif_make_resource(env, stmt); + enif_release_resource(stmt); - return make_ok_tuple(env, db_conn); + return make_ok_tuple(env, esqlite_stmt); } + +/* static ERL_NIF_TERM set_update_hook(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *db; + esqlite3 *db; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &db)) + + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &db)) 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"); @@ -903,7 +933,7 @@ set_update_hook(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) if(!cmd) return make_error_tuple(env, "command_create_failed"); - /* command */ + // command cmd->type = cmd_update_hook_set; cmd->ref = enif_make_copy(cmd->env, argv[1]); cmd->pid = pid; @@ -911,20 +941,20 @@ set_update_hook(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, db, cmd); } +*/ /* * Execute the sql statement - */ static ERL_NIF_TERM esqlite_exec(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *db; + esqlite3 *db; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &db)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &db)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[1])) return make_error_tuple(env, "invalid_ref"); @@ -935,7 +965,7 @@ esqlite_exec(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) if(!cmd) return make_error_tuple(env, "command_create_failed"); - /* command */ + // command cmd->type = cmd_exec; cmd->ref = enif_make_copy(cmd->env, argv[1]); cmd->pid = pid; @@ -943,20 +973,20 @@ esqlite_exec(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, db, cmd); } + */ /* * Count the nr of changes of last statement - */ static ERL_NIF_TERM esqlite_changes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *db; + esqlite3 *db; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 3) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &db)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &db)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[1])) return make_error_tuple(env, "invalid_ref"); @@ -967,24 +997,26 @@ esqlite_changes(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) if(!cmd) return make_error_tuple(env, "command_create_failed"); - /* command */ + // command cmd->type = cmd_changes; cmd->ref = enif_make_copy(cmd->env, argv[1]); cmd->pid = pid; return push_command(env, db, cmd); } + */ +/* static ERL_NIF_TERM esqlite_insert(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *db; + esqlite3 *db; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &db)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &db)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[1])) return make_error_tuple(env, "invalid_ref"); @@ -995,7 +1027,7 @@ esqlite_insert(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) if(!cmd) return make_error_tuple(env, "command_create_failed"); - /* command */ + // command cmd->type = cmd_insert; cmd->ref = enif_make_copy(cmd->env, argv[1]); cmd->pid = pid; @@ -1003,17 +1035,19 @@ esqlite_insert(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, db, cmd); } +*/ +/* static ERL_NIF_TERM esqlite_last_insert_rowid(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *db; + esqlite3 *db; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 3) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &db)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &db)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[1])) return make_error_tuple(env, "invalid_ref"); @@ -1024,24 +1058,26 @@ esqlite_last_insert_rowid(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) if(!cmd) return make_error_tuple(env, "command_create_failed"); - /* command */ + // command cmd->type = cmd_last_insert_rowid; cmd->ref = enif_make_copy(cmd->env, argv[1]); cmd->pid = pid; return push_command(env, db, cmd); } +*/ +/* static ERL_NIF_TERM esqlite_get_autocommit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *db; + esqlite3 *db; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 3) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &db)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &db)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[1])) return make_error_tuple(env, "invalid_ref"); @@ -1052,62 +1088,31 @@ esqlite_get_autocommit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) if(!cmd) return make_error_tuple(env, "command_create_failed"); - /* command */ + // command cmd->type = cmd_get_autocommit; cmd->ref = enif_make_copy(cmd->env, argv[1]); cmd->pid = pid; return push_command(env, db, cmd); } - -/* - * Prepare the sql statement - */ -static ERL_NIF_TERM -esqlite_prepare(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) -{ - esqlite_connection *conn; - esqlite_command *cmd = NULL; - ErlNifPid pid; - - if(argc != 4) - return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) - 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_prepare; - cmd->ref = enif_make_copy(cmd->env, argv[1]); - cmd->pid = pid; - cmd->arg = enif_make_copy(cmd->env, argv[3]); - - return push_command(env, conn, cmd); -} +*/ /* * Bind a variable to a prepared statement - */ static ERL_NIF_TERM esqlite_bind(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; - esqlite_statement *stmt; + esqlite3 *conn; + esqlite3_stmt *stmt; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 5) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[1], esqlite_statement_type, (void **) &stmt)) + if(!enif_get_resource(env, argv[1], esqlite3_stmt_type, (void **) &stmt)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[2])) return make_error_tuple(env, "invalid_ref"); @@ -1126,15 +1131,15 @@ esqlite_bind(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, conn, cmd); } + */ /* * Multi step to a prepared statement - */ static ERL_NIF_TERM esqlite_multi_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; - esqlite_statement *stmt; + esqlite3 *conn; + esqlite3_stmt *stmt; esqlite_command *cmd = NULL; ErlNifPid pid; int chunk_size = 0; @@ -1142,10 +1147,10 @@ esqlite_multi_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) if(argc != 5) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[1], esqlite_statement_type, (void **) &stmt)) + if(!enif_get_resource(env, argv[1], esqlite3_stmt_type, (void **) &stmt)) return enif_make_badarg(env); if(!enif_get_int(env, argv[2], &chunk_size)) @@ -1172,23 +1177,23 @@ esqlite_multi_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, conn, cmd); } + */ /* * Reset a prepared statement to its initial state - */ static ERL_NIF_TERM esqlite_reset(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; - esqlite_statement *stmt; + esqlite3 *conn; + esqlite3_stmt *stmt; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[1], esqlite_statement_type, (void **) &stmt)) + if(!enif_get_resource(env, argv[1], esqlite3_stmt_type, (void **) &stmt)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[2])) return make_error_tuple(env, "invalid_ref"); @@ -1208,23 +1213,23 @@ esqlite_reset(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, conn, cmd); } + */ /* * Get the column names of the prepared statement. - */ static ERL_NIF_TERM esqlite_column_names(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; - esqlite_statement *stmt; + esqlite3 *conn; + esqlite3_stmt *stmt; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[1], esqlite_statement_type, (void **) &stmt)) + if(!enif_get_resource(env, argv[1], esqlite3_stmt_type, (void **) &stmt)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[2])) return make_error_tuple(env, "invalid_ref"); @@ -1244,24 +1249,24 @@ esqlite_column_names(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, conn, cmd); } + */ /* * Get the column types of the prepared statement. - */ static ERL_NIF_TERM esqlite_column_types(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; - esqlite_statement *stmt; + esqlite3 *conn; + esqlite3_stmt *stmt; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[1], esqlite_statement_type, (void **) &stmt)) + if(!enif_get_resource(env, argv[1], esqlite3_stmt_type, (void **) &stmt)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[2])) return make_error_tuple(env, "invalid_ref"); @@ -1282,24 +1287,25 @@ esqlite_column_types(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, conn, cmd); } + */ /* * Backup functions * */ - +/* static ERL_NIF_TERM esqlite_backup_init(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *destination; + esqlite3 *destination; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 6) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &destination)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &destination)) return enif_make_badarg(env); // 1 destination name // 2 source connection with database @@ -1318,22 +1324,24 @@ esqlite_backup_init(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) cmd->pid = pid; cmd->arg = enif_make_tuple3(cmd->env, argv[1], argv[2], argv[3]); - /* Use the connection of the destination database */ + // Use the connection of the destination database return push_command(env, destination, cmd); } +*/ +/* static ERL_NIF_TERM esqlite_backup_finish(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; - esqlite_backup *backup; + esqlite3 *conn; + esqlite3_backup *backup; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); if(!enif_is_ref(env, argv[2])) @@ -1352,19 +1360,21 @@ esqlite_backup_finish(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, conn, cmd); } +*/ +/* static ERL_NIF_TERM esqlite_backup_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; - esqlite_backup *backup; + esqlite3 *conn; + esqlite3_backup *backup; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 5) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); // 1 backup if(!enif_is_number(env, argv[2])) @@ -1385,23 +1395,23 @@ esqlite_backup_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, conn, cmd); } +*/ /* * Get the remaining pagecount of the backup. - */ static ERL_NIF_TERM esqlite_backup_remaining(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; - esqlite_backup *backup; + esqlite3 *conn; + esqlite3_backup *backup; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); // backup 1 if(!enif_is_ref(env, argv[2])) @@ -1420,23 +1430,23 @@ esqlite_backup_remaining(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, conn, cmd); } + */ /* * Get the total pagecount of the backup - */ static ERL_NIF_TERM esqlite_backup_pagecount(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; - esqlite_backup *backup; + esqlite3 *conn; + esqlite3_backup *backup; esqlite_command *cmd = NULL; ErlNifPid pid; if(argc != 4) return enif_make_badarg(env); - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); // backup 1 if(!enif_is_ref(env, argv[2])) @@ -1455,6 +1465,7 @@ esqlite_backup_pagecount(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return push_command(env, conn, cmd); } + */ /* * Interrupt currently active query. @@ -1463,45 +1474,17 @@ esqlite_backup_pagecount(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM esqlite_interrupt(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - esqlite_connection *conn; + esqlite3 *conn; - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) return enif_make_badarg(env); - esqlite_connection *db = (esqlite_connection *) conn; + esqlite3 *db = (esqlite3 *) conn; sqlite3_interrupt(db->db); return enif_make_atom(env, "ok"); } -/* - * Close the database - */ -static ERL_NIF_TERM -esqlite_close(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) -{ - esqlite_connection *conn; - esqlite_command *cmd = NULL; - ErlNifPid pid; - - if(!enif_get_resource(env, argv[0], esqlite_connection_type, (void **) &conn)) - 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_close; - cmd->ref = enif_make_copy(cmd->env, argv[1]); - cmd->pid = pid; - - return push_command(env, conn, cmd); -} - /* * Load the nif. Initialize some stuff and such */ @@ -1510,25 +1493,26 @@ on_load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info) { ErlNifResourceType *rt; - rt = enif_open_resource_type(env, "esqlite3_nif", "esqlite_connection_type", destruct_esqlite_connection, + rt = enif_open_resource_type(env, "esqlite3_nif", "esqlite3_type", destruct_esqlite3, ERL_NIF_RT_CREATE, NULL); if(!rt) return -1; - esqlite_connection_type = rt; + esqlite3_type = rt; - rt = enif_open_resource_type(env, "esqlite3_nif", "esqlite_statement_type", destruct_esqlite_statement, + rt = enif_open_resource_type(env, "esqlite3_nif", "esqlite3_stmt_type", destruct_esqlite3_stmt, ERL_NIF_RT_CREATE, NULL); if(!rt) return -1; - esqlite_statement_type = rt; + esqlite3_stmt_type = rt; - rt = enif_open_resource_type(env, "esqlite3_nif", "esqlite_backup_type", destruct_esqlite_backup, + rt = enif_open_resource_type(env, "esqlite3_nif", "esqlite3_backup_type", destruct_esqlite3_backup, ERL_NIF_RT_CREATE, NULL); if(!rt) return -1; - esqlite_backup_type = rt; + esqlite3_backup_type = rt; atom_esqlite3 = make_atom(env, "esqlite3"); - if(SQLITE_OK != sqlite3_initialize()) + if(SQLITE_OK != sqlite3_initialize()) { return -1; + } return 0; } @@ -1544,11 +1528,18 @@ static int on_upgrade(ErlNifEnv* env, void** priv, void** old_priv_data, ERL_NIF } static ErlNifFunc nif_funcs[] = { - {"open", 4, esqlite_open, ERL_NIF_DIRTY_JOB_IO_BOUND}, + {"open", 1, esqlite_open, ERL_NIF_DIRTY_JOB_IO_BOUND}, + {"close", 1, esqlite_close, ERL_NIF_DIRTY_JOB_IO_BOUND}, + + {"prepare", 2, esqlite_prepare}, + + {"interrupt", 1, esqlite_interrupt, ERL_NIF_DIRTY_JOB_IO_BOUND} + + /* {"set_update_hook", 4, set_update_hook}, + {"exec", 4, esqlite_exec, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"changes", 3, esqlite_changes}, - {"prepare", 4, esqlite_prepare}, {"insert", 4, esqlite_insert}, {"last_insert_rowid", 3, esqlite_last_insert_rowid}, {"get_autocommit", 3, esqlite_get_autocommit}, @@ -1565,9 +1556,8 @@ static ErlNifFunc nif_funcs[] = { {"backup_remaining", 4, esqlite_backup_remaining}, {"backup_pagecount", 4, esqlite_backup_pagecount}, {"backup_finish", 4, esqlite_backup_finish}, + */ - {"interrupt", 1, esqlite_interrupt, ERL_NIF_DIRTY_JOB_IO_BOUND}, - {"close", 3, esqlite_close} }; ERL_NIF_INIT(esqlite3_nif, nif_funcs, on_load, on_reload, on_upgrade, NULL); diff --git a/c_src/queue.c b/c_src/queue.c deleted file mode 100644 index 685e9c8..0000000 --- a/c_src/queue.c +++ /dev/null @@ -1,195 +0,0 @@ -// This file is part of Emonk released under the MIT license. -// See the LICENSE file for more information. - -/* Adapted by: Maas-Maarten Zeeman -#include - -#include "queue.h" - -struct qitem_t -{ - struct qitem_t* next; - void* data; -}; - -typedef struct qitem_t qitem; - -struct queue_t -{ - ErlNifMutex *lock; - ErlNifCond *cond; - qitem *head; - qitem *tail; - void *message; - int length; -}; - -queue * -queue_create() -{ - queue *ret; - - ret = (queue *) enif_alloc(sizeof(struct queue_t)); - if(ret == NULL) goto error; - - ret->lock = NULL; - ret->cond = NULL; - ret->head = NULL; - ret->tail = NULL; - ret->message = NULL; - ret->length = 0; - - ret->lock = enif_mutex_create("queue_lock"); - if(ret->lock == NULL) goto error; - - ret->cond = enif_cond_create("queue_cond"); - if(ret->cond == NULL) goto error; - - return ret; - -error: - if(ret->lock != NULL) - enif_mutex_destroy(ret->lock); - if(ret->cond != NULL) - enif_cond_destroy(ret->cond); - if(ret != NULL) - enif_free(ret); - return NULL; -} - -void -queue_destroy(queue *queue) -{ - ErlNifMutex *lock; - ErlNifCond *cond; - int length; - - enif_mutex_lock(queue->lock); - lock = queue->lock; - cond = queue->cond; - length = queue->length; - - queue->lock = NULL; - queue->cond = NULL; - queue->head = NULL; - queue->tail = NULL; - queue->length = -1; - enif_mutex_unlock(lock); - - assert(length == 0 && "Attempting to destroy a non-empty queue."); - enif_cond_destroy(cond); - enif_mutex_destroy(lock); - enif_free(queue); -} - -int -queue_has_item(queue *queue) -{ - int ret; - - enif_mutex_lock(queue->lock); - ret = (queue->head != NULL); - enif_mutex_unlock(queue->lock); - - return ret; -} - -int -queue_push(queue *queue, void *item) -{ - qitem * entry = (qitem *) enif_alloc(sizeof(struct qitem_t)); - if(entry == NULL) - return 0; - - entry->data = item; - entry->next = NULL; - - enif_mutex_lock(queue->lock); - - assert(queue->length >= 0 && "Invalid queue size at push"); - - if(queue->tail != NULL) - queue->tail->next = entry; - - queue->tail = entry; - - if(queue->head == NULL) - queue->head = queue->tail; - - queue->length += 1; - - enif_cond_signal(queue->cond); - enif_mutex_unlock(queue->lock); - - return 1; -} - -void* -queue_pop(queue *queue) -{ - qitem *entry; - void* item; - - enif_mutex_lock(queue->lock); - - /* Wait for an item to become available. - */ - while(queue->head == NULL) - enif_cond_wait(queue->cond, queue->lock); - - assert(queue->length >= 0 && "Invalid queue size at pop."); - - /* Woke up because queue->head != NULL - * Remove the entry and return the payload. - */ - entry = queue->head; - queue->head = entry->next; - entry->next = NULL; - - if(queue->head == NULL) { - assert(queue->tail == entry && "Invalid queue state: Bad tail."); - queue->tail = NULL; - } - - queue->length -= 1; - - enif_mutex_unlock(queue->lock); - - item = entry->data; - enif_free(entry); - - return item; -} - -int -queue_send(queue *queue, void *item) -{ - enif_mutex_lock(queue->lock); - assert(queue->message == NULL && "Attempting to send multiple messages."); - queue->message = item; - enif_cond_signal(queue->cond); - enif_mutex_unlock(queue->lock); - return 1; -} - -void * -queue_receive(queue *queue) -{ - void *item; - - enif_mutex_lock(queue->lock); - - /* Wait for an item to become available. - */ - while(queue->message == NULL) - enif_cond_wait(queue->cond, queue->lock); - - item = queue->message; - queue->message = NULL; - - enif_mutex_unlock(queue->lock); - - return item; -} diff --git a/c_src/queue.h b/c_src/queue.h deleted file mode 100644 index 5ac597d..0000000 --- a/c_src/queue.h +++ /dev/null @@ -1,24 +0,0 @@ -// This file is part of Emonk released under the MIT license. -// See the LICENSE file for more information. - -/* adapted by: Maas-Maarten Zeeman sqlite type conversions @@ -81,7 +81,7 @@ -type row() :: tuple(). % tuple of cell_type -type cell_type() :: undefined | integer() | binary() | float(). --export_type([connection/0, statement/0, sql/0, row/0, rowid/0, cell_type/0]). +-export_type([esqlite3/0, esqlite3_stmt/0, sql/0, row/0, rowid/0, cell_type/0]). %% @doc Opens a sqlite3 database mentioned in Filename. %% @@ -98,388 +98,378 @@ %% ```open("file:memdb1?mode=memory&cache=shared")''' %% Opens a shared memory database named memdb1 with a shared cache. %% --spec open(string()) -> {ok, connection()} | {error, _}. +-spec open(Filename) -> OpenResult + when Filename :: string(), + OpenResult :: {ok, esqlite3()} | {error, _}. open(Filename) -> - open(Filename, ?DEFAULT_TIMEOUT). - -%% @doc Like open/1, but with an additional timeout. -%% --spec open(string(), timeout()) -> {ok, connection()} | {error, _}. -open(Filename) -> - Ref = make_ref(), case esqlite3_nif:open(Filename) of - {ok, RawConnection} -> - {ok, #connection{raw_connection=RawConnection}}; + {ok, Connection} -> + {ok, #esqlite3{db=Connection}}; {error, _Msg}=Error -> Error end. %% @doc Close the database --spec close(connection()) -> ok | {error, _}. -close(Connection) -> - close(Connection, ?DEFAULT_TIMEOUT). - -%% @doc Close the database --spec close(connection(), timeout()) -> ok | {error, _}. -close(#connection{raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:close(RawConnection, Ref, self()), - receive_answer(RawConnection, Ref, Timeout). +-spec close(Connection) -> CloseResult + when Connection :: esqlite3(), + CloseResult :: ok | {error, _}. +close(#esqlite3{db=Connection}) -> + esqlite3_nif:close(Connection). %% @doc Flush any stale answers left in the mailbox of the current process. %% This can happen if there has been a timeout. Normally the nif functions %% are called with the default 'infinite' timeout, so calling this is not %% needed. --spec flush() -> ok. -flush() -> - flush_answers(). - - -%% @doc Subscribe to database notifications. When rows are inserted deleted -%% or updates, the process will receive messages: -%% ```{insert, string(), rowid()}''' -%% When a new row has been inserted. -%% ```{delete, string(), rowid()}''' -%% When a new row has been deleted. -%% ```{update, string(), rowid()}''' -%% When a row has been updated. -%% --spec set_update_hook(pid(), connection()) -> ok | {error, term()}. -set_update_hook(Pid, Connection) -> - set_update_hook(Pid, Connection, ?DEFAULT_TIMEOUT). - -%% @doc Same as set_update_hook/2, but with an additional timeout parameter. -%% --spec set_update_hook(pid(), connection(), timeout()) -> ok | {error, term()}. -set_update_hook(Pid, #connection{raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:set_update_hook(RawConnection, Ref, self(), Pid), - receive_answer(RawConnection, Ref, Timeout). - -%% -%% q -%% - -%% @doc Execute a sql statement, returns a list with tuples. --spec q(sql(), connection()) -> list(row()) | {error, _}. -q(Sql, Connection) -> - q(Sql, [], Connection, ?DEFAULT_TIMEOUT). - -%% @doc Execute statement, bind args and return a list with tuples as result. --spec q(sql(), list(), connection()) -> list(row()) | {error, _}. -q(Sql, Args, Connection) -> - q(Sql, Args, Connection, ?DEFAULT_TIMEOUT). - -%% @doc Execute statement, bind args and return a list with tuples as result restricted by timeout. --spec q(sql(), list(), connection(), timeout()) -> list(row()) | {error, _}. -q(Sql, [], Connection, Timeout) -> - case prepare(Sql, Connection, Timeout) of - {ok, Statement} -> - fetchall(Statement, ?DEFAULT_CHUNK_SIZE, Timeout); - {error, _Msg}=Error -> - Error - end; -q(Sql, Args, Connection, Timeout) -> - case prepare(Sql, Connection, Timeout) of - {ok, Statement} -> - case bind(Statement, Args, Timeout) of - ok -> - fetchall(Statement, ?DEFAULT_CHUNK_SIZE, Timeout); - {error, _}=Error -> - Error - end; - {error, _Msg}=Error -> - Error - end. - -%% +%-spec flush() -> ok. +%flush() -> +% flush_answers(). +% +% +%%% @doc Subscribe to database notifications. When rows are inserted deleted +%%% or updates, the process will receive messages: +%%% ```{insert, string(), rowid()}''' +%%% When a new row has been inserted. +%%% ```{delete, string(), rowid()}''' +%%% When a new row has been deleted. +%%% ```{update, string(), rowid()}''' +%%% When a row has been updated. +%%% +%-spec set_update_hook(pid(), connection()) -> ok | {error, term()}. +%set_update_hook(Pid, Connection) -> +% set_update_hook(Pid, Connection, ?DEFAULT_TIMEOUT). +% +%%% @doc Same as set_update_hook/2, but with an additional timeout parameter. +%%% +%-spec set_update_hook(pid(), connection(), timeout()) -> ok | {error, term()}. +%set_update_hook(Pid, #connection{raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:set_update_hook(RawConnection, Ref, self(), Pid), +% receive_answer(RawConnection, Ref, Timeout). +% +%%% +%%% q +%%% +% +%%% @doc Execute a sql statement, returns a list with tuples. +%-spec q(sql(), connection()) -> list(row()) | {error, _}. +%q(Sql, Connection) -> +% q(Sql, [], Connection, ?DEFAULT_TIMEOUT). +% +%%% @doc Execute statement, bind args and return a list with tuples as result. +%-spec q(sql(), list(), connection()) -> list(row()) | {error, _}. +%%q(Sql, Args, Connection) -> +% q(Sql, Args, Connection, ?DEFAULT_TIMEOUT). +% +%%% @doc Execute statement, bind args and return a list with tuples as result restricted by timeout. +%-spec q(sql(), list(), connection(), timeout()) -> list(row()) | {error, _}. +%q(Sql, [], Connection, Timeout) -> +% case prepare(Sql, Connection, Timeout) of +% {ok, Statement} -> +% fetchall(Statement, ?DEFAULT_CHUNK_SIZE, Timeout); +% {error, _Msg}=Error -> +% Error +% end; +%q(Sql, Args, Connection, Timeout) -> +% case prepare(Sql, Connection, Timeout) of +% {ok, Statement} -> +% case bind(Statement, Args, Timeout) of +% ok -> +% fetchall(Statement, ?DEFAULT_CHUNK_SIZE, Timeout); +% {error, _}=Error -> +% Error +% end; +% {error, _Msg}=Error -> +% Error +% end. +% +%%% %% map -%% - -%% @doc Execute statement and return a list with the result of F for each row. --spec map(Fun, sql(), connection()) -> list(Type) when - Fun :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), - Row :: row(), - ColumnNames :: tuple(), - Type :: any(). -map(Fun, Sql, Connection) -> - case prepare(Sql, Connection) of - {ok, Statement} -> - map_s(Fun, Statement); - {error, _Msg}=Error -> - Error - end. - -%% @doc Execute statement, bind args and return a list with the result of F for each row. --spec map(F, sql(), list(), connection()) -> list(Type) when - F :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), - Row :: tuple(), - ColumnNames :: tuple(), - Type :: any(). -map(Fun, Sql, [], Connection) -> - map(Fun, Sql, Connection); -map(Fun, Sql, Args, Connection) -> - case prepare(Sql, Connection) of - {ok, Statement} -> - case bind(Statement, Args) of - ok -> - map_s(Fun, Statement); - {error, _}=Error -> - Error - end; - {error, _Msg}=Error -> - Error - end. +%%% +% +%%% @doc Execute statement and return a list with the result of F for each row. +%-spec map(Fun, sql(), connection()) -> list(Type) when +%% Fun :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), +% Row :: row(), +% ColumnNames :: tuple(), +% Type :: any(). +%map(Fun, Sql, Connection) -> +% case prepare(Sql, Connection) of +% {ok, Statement} -> +% map_s(Fun, Statement); +% {error, _Msg}=Error -> +% Error +% end. +% +%%% @doc Execute statement, bind args and return a list with the result of F for each row. +%-spec map(F, sql(), list(), connection()) -> list(Type) when +% F :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), +% Row :: tuple(), +% ColumnNames :: tuple(), +% Type :: any(). +%map(Fun, Sql, [], Connection) -> +% map(Fun, Sql, Connection); +%map(Fun, Sql, Args, Connection) -> +% case prepare(Sql, Connection) of +% {ok, Statement} -> +% case bind(Statement, Args) of +% ok -> +% map_s(Fun, Statement); +%% {error, _}=Error -> +% Error +% end; +% {error, _Msg}=Error -> +%% Error +% end. %% %% foreach %% %% @doc Execute statement and call F with each row. --spec foreach(Fun, sql(), connection()) -> ok when - Fun :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), - Row :: tuple(), - ColumnNames :: tuple(). -foreach(Fun, Sql, Connection) -> - case prepare(Sql, Connection) of - {ok, Statement} -> - foreach_s(Fun, Statement); - {error, _Msg}=Error -> - Error - end. +%-spec foreach(Fun, sql(), connection()) -> ok when +% Fun :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), +% Row :: tuple(), +% ColumnNames :: tuple(). +%foreach(Fun, Sql, Connection) -> +% case prepare(Sql, Connection) of +% {ok, Statement} -> +% foreach_s(Fun, Statement); +% {error, _Msg}=Error -> +% Error +% end. %% @doc Execute statement, bind args and call F with each row. --spec foreach(Fun, sql(), list(), connection()) -> ok when - Fun :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), - Row :: row(), - ColumnNames :: tuple(). -foreach(F, Sql, [], Connection) -> - foreach(F, Sql, Connection); -foreach(F, Sql, Args, Connection) -> - case prepare(Sql, Connection) of - {ok, Statement} -> - case bind(Statement, Args) of - ok -> - foreach_s(F, Statement); - {error, _Msg}=Error -> - Error - end; - {error, _Msg}=Error -> - Error - end. +%-spec foreach(Fun, sql(), list(), connection()) -> ok when +% Fun :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), +% Row :: row(), +% ColumnNames :: tuple(). +%foreach(F, Sql, [], Connection) -> +% foreach(F, Sql, Connection); +%foreach(F, Sql, Args, Connection) -> +% case prepare(Sql, Connection) of +% {ok, Statement} -> +% case bind(Statement, Args) of +%% ok -> +% foreach_s(F, Statement); +% {error, _Msg}=Error -> +% Error +% end; +% {error, _Msg}=Error -> +% Error +% end. %% %% fetchall %% %% --spec fetchone(statement()) -> tuple(). -fetchone(Statement) -> - case try_multi_step(Statement, 1, [], 0) of - {'$done', []} -> ok; - {error, _} = E -> E; - {rows, [Row | []]} -> Row - end. - -%% @doc Fetch all records -%% @param Statement is prepared sql statement --spec fetchall(statement()) -> list(row()) | {error, _}. -fetchall(Statement) -> - fetchall(Statement, ?DEFAULT_CHUNK_SIZE, ?DEFAULT_TIMEOUT). - +%-spec fetchone(statement()) -> tuple(). +%fetchone(Statement) -> +% case try_multi_step(Statement, 1, [], 0) of +% {'$done', []} -> ok; +% {error, _} = E -> E; +% {rows, [Row | []]} -> Row +% end. +% +%%% @doc Fetch all records +%%% @param Statement is prepared sql statement +%-spec fetchall(statement()) -> list(row()) | {error, _}. +%fetchall(Statement) -> +% fetchall(Statement, ?DEFAULT_CHUNK_SIZE, ?DEFAULT_TIMEOUT). +% %% @doc Fetch all records %% @param Statement is prepared sql statement %% @param ChunkSize is a count of rows to read from sqlite and send to erlang process in one bulk. %% Decrease this value if rows are heavy. Default value is 5000 (DEFAULT_CHUNK_SIZE). --spec fetchall(statement(), pos_integer()) -> list(row()) | {error, _}. -fetchall(Statement, ChunkSize) -> - fetchall(Statement, ChunkSize, ?DEFAULT_TIMEOUT). - -%% @doc Fetch all records -%% @param Statement is prepared sql statement +%-spec fetchall(statement(), pos_integer()) -> list(row()) | {error, _}. +%fetchall(Statement, ChunkSize) -> +% fetchall(Statement, ChunkSize, ?DEFAULT_TIMEOUT). +% +%%% @doc Fetch all records +%%% @param Statement is prepared sql statement %% @param ChunkSize is a count of rows to read from sqlite and send to erlang process in one bulk. %% Decrease this value if rows are heavy. Default value is 5000 (DEFAULT_CHUNK_SIZE). %% @param Timeout is timeout per each request of the one bulk --spec fetchall(statement(), pos_integer(), timeout()) -> list(row()) | {error, _}. -fetchall(Statement, ChunkSize, Timeout) -> - case fetchall_internal(Statement, ChunkSize, [], Timeout) of - {'$done', Rows} -> lists:reverse(Rows); - {error, _} = E -> E - end. +%-spec fetchall(statement(), pos_integer(), timeout()) -> list(row()) | {error, _}. +%fetchall(Statement, ChunkSize, Timeout) -> +% case fetchall_internal(Statement, ChunkSize, [], Timeout) of +% {'$done', Rows} -> lists:reverse(Rows); +% {error, _} = E -> E +% end. %% @doc Execute Sql statement. %% --spec exec(sql(), connection()) -> ok | {error, _}. -exec(Sql, Connection) -> - exec(Sql, [], Connection, ?DEFAULT_TIMEOUT). +%-spec exec(sql(), connection()) -> ok | {error, _}. +%exec(Sql, Connection) -> +% exec(Sql, [], Connection, ?DEFAULT_TIMEOUT). +% +%-spec exec(sql(), list(cell_type()) | connection(), connection() | timeout()) -> ok | {error, _}. +%exec(Sql, #connection{}=Connection, Timeout) -> +% exec(Sql, [], Connection, Timeout); +%exec(Sql, Params, #connection{}=Connection) -> +% exec(Sql, Params, Connection, ?DEFAULT_TIMEOUT). --spec exec(sql(), list(cell_type()) | connection(), connection() | timeout()) -> ok | {error, _}. -exec(Sql, #connection{}=Connection, Timeout) -> - exec(Sql, [], Connection, Timeout); -exec(Sql, Params, #connection{}=Connection) -> - exec(Sql, Params, Connection, ?DEFAULT_TIMEOUT). - --spec exec(sql(), list(cell_type()), connection(), timeout()) -> ok | {error, _}. -exec(Sql, [], #connection{raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:exec(RawConnection, Ref, self(), Sql), - receive_answer(RawConnection, Ref, Timeout); -exec(Sql, Params, Connection, Timeout) -> - {ok, Statement} = prepare(Sql, Connection, Timeout), - case bind(Statement, Params) of - ok -> - step(Statement, Timeout); - {error, _}=Error -> - Error - end. +%-spec exec(sql(), list(cell_type()), connection(), timeout()) -> ok | {error, _}. +%exec(Sql, [], #connection{raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:exec(RawConnection, Ref, self(), Sql), +% receive_answer(RawConnection, Ref, Timeout); +%exec(Sql, Params, Connection, Timeout) -> +% {ok, Statement} = prepare(Sql, Connection, Timeout), +% case bind(Statement, Params) of +% ok -> +% step(Statement, Timeout); +% {error, _}=Error -> +% Error +% end. %% @doc Return the number of affected rows of last statement. --spec changes(connection()) -> non_neg_integer(). -changes(Connection) -> - changes(Connection, ?DEFAULT_TIMEOUT). - --spec changes(connection(), timeout()) -> non_neg_integer(). -changes(#connection{raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:changes(RawConnection, Ref, self()), - receive_answer(RawConnection, Ref, Timeout). - -%% @doc Insert records, returns the last rowid. +%-spec changes(connection()) -> non_neg_integer(). +%changes(Connection) -> +% changes(Connection, ?DEFAULT_TIMEOUT). +% +%-spec changes(connection(), timeout()) -> non_neg_integer(). +%changes(#connection{raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:changes(RawConnection, Ref, self()), +% receive_answer(RawConnection, Ref, Timeout). +% +%%% @doc Insert records, returns the last rowid. %% --spec insert(sql(), connection()) -> {ok, rowid()} | {error, _}. -insert(Sql, Connection) -> - insert(Sql, Connection, ?DEFAULT_TIMEOUT). +%-spec insert(sql(), connection()) -> {ok, rowid()} | {error, _}. +%insert(Sql, Connection) -> +% insert(Sql, Connection, ?DEFAULT_TIMEOUT). %% @doc Like insert/2, but with extra timeout parameter. --spec insert(sql(), connection(), timeout()) -> {ok, rowid()} | {error, _}. -insert(Sql, #connection{raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:insert(RawConnection, Ref, self(), Sql), - receive_answer(RawConnection, Ref, Timeout). +%-spec insert(sql(), connection(), timeout()) -> {ok, rowid()} | {error, _}. +%insert(Sql, #connection{raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:insert(RawConnection, Ref, self(), Sql), +% receive_answer(RawConnection, Ref, Timeout). %% @doc Get the last insert rowid, using the default timeout. %% --spec last_insert_rowid(connection()) -> {ok, rowid()} | {error, _}. -last_insert_rowid(Connection) -> - last_insert_rowid(Connection, ?DEFAULT_TIMEOUT). +%-spec last_insert_rowid(connection()) -> {ok, rowid()} | {error, _}. +%last_insert_rowid(Connection) -> +% last_insert_rowid(Connection, ?DEFAULT_TIMEOUT). %% @doc Get the last insert rowid. %% --spec last_insert_rowid(connection(), timeout()) -> {ok, rowid()} | {error, _}. -last_insert_rowid(#connection{raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:last_insert_rowid(RawConnection, Ref, self()), - receive_answer(RawConnection, Ref, Timeout). +%-spec last_insert_rowid(connection(), timeout()) -> {ok, rowid()} | {error, _}. +%last_insert_rowid(#connection{raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:last_insert_rowid(RawConnection, Ref, self()), +% receive_answer(RawConnection, Ref, Timeout). %% @doc Check if the connection is in auto-commit mode. %% See: [https://sqlite.org/c3ref/get_autocommit.html] for more details. %% --spec get_autocommit(connection()) -> true | false. -get_autocommit(Connection) -> - get_autocommit(Connection, ?DEFAULT_TIMEOUT). +%-spec get_autocommit(connection()) -> true | false. +%get_autocommit(Connection) -> +% get_autocommit(Connection, ?DEFAULT_TIMEOUT). %% @doc Like autocommit/1, but with an extra timeout attribute. --spec get_autocommit(connection(), timeout()) -> true | false. -get_autocommit(#connection{raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:get_autocommit(RawConnection, Ref, self()), - receive_answer(RawConnection, Ref, Timeout). - +%-spec get_autocommit(connection(), timeout()) -> true | false. +%get_autocommit(#connection{raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:get_autocommit(RawConnection, Ref, self()), +% receive_answer(RawConnection, Ref, Timeout). +% %% @doc Compile a SQL statement. Returns a cached compiled statement which can be used in %% queries. %% --spec prepare(sql(), connection()) -> {ok, statement()} | {error, _}. -prepare(Sql, Connection) -> - prepare(Sql, Connection, ?DEFAULT_TIMEOUT). +%-spec prepare(sql(), connection()) -> {ok, statement()} | {error, _}. +%prepare(Sql, Connection) -> +% prepare(Sql, Connection, ?DEFAULT_TIMEOUT). %% @doc Like prepare/2, but with an extra timeout value. --spec prepare(sql(), connection(), timeout()) -> {ok, statement()} | {error, _}. -prepare(Sql, #connection{raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:prepare(RawConnection, Ref, self(), Sql), - case receive_answer(RawConnection, Ref, Timeout) of - {ok, Stmt} when is_reference(Stmt) -> - {ok, #statement{raw_statement=Stmt, raw_connection=RawConnection}}; - {error, _}=Error -> - Error - end. +%-spec prepare(sql(), connection(), timeout()) -> {ok, statement()} | {error, _}. +%prepare(Sql, #connection{raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:prepare(RawConnection, Ref, self(), Sql), +% case receive_answer(RawConnection, Ref, Timeout) of +% {ok, Stmt} when is_reference(Stmt) -> +% {ok, #statement{raw_statement=Stmt, raw_connection=RawConnection}}; +% {error, _}=Error -> +%% Error +% end. %% @doc Step %% --spec step(statement()) -> tuple() | '$busy' | '$done'. -step(Stmt) -> - step(Stmt, ?DEFAULT_TIMEOUT). - +%-spec step(statement()) -> tuple() | '$busy' | '$done'. +%step(Stmt) -> +% step(Stmt, ?DEFAULT_TIMEOUT). +% %% @doc %% --spec step(statement(), timeout()) -> tuple() | '$busy' | '$done'. -step(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:multi_step(RawConnection, RawStatement, 1, Ref, self()), - case receive_answer(RawConnection, Ref, Timeout) of - {rows, [Row | []]} -> {row, Row}; - {'$done', []} -> '$done'; - {'$busy', []} -> '$busy'; - Else -> Else - end. +%-spec step(statement(), timeout()) -> tuple() | '$busy' | '$done'. +%step(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:multi_step(RawConnection, RawStatement, 1, Ref, self()), +% case receive_answer(RawConnection, Ref, Timeout) of +% {rows, [Row | []]} -> {row, Row}; +% {'$done', []} -> '$done'; +% {'$busy', []} -> '$busy'; +% Else -> Else +% end. %% @doc Reset the prepared statement back to its initial state. %% --spec reset(statement()) -> ok | {error, _}. -reset(#statement{raw_statement=RawStatement, raw_connection=RawConnection}) -> - Ref = make_ref(), - ok = esqlite3_nif:reset(RawConnection, RawStatement, Ref, self()), - receive_answer(RawConnection, Ref, ?DEFAULT_TIMEOUT). +%-spec reset(statement()) -> ok | {error, _}. +%reset(#statement{raw_statement=RawStatement, raw_connection=RawConnection}) -> +% Ref = make_ref(), +% ok = esqlite3_nif:reset(RawConnection, RawStatement, Ref, self()), +% receive_answer(RawConnection, Ref, ?DEFAULT_TIMEOUT). %% @doc Bind values to prepared statements %% --spec bind(statement(), list(cell_type())) -> ok | {error, _}. -bind(Stmt, Args) -> - bind(Stmt, Args, ?DEFAULT_TIMEOUT). +%-spec bind(statement(), list(cell_type())) -> ok | {error, _}. +%bind(Stmt, Args) -> +% bind(Stmt, Args, ?DEFAULT_TIMEOUT). %% @doc Bind values to prepared statements --spec bind(statement(), list(cell_type()), timeout()) -> ok | {error, _}. -bind(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, Args, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:bind(RawConnection, RawStatement, Ref, self(), Args), - receive_answer(RawConnection, Ref, Timeout). - +%-spec bind(statement(), list(cell_type()), timeout()) -> ok | {error, _}. +%bind(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, Args, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:bind(RawConnection, RawStatement, Ref, self(), Args), +% receive_answer(RawConnection, Ref, Timeout). +% %% @doc Return the column names of the prepared statement. %% --spec column_names(statement()) -> {atom()}. -column_names(Stmt) -> - column_names(Stmt, ?DEFAULT_TIMEOUT). +%-spec column_names(statement()) -> {atom()}. +%column_names(Stmt) -> +% column_names(Stmt, ?DEFAULT_TIMEOUT). --spec column_names(statement(), timeout()) -> {atom()}. -column_names(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:column_names(RawConnection, RawStatement, Ref, self()), - receive_answer(RawConnection, Ref, Timeout). +%-spec column_names(statement(), timeout()) -> {atom()}. +%column_names(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:column_names(RawConnection, RawStatement, Ref, self()), +% receive_answer(RawConnection, Ref, Timeout). %% @doc Return the column types of the prepared statement. %% --spec column_types(statement()) -> {atom()}. -column_types(Statement) -> - column_types(Statement, ?DEFAULT_TIMEOUT). +%-spec column_types(statement()) -> {atom()}. +%column_types(Statement) -> +% column_types(Statement, ?DEFAULT_TIMEOUT). --spec column_types(statement(), timeout()) -> {atom()}. -column_types(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:column_types(RawConnection, RawStatement, Ref, self()), - receive_answer(RawConnection, Ref, Timeout). +%-spec column_types(statement(), timeout()) -> {atom()}. +%column_types(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:column_types(RawConnection, RawStatement, Ref, self()), +% receive_answer(RawConnection, Ref, Timeout). %% @doc make multiple sqlite steps per call return rows in reverse order %% --spec multi_step(term(), pos_integer(), timeout()) -> - {rows, list(tuple())} | - {'$busy', list(tuple())} | - {'$done', list(tuple())} | - {error, _}. -multi_step(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, ChunkSize, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:multi_step(RawConnection, RawStatement, ChunkSize, Ref, self()), - receive_answer(RawConnection, Ref, Timeout). +%-spec multi_step(term(), pos_integer(), timeout()) -> +% {rows, list(tuple())} | +% {'$busy', list(tuple())} | +% {'$done', list(tuple())} | +% {error, _}. +%multi_step(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, ChunkSize, Timeout) -> +% Ref = make_ref(), +%% ok = esqlite3_nif:multi_step(RawConnection, RawStatement, ChunkSize, Ref, self()), +% receive_answer(RawConnection, Ref, Timeout). %% %% Backup API @@ -487,185 +477,185 @@ multi_step(#statement{raw_statement=RawStatement, raw_connection=RawConnection}, % @doc Initialize a backup procedure. %% --spec backup_init(connection(), string(), connection(), string()) -> {ok, backup()} | {error, _}. -backup_init(Dest, DestName, Src, SrcName) -> - backup_init(Dest, DestName, Src, SrcName, ?DEFAULT_TIMEOUT). - +%-spec backup_init(connection(), string(), connection(), string()) -> {ok, backup()} | {error, _}. +%backup_init(Dest, DestName, Src, SrcName) -> +% backup_init(Dest, DestName, Src, SrcName, ?DEFAULT_TIMEOUT). +% %% @doc Like backup_init/4, but with an extra timeout value. %% --spec backup_init(connection(), string(), connection(), string(), timeout()) -> {ok, backup()} | {error, _}. -backup_init(#connection{raw_connection=Dest}, DestName, #connection{raw_connection=Src}, SrcName, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:backup_init(Dest, DestName, Src, SrcName, Ref, self()), - case receive_answer(Dest, Ref, Timeout) of - {ok, RawBackup} when is_reference(RawBackup) -> - {ok, #backup{raw_connection=Dest, raw_backup=RawBackup}}; - {error, _} = Error -> - Error - end. +%-spec backup_init(connection(), string(), connection(), string(), timeout()) -> {ok, backup()} | {error, _}. +%backup_init(#connection{raw_connection=Dest}, DestName, #connection{raw_connection=Src}, SrcName, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:backup_init(Dest, DestName, Src, SrcName, Ref, self()), +% case receive_answer(Dest, Ref, Timeout) of +% {ok, RawBackup} when is_reference(RawBackup) -> +% {ok, #backup{raw_connection=Dest, raw_backup=RawBackup}}; +% {error, _} = Error -> +% Error +% end. %% @doc Release the resources held by the backup. --spec backup_finish(backup()) -> ok | {error, _}. -backup_finish(Backup) -> - backup_finish(Backup, ?DEFAULT_TIMEOUT). -%% @doc Like backup_finish/1, but with an extra timeout. --spec backup_finish(backup(), timeout()) -> ok | {error, _}. -backup_finish(#backup{raw_connection=Conn, raw_backup=Back}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:backup_finish(Conn, Back, Ref, self()), - receive_answer(Conn, Ref, Timeout). +%-spec backup_finish(backup()) -> ok | {error, _}. +%backup_finish(Backup) -> +% backup_finish(Backup, ?DEFAULT_TIMEOUT). +%%% @doc Like backup_finish/1, but with an extra timeout. +%-spec backup_finish(backup(), timeout()) -> ok | {error, _}. +%backup_finish(#backup{raw_connection=Conn, raw_backup=Back}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:backup_finish(Conn, Back, Ref, self()), +% receive_answer(Conn, Ref, Timeout). %% @doc Do a backup step. --spec backup_step(backup(), integer()) -> ok | {error, _}. -backup_step(Backup, NPage) -> - backup_step(Backup, NPage, ?DEFAULT_TIMEOUT). +%-spec backup_step(backup(), integer()) -> ok | {error, _}. +%backup_step(Backup, NPage) -> +% backup_step(Backup, NPage, ?DEFAULT_TIMEOUT). %% @doc Do a backup step. --spec backup_step(backup(), integer(), timeout()) -> ok | {error, _}. -backup_step(#backup{raw_connection=Conn, raw_backup=Back}, NPage, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:backup_step(Conn, Back, NPage, Ref, self()), - receive_answer(Conn, Ref, Timeout). +%-spec backup_step(backup(), integer(), timeout()) -> ok | {error, _}. +%backup_step(#backup{raw_connection=Conn, raw_backup=Back}, NPage, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:backup_step(Conn, Back, NPage, Ref, self()), +% receive_answer(Conn, Ref, Timeout). %% @doc Get the remaining number of pages which need to be backed up. --spec backup_remaining(backup()) -> {ok, pos_integer()} | {error, _}. -backup_remaining(Backup) -> - backup_remaining(Backup, ?DEFAULT_TIMEOUT). +%-spec backup_remaining(backup()) -> {ok, pos_integer()} | {error, _}. +%backup_remaining(Backup) -> +% backup_remaining(Backup, ?DEFAULT_TIMEOUT). %% @doc Get the remaining number of pages which need to be backed up. --spec backup_remaining(backup(), timeout()) -> {ok, pos_integer()} | {error, _}. -backup_remaining(#backup{raw_connection=Conn, raw_backup=Back}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:backup_remaining(Conn, Back, Ref, self()), - case receive_answer(Conn, Ref, Timeout) of - {ok, R} when is_integer(R) -> - {ok, R}; - {error, _}=E -> - E - end. - +%-spec backup_remaining(backup(), timeout()) -> {ok, pos_integer()} | {error, _}. +%backup_remaining(#backup{raw_connection=Conn, raw_backup=Back}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:backup_remaining(Conn, Back, Ref, self()), +% case receive_answer(Conn, Ref, Timeout) of +% {ok, R} when is_integer(R) -> +% {ok, R}; +% {error, _}=E -> +% E +% end. +%% %% @doc Get the remaining number of pages which need to be backed up. --spec backup_pagecount(backup()) -> {ok, pos_integer()} | {error, _}. -backup_pagecount(Backup) -> - backup_pagecount(Backup, ?DEFAULT_TIMEOUT). - +%-spec backup_pagecount(backup()) -> {ok, pos_integer()} | {error, _}. +%backup_pagecount(Backup) -> +% backup_pagecount(Backup, ?DEFAULT_TIMEOUT). +% %% @doc Get the remaining number of pages which need to be backed up. --spec backup_pagecount(backup(), timeout()) -> {ok, pos_integer()} | {error, _}. -backup_pagecount(#backup{raw_connection=Conn, raw_backup=Back}, Timeout) -> - Ref = make_ref(), - ok = esqlite3_nif:backup_pagecount(Conn, Back, Ref, self()), - case receive_answer(Conn, Ref, Timeout) of - {ok, R} when is_integer(R) -> - {ok, R}; - {error, _}=E -> - E - end. +%-spec backup_pagecount(backup(), timeout()) -> {ok, pos_integer()} | {error, _}. +%backup_pagecount(#backup{raw_connection=Conn, raw_backup=Back}, Timeout) -> +% Ref = make_ref(), +% ok = esqlite3_nif:backup_pagecount(Conn, Back, Ref, self()), +% case receive_answer(Conn, Ref, Timeout) of +% {ok, R} when is_integer(R) -> +% {ok, R}; +% {error, _}=E -> +% E +% end. %% %% Helpers %% --spec foreach_s(Fun, statement()) -> ok when - Fun :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), - Row :: row(), - ColumnNames :: tuple(). -foreach_s(Fun, Statement) when is_function(Fun, 1) -> - case try_multi_step(Statement, 1, [], 0) of - {'$done', []} -> - ok; - {error, _} = Error -> - Error; - {rows, [Row | []]} -> - Fun(Row), - foreach_s(Fun, Statement) - end; -foreach_s(Fun, Statement) when is_function(Fun, 2) -> - ColumnNames = column_names(Statement), - case try_multi_step(Statement, 1, [], 0) of - {'$done', []} -> - ok; - {error, _} = Error -> - Error; - {rows, [Row | []]} -> - Fun(ColumnNames, Row), - foreach_s(Fun, Statement) - end. +%-spec foreach_s(Fun, statement()) -> ok when +% Fun :: fun((Row) -> any()) | fun((ColumnNames, Row) -> any()), +% Row :: row(), +% ColumnNames :: tuple(). +%foreach_s(Fun, Statement) when is_function(Fun, 1) -> +% case try_multi_step(Statement, 1, [], 0) of +% {'$done', []} -> +%% ok; +% {error, _} = Error -> +% Error; +% {rows, [Row | []]} -> +% Fun(Row), +% foreach_s(Fun, Statement) +% end; +%foreach_s(Fun, Statement) when is_function(Fun, 2) -> +% ColumnNames = column_names(Statement), +% case try_multi_step(Statement, 1, [], 0) of +% {'$done', []} -> +% ok; +% {error, _} = Error -> +% Error; +% {rows, [Row | []]} -> +% Fun(ColumnNames, Row), +% foreach_s(Fun, Statement) +% end. --spec map_s(Fun, statement()) -> list(Type) when - Fun :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), - Row :: row(), - ColumnNames :: tuple(), - Type :: term(). -map_s(Fun, Statement) when is_function(Fun, 1) -> - case try_multi_step(Statement, 1, [], 0) of - {'$done', []} -> - []; - {error, _} = Error -> - Error; - {rows, [Row | []]} -> - [Fun(Row) | map_s(Fun, Statement)] - end; -map_s(Fun, Statement) when is_function(Fun, 2) -> - ColumnNames = column_names(Statement), - case try_multi_step(Statement, 1, [], 0) of - {'$done', []} -> - []; - {error, _} = Error -> - Error; - {rows, [Row | []]} -> - [Fun(ColumnNames, Row) | map_s(Fun, Statement)] - end. +%-spec map_s(Fun, statement()) -> list(Type) when +%% Fun :: fun((Row) -> Type) | fun((ColumnNames, Row) -> Type), +% Row :: row(), +% ColumnNames :: tuple(), +% Type :: term(). +%map_s(Fun, Statement) when is_function(Fun, 1) -> +% case try_multi_step(Statement, 1, [], 0) of +% {'$done', []} -> +% []; +% {error, _} = Error -> +% Error; +% {rows, [Row | []]} -> +% [Fun(Row) | map_s(Fun, Statement)] +% end; +%map_s(Fun, Statement) when is_function(Fun, 2) -> +% ColumnNames = column_names(Statement), +% case try_multi_step(Statement, 1, [], 0) of +% {'$done', []} -> +% []; +% {error, _} = Error -> +% Error; +% {rows, [Row | []]} -> +% [Fun(ColumnNames, Row) | map_s(Fun, Statement)] +% end. %% return rows in reverse order --spec fetchall_internal(statement(), pos_integer(), list(row()), timeout()) -> - {'$done', list(row())} | - {error, _}. -fetchall_internal(Statement, ChunkSize, Rest, Timeout) -> - case try_multi_step(Statement, ChunkSize, Rest, 0, Timeout) of - {rows, Rows} -> fetchall_internal(Statement, ChunkSize, Rows, Timeout); - Else -> Else - end. +%-spec fetchall_internal(statement(), pos_integer(), list(row()), timeout()) -> +% {'$done', list(row())} | +% {error, _}. +%fetchall_internal(Statement, ChunkSize, Rest, Timeout) -> +% case try_multi_step(Statement, ChunkSize, Rest, 0, Timeout) of +% {rows, Rows} -> fetchall_internal(Statement, ChunkSize, Rows, Timeout); +% Else -> Else +% end. + +%% Try a number of steps, when the database is busy, +%%% return rows in revers order +%try_multi_step(Statement, ChunkSize, Rest, Tries) -> +% try_multi_step(Statement, ChunkSize, Rest, Tries, ?DEFAULT_TIMEOUT). %% Try a number of steps, when the database is busy, %% return rows in revers order -try_multi_step(Statement, ChunkSize, Rest, Tries) -> - try_multi_step(Statement, ChunkSize, Rest, Tries, ?DEFAULT_TIMEOUT). +%-spec try_multi_step(statement(), pos_integer(), list(tuple()), non_neg_integer(), timeout()) -> +% {rows, list(tuple())} | +% {'$done', list(tuple())} | +% {error, term()}. +%try_multi_step(_Statement, _ChunkSize, _Rest, Tries, _Timeout) when Tries > 5 -> +% throw(too_many_tries); +%try_multi_step(Statement, ChunkSize, Rest, Tries, Timeout) -> +% case multi_step(Statement, ChunkSize, Timeout) of +% {'$busy', Rows} -> %% core can fetch a number of rows (rows < ChunkSize) per 'multi_step' call and then get busy... +% erlang:display({"busy", Tries}), +% timer:sleep(100 * Tries), +% try_multi_step(Statement, ChunkSize, Rows ++ Rest, Tries + 1, Timeout); +% {rows, Rows} -> +% {rows, Rows ++ Rest}; +% {'$done', Rows} -> +% {'$done', Rows ++ Rest}; +% Else -> Else +% end. -%% Try a number of steps, when the database is busy, -%% return rows in revers order --spec try_multi_step(statement(), pos_integer(), list(tuple()), non_neg_integer(), timeout()) -> - {rows, list(tuple())} | - {'$done', list(tuple())} | - {error, term()}. -try_multi_step(_Statement, _ChunkSize, _Rest, Tries, _Timeout) when Tries > 5 -> - throw(too_many_tries); -try_multi_step(Statement, ChunkSize, Rest, Tries, Timeout) -> - case multi_step(Statement, ChunkSize, Timeout) of - {'$busy', Rows} -> %% core can fetch a number of rows (rows < ChunkSize) per 'multi_step' call and then get busy... - erlang:display({"busy", Tries}), - timer:sleep(100 * Tries), - try_multi_step(Statement, ChunkSize, Rows ++ Rest, Tries + 1, Timeout); - {rows, Rows} -> - {rows, Rows ++ Rest}; - {'$done', Rows} -> - {'$done', Rows ++ Rest}; - Else -> Else - end. +%receive_answer(RawConnection, Ref, Timeout) -> +% receive +% {esqlite3, Ref, Resp} -> Resp +% after +% Timeout -> +% ok = esqlite3_nif:interrupt(RawConnection), +% throw({error, timeout, Ref}) +% end. -receive_answer(RawConnection, Ref, Timeout) -> - receive - {esqlite3, Ref, Resp} -> Resp - after - Timeout -> - ok = esqlite3_nif:interrupt(RawConnection), - throw({error, timeout, Ref}) - end. - -flush_answers() -> - receive - {esqlite3, _, _} -> flush_answers() - after - 0 -> ok - end. +%flush_answers() -> +% receive +% {esqlite3, _, _} -> flush_answers() +% after +% 0 -> ok +% end. diff --git a/src/esqlite3_nif.erl b/src/esqlite3_nif.erl index dbd0b81..74d2b37 100644 --- a/src/esqlite3_nif.erl +++ b/src/esqlite3_nif.erl @@ -21,34 +21,38 @@ %% low-level exports -export([ open/1, - set_update_hook/4, - exec/4, - changes/3, - insert/4, - last_insert_rowid/3, - get_autocommit/3, - prepare/4, - multi_step/5, - reset/4, - finalize/4, - bind/5, - column_names/4, - column_types/4, - backup_init/6, - backup_step/5, - backup_remaining/4, - backup_pagecount/4, - backup_finish/4, - interrupt/1, - close/3 + close/1, + prepare/2, + + interrupt/1 +% set_update_hook/4, +% exec/4, +% changes/3, +% insert/4, +% last_insert_rowid/3, +% get_autocommit/3, +% multi_step/5, +% reset/4, +% finalize/4, +% bind/5, + +% column_names/4, +% column_types/4, + +% backup_init/6, +% backup_step/5, +% backup_remaining/4, +% backup_pagecount/4, +% backup_finish/4, ]). --type raw_connection() :: reference(). --type raw_statement() :: reference(). --type raw_backup() :: reference(). +-type esqlite3() :: reference(). +-type esqlite3_stmt() :: reference(). +%-type esqlite3_backup() :: reference(). -type sql() :: iodata(). --export_type([raw_connection/0, raw_statement/0, raw_backup/0, sql/0]). +-export_type([esqlite3/0, esqlite3_stmt/0, sql/0]). +%-export_type([esqlite3_backup/0]). -on_load(init/0). @@ -64,15 +68,32 @@ init() -> %% @doc Open the specified sqlite3 database. %% -spec open(Filename) -> OpenResult - when Filename :: string() - OpenResult :: {ok, ref()} | {error, _}. + when Filename :: string(), + OpenResult :: {ok, esqlite3()} | {error, _}. open(_Filename) -> erlang:nif_error(nif_library_not_loaded). --spec set_update_hook(reference(), pid(), pid()) -> ok | {error, _}. -set_update_hook(_Db, _Ref, _Dest, _Pid) -> +%% @doc Close the connection. +%% +-spec close(Connection) -> CloseResult + when Connection :: esqlite3(), + CloseResult :: ok | {error, _}. +close(_Db) -> erlang:nif_error(nif_library_not_loaded). +%% @doc Compile a sql statement. +%% +-spec prepare(Connection, Sql) -> PrepareResult + when Connection :: esqlite3(), + Sql :: sql(), + PrepareResult :: {ok, esqlite3_stmt()} | {error, _}. +prepare(_Connection, _Sql) -> + erlang:nif_error(nif_library_not_loaded). + +% -spec set_update_hook((), pid(), pid()) -> ok | {error, _}. +%set_update_hook(_Db, _Ref, _Dest, _Pid) -> +% erlang:nif_error(nif_library_not_loaded). + %% @doc Exec the query. %% %% Sends an asynchronous exec command over the connection and returns @@ -81,111 +102,99 @@ set_update_hook(_Db, _Ref, _Dest, _Pid) -> %% When the statement is executed Dest will receive message {Ref, answer()} %% with answer() integer | {error, reason()} %% --spec exec(raw_connection(), reference(), pid(), sql()) -> ok | {error, _}. -exec(_Db, _Ref, _Dest, _Sql) -> - erlang:nif_error(nif_library_not_loaded). +%-spec exec(esqlite3(), reference(), pid(), sql()) -> ok | {error, _}. +%%exec(_Db, _Ref, _Dest, _Sql) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Get the number of affected rows of last statement %% %% When the statement is executed Dest will receive message {Ref, answer()} %% with answer() integer | {error, reason()} --spec changes(raw_connection(), reference(), pid()) -> ok | {error, _}. -changes(_Db, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec changes(esqlite3(), reference(), pid()) -> ok | {error, _}. +%changes(_Db, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc %% --spec prepare(raw_connection(), reference(), pid(), sql()) -> ok | {error, _}. -prepare(_Db, _Ref, _Dest, _Sql) -> - erlang:nif_error(nif_library_not_loaded). +%-spec multi_step(esqlite3(), esqlite3_stmt(), pos_integer(), reference(), pid()) -> ok | {error, _}. +%multi_step(_Db, _Stmt, _Chunk_Size, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc %% --spec multi_step(raw_connection(), raw_statement(), pos_integer(), reference(), pid()) -> ok | {error, _}. -multi_step(_Db, _Stmt, _Chunk_Size, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec reset(esqlite3(), esqlite3_stmt(), reference(), pid()) -> ok | {error, _}. +%reset(_Db, _Stmt, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc %% --spec reset(raw_connection(), raw_statement(), reference(), pid()) -> ok | {error, _}. -reset(_Db, _Stmt, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). - -%% @doc -%% --spec finalize(raw_connection(), raw_statement(), reference(), pid()) -> ok | {error, _}. -finalize(_Db, _Stmt, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec finalize(esqlite3(), esqlite3_stmt(), reference(), pid()) -> ok | {error, _}. +%finalize(_Db, _Stmt, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Bind parameters to a prepared statement. %% --spec bind(raw_connection(), raw_statement(), reference(), pid(), list(any())) -> ok | {error, _}. -bind(_Db, _Stmt, _Ref, _Dest, _Args) -> - erlang:nif_error(nif_library_not_loaded). +%-spec bind(esqlite3(), esqlite3_stmt(), reference(), pid(), list(any())) -> ok | {error, _}. +%bind(_Db, _Stmt, _Ref, _Dest, _Args) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Retrieve the column names of the prepared statement %% --spec column_names(raw_connection(), raw_statement(), reference(), pid()) -> ok | {error, _}. -column_names(_Db, _Stmt, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec column_names(esqlite3(), esqlite3_stmt(), reference(), pid()) -> ok | {error, _}. +%column_names(_Db, _Stmt, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Retrieve the column types of the prepared statement %% --spec column_types(raw_connection(), raw_statement(), reference(), pid()) -> ok | {error, _}. -column_types(_Db, _Stmt, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec column_types(esqlite3(), esqlite3_stmt(), reference(), pid()) -> ok | {error, _}. +%column_types(_Db, _Stmt, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Initialize a backup procedure of a database. --spec backup_init(raw_connection(), string(), raw_connection(), string(), reference(), pid()) -> ok | {error, _}. -backup_init(_DestDb, _DestName, _SourceDb, _SourceName, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec backup_init(esqlite3(), string(), esqlite3_stmt(), string(), reference(), pid()) -> ok | {error, _}. +%backup_init(_DestDb, _DestName, _SourceDb, _SourceName, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Do a backup step. --spec backup_step(raw_connection(), raw_backup(), integer(), reference(), pid()) -> ok | {error, _}. -backup_step(_Db, _Backup, _NPages, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec backup_step(esqlite3(), esqlite3_backup(), integer(), reference(), pid()) -> ok | {error, _}. +%backup_step(_Db, _Backup, _NPages, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Get the amount of remaining pages which need to be backed up. --spec backup_remaining(raw_connection(), raw_backup(), reference(), pid()) -> ok | {error, _}. -backup_remaining(_Db, _Backup, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec backup_remaining(esqlite3(), esqlite3_backup(), reference(), pid()) -> ok | {error, _}. +%backup_remaining(_Db, _Backup, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Get the total number of pages which need to be backed up. --spec backup_pagecount(raw_connection(), raw_backup(), reference(), pid()) -> ok | {error, _}. -backup_pagecount(_Db, _Backup, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec backup_pagecount(esqlite3(), esqlite3_backup(), reference(), pid()) -> ok | {error, _}. +%backup_pagecount(_Db, _Backup, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Finish the backup. --spec backup_finish(raw_connection(), raw_backup(), reference(), pid()) -> ok | {error, _}. -backup_finish(_Db, _Backup, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec backup_finish(esqlite3(), esqlite3_backup(), reference(), pid()) -> ok | {error, _}. +%backup_finish(_Db, _Backup, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Interrupt all active queries. --spec interrupt(raw_connection()) -> ok. +-spec interrupt(esqlite3()) -> ok. interrupt(_Db) -> erlang:nif_error(nif_library_not_loaded). -%% @doc Close the connection. -%% --spec close(raw_connection(), reference(), pid()) -> ok | {error, _}. -close(_Db, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). - %% @doc Insert record %% --spec insert(raw_connection(), reference(), pid(), sql()) -> ok | {error, _}. -insert(_Db, _Ref, _Dest, _Sql) -> - erlang:nif_error(nif_library_not_loaded). +%-spec insert(esqlite3(), reference(), pid(), sql()) -> ok | {error, _}. +%insert(_Db, _Ref, _Dest, _Sql) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Get the last insert rowid. %% --spec last_insert_rowid(raw_connection(), reference(), pid()) -> ok | {error, _}. -last_insert_rowid(_Db, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec last_insert_rowid(esqlite3(), reference(), pid()) -> ok | {error, _}. +%last_insert_rowid(_Db, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded). %% @doc Get automcommit %% --spec get_autocommit(raw_connection(), reference(), pid()) -> ok | {error, _}. -get_autocommit(_Db, _Ref, _Dest) -> - erlang:nif_error(nif_library_not_loaded). +%-spec get_autocommit(esqlite3(), reference(), pid()) -> ok | {error, _}. +%get_autocommit(_Db, _Ref, _Dest) -> +% erlang:nif_error(nif_library_not_loaded).