static ERL_NIF_TERM do_bind(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TERM arg) { int parameter_count = sqlite3_bind_parameter_count(stmt); int i, is_list, r; ERL_NIF_TERM list, head, tail; unsigned int list_length; is_list = enif_get_list_length(env, arg, &list_length); if(!is_list) return make_error_tuple(env, "bad_arg_list"); if(parameter_count != list_length) return make_error_tuple(env, "args_wrong_length"); sqlite3_reset(stmt); list = arg; for(i=0; i < list_length; i++) { enif_get_list_cell(env, list, &head, &tail); r = bind_cell(env, head, stmt, i+1); if(r == -1) return make_error_tuple(env, "wrong_type"); if(r != SQLITE_OK) return make_sqlite3_error_tuple(env, r, db); list = tail; } return make_atom(env, "ok"); }
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(db->db); db->db = NULL; return error; } return make_atom(env, "ok"); }
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; enif_inspect_iolist_as_binary(env, arg, &bin); 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) return make_sqlite3_error_tuple(env, rc, conn->db); enif_keep_resource(conn); stmt->connection = conn; esqlite_stmt = enif_make_resource(env, stmt); enif_release_resource(stmt); return make_ok_tuple(env, esqlite_stmt); }
static ERL_NIF_TERM do_reset(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt) { int rc = sqlite3_reset(stmt); if(rc == SQLITE_OK) return make_atom(env, "ok"); return make_sqlite3_error_tuple(env, rc, db); }
static ERL_NIF_TERM do_close(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) { int rc; rc = sqlite3_close(conn->db); if(rc != SQLITE_OK) return make_sqlite3_error_tuple(env, rc, conn->db); conn->db = NULL; return make_atom(env, "ok"); }
static ERL_NIF_TERM do_exec(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) { ErlNifBinary bin; int rc; enif_inspect_iolist_as_binary(env, arg, &bin); rc = sqlite3_exec(conn->db, (char *) bin.data, NULL, NULL, NULL); if(rc != SQLITE_OK) return make_sqlite3_error_tuple(env, rc, conn->db); return make_atom(env, "ok"); }
static ERL_NIF_TERM do_multi_step(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt, const ERL_NIF_TERM arg) { ERL_NIF_TERM status; ERL_NIF_TERM rows = enif_make_list_from_array(env, NULL, 0); ERL_NIF_TERM *rowBuffer = NULL; int rowBufferSize = 0; int chunk_size = 0; enif_get_int(env, arg, &chunk_size); int rc = sqlite3_step(stmt); while (rc == SQLITE_ROW && chunk_size-- > 0) { if (!rowBufferSize) rowBufferSize = sqlite3_column_count(stmt); if (rowBuffer == NULL) rowBuffer = (ERL_NIF_TERM *) enif_alloc(sizeof(ERL_NIF_TERM)*rowBufferSize); rows = enif_make_list_cell(env, make_row(env, stmt, rowBuffer, rowBufferSize), rows); if (chunk_size > 0) rc = sqlite3_step(stmt); } switch(rc) { case SQLITE_ROW: status = make_atom(env, "rows"); break; case SQLITE_BUSY: 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. */ sqlite3_reset(stmt); status = make_atom(env, "$done"); break; default: /* 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); }
/* * insert action */ static ERL_NIF_TERM do_insert(ErlNifEnv *env, esqlite_connection *conn, const ERL_NIF_TERM arg) { ErlNifBinary bin; int rc; ERL_NIF_TERM eos = enif_make_int(env, 0); enif_inspect_iolist_as_binary(env, enif_make_list2(env, arg, eos), &bin); rc = sqlite3_exec(conn->db, (char *) bin.data, NULL, NULL, NULL); if(rc != SQLITE_OK) return make_sqlite3_error_tuple(env, rc, conn->db); sqlite3_int64 last_rowid = sqlite3_last_insert_rowid(conn->db); ERL_NIF_TERM last_rowid_term = enif_make_int64(env, last_rowid); return make_ok_tuple(env, last_rowid_term); }
static ERL_NIF_TERM do_step(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt) { int rc = sqlite3_step(stmt); if(rc == SQLITE_ROW) return make_row(env, stmt); if(rc == SQLITE_DONE) return make_atom(env, "$done"); if(rc == SQLITE_BUSY) return make_atom(env, "$busy"); if(rc == SQLITE_ERROR) return make_sqlite3_error_tuple(env, rc, db); if(rc == SQLITE_MISUSE) return make_error_tuple(env, "misuse"); return make_error_tuple(env, "unexpected_return_value"); }
static ERL_NIF_TERM do_step(ErlNifEnv *env, sqlite3 *db, sqlite3_stmt *stmt) { int rc = sqlite3_step(stmt); if(rc == SQLITE_ROW) return make_row(env, stmt); if(rc == SQLITE_BUSY) return make_atom(env, "$busy"); if(rc == 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. */ sqlite3_reset(stmt); return make_atom(env, "$done"); } /* We use prepare_v2, so any error code can be returned. */ return make_sqlite3_error_tuple(env, rc, db); }