From 71dbc8faafde68fac1267ee1c3bd0a1e4be0494d Mon Sep 17 00:00:00 2001 From: Maas-Maarten Zeeman Date: Sat, 21 May 2022 13:54:35 +0200 Subject: [PATCH] Removed outdated comments --- c_src/esqlite3_nif.c | 119 ++++++++++++++++++++++++++++++++++---- src/esqlite3.erl | 133 +++++++++++-------------------------------- src/esqlite3_nif.erl | 32 ++++++++--- 3 files changed, 166 insertions(+), 118 deletions(-) diff --git a/c_src/esqlite3_nif.c b/c_src/esqlite3_nif.c index 9249312..f0ba610 100644 --- a/c_src/esqlite3_nif.c +++ b/c_src/esqlite3_nif.c @@ -1412,6 +1412,38 @@ esqlite_bind_double(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return make_atom(env, "ok"); } +static ERL_NIF_TERM +esqlite_bind_null(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + esqlite3_stmt *stmt; + int index; + double value; + + if(argc != 2) { + return enif_make_badarg(env); + } + + if(!enif_get_resource(env, argv[0], esqlite3_stmt_type, (void **) &stmt)) { + return enif_make_badarg(env); + } + + if(!stmt->statement) { + return enif_raise_exception(env, make_atom(env, "no_prepared_statement")); + } + + if(!enif_get_int(env, argv[1], &index)) { + return enif_make_badarg(env); + } + + int rc = sqlite3_bind_null(stmt->statement, index); + if(rc != SQLITE_OK) { + return make_sqlite3_error_tuple(env, rc); + } + + return make_atom(env, "ok"); +} + + static ERL_NIF_TERM esqlite_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { @@ -1450,6 +1482,26 @@ esqlite_step(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return make_sqlite3_error_tuple(env, rc); } +static ERL_NIF_TERM +esqlite_reset(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + esqlite3_stmt *stmt; + + if(argc != 1) { + return enif_make_badarg(env); + } + + if(!enif_get_resource(env, argv[0], esqlite3_stmt_type, (void **) &stmt)) { + return enif_make_badarg(env); + } + + if(!stmt->statement) { + return enif_raise_exception(env, make_atom(env, "no_prepared_statement")); + } + + int rc = sqlite3_reset(stmt->statement); + return make_sqlite3_error_tuple(env, rc); +} /* @@ -1643,11 +1695,54 @@ esqlite_interrupt(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return enif_make_badarg(env); esqlite3 *db = (esqlite3 *) conn; - sqlite3_interrupt(db->db); + if(db->db == NULL) { + return make_error_tuple(env, "closed"); + } + sqlite3_interrupt(db->db); return enif_make_atom(env, "ok"); } +static ERL_NIF_TERM +esqlite_get_autocommit(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + esqlite3 *conn; + + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) + return enif_make_badarg(env); + + esqlite3 *db = (esqlite3 *) conn; + + if(db->db == NULL) { + return make_error_tuple(env, "closed"); + } + + if(sqlite3_get_autocommit(db->db)) { + return make_atom(env, "true"); + } + + return make_atom(env, "false"); +} + +static ERL_NIF_TERM +esqlite_last_insert_rowid(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + esqlite3 *conn; + + if(!enif_get_resource(env, argv[0], esqlite3_type, (void **) &conn)) + return enif_make_badarg(env); + + esqlite3 *db = (esqlite3 *) conn; + + if(db->db == NULL) { + return make_error_tuple(env, "closed"); + } + + sqlite3_int64 last_rowid = sqlite3_last_insert_rowid(db->db); + return enif_make_int64(env, last_rowid); +} + + /* * Load the nif. Initialize some stuff and such */ @@ -1703,8 +1798,7 @@ static ErlNifFunc nif_funcs[] = { {"bind_int64", 3, esqlite_bind_int64}, {"bind_double", 3, esqlite_bind_double}, - {"step", 1, esqlite_step}, - + {"bind_null", 2, esqlite_bind_null}, /* {"bind_text", 3, esqlite_bind_blob}, @@ -1712,7 +1806,18 @@ static ErlNifFunc nif_funcs[] = { {"bind_null", 2, esqlite_bind_blob}, */ - {"interrupt", 1, esqlite_interrupt, ERL_NIF_DIRTY_JOB_IO_BOUND} + {"step", 1, esqlite_step}, + {"reset", 1, esqlite_reset}, + + /* + Other interesting additions... trace. + wal_hook triggered after every commit. + also interesting commit and rollback_hooks + */ + + {"interrupt", 1, esqlite_interrupt, ERL_NIF_DIRTY_JOB_IO_BOUND}, + {"last_insert_rowid", 1, esqlite_last_insert_rowid}, + {"get_autocommit", 1, esqlite_get_autocommit}, /* {"set_update_hook", 4, set_update_hook}, @@ -1720,12 +1825,6 @@ static ErlNifFunc nif_funcs[] = { {"exec", 4, esqlite_exec, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"changes", 3, esqlite_changes}, {"insert", 4, esqlite_insert}, - {"last_insert_rowid", 3, esqlite_last_insert_rowid}, - {"get_autocommit", 3, esqlite_get_autocommit}, - {"reset", 4, esqlite_reset}, - - // TODO: {"esqlite_bind", 3, esqlite_bind_named}, - {"bind", 5, esqlite_bind}, {"backup_init", 6, esqlite_backup_init}, {"backup_step", 5, esqlite_backup_step}, diff --git a/src/esqlite3.erl b/src/esqlite3.erl index b826300..6f953f3 100644 --- a/src/esqlite3.erl +++ b/src/esqlite3.erl @@ -21,41 +21,40 @@ -export([ open/1, close/1, + %% db connection functions + get_autocommit/1, + last_insert_rowid/1, +% set_update_hook/2, set_update_hook/3, + prepare/2, prepare/3, + %% prepared statement functions column_names/1, column_decltypes/1, bind_int/3, bind_int64/3, bind_double/3, + % bind_text/3, + % bind_blob/3, + bind_null/2, - step/1 + step/1, + reset/1 -% set_update_hook/2, set_update_hook/3, % exec/2, exec/3, exec/4, % changes/1, changes/2, % insert/2, insert/3, -% last_insert_rowid/1, % -% get_autocommit/1, get_autocommit/2, -% -% step/1, step/2, -% -% reset/1, -% bind/2, bind/3, % fetchone/1, % fetchall/1, fetchall/2, fetchall/3, % -% % backup_init/4, backup_init/5, % backup_finish/1, backup_finish/2, % backup_remaining/1, backup_remaining/2, % backup_pagecount/1, backup_pagecount/2, % backup_step/2, backup_step/3, -% -% flush/0 ]). % -export([q/2, q/3, q/4, map/3, map/4, foreach/3, foreach/4]). @@ -137,15 +136,7 @@ open(Filename) -> 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()}''' @@ -378,26 +369,20 @@ close(#esqlite3{db=Connection}) -> %% @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) -> RowidResult + when Connection :: esqlite3(), + RowidResult :: integer() | {error, closed}. +last_insert_rowid(#esqlite3{db=Connection}) -> + esqlite3_nif:last_insert_rowid(Connection). %% @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). - -%% @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) -> AutocommitResult + when Connection :: esqlite3(), + AutocommitResult :: true | false | {error, closed}. +get_autocommit(#esqlite3{db=Connection}) -> + esqlite3_nif:get_autocommit(Connection). %% @doc Compile a SQL statement. Returns a cached compiled statement which can be used in %% queries. @@ -449,64 +434,25 @@ bind_int64(#esqlite3_stmt{stmt=Stmt}, Index, Value) -> bind_double(#esqlite3_stmt{stmt=Stmt}, Index, Value) -> esqlite3_nif:bind_double(Stmt, Index, Value). +-spec bind_null(Statement, Index) -> BindResult + when Statement :: esqlite3_stmt(), + Index :: integer(), + BindResult :: ok | {error, _}. +bind_null(#esqlite3_stmt{stmt=Stmt}, Index) -> + esqlite3_nif:bind_null(Stmt, Index). + -spec step(Statement) -> StepResult when Statement :: esqlite3_stmt(), StepResult:: ok | {error, _}. step(#esqlite3_stmt{stmt=Stmt}) -> esqlite3_nif:step(Stmt). +-spec reset(Statement) -> ResetResult + when Statement :: esqlite3_stmt(), + ResetResult:: ok | {error, _}. +reset(#esqlite3_stmt{stmt=Stmt}) -> + esqlite3_nif:reset(Stmt). -%% @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(), -% 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). -% -%% @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. - -%% @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). - -%% @doc Bind values to prepared statements -%% -%-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). -% %% @doc Return the column names of the prepared statement. %% -spec column_names(Statement) -> Names @@ -524,17 +470,6 @@ column_decltypes(#esqlite3_stmt{stmt=Stmt}) -> esqlite3_nif:column_decltypes(Stmt). -%% @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). %% %% Backup API diff --git a/src/esqlite3_nif.erl b/src/esqlite3_nif.erl index 89601d0..64147e9 100644 --- a/src/esqlite3_nif.erl +++ b/src/esqlite3_nif.erl @@ -22,6 +22,10 @@ -export([ open/1, close/1, + + get_autocommit/1, + last_insert_rowid/1, + prepare/3, column_names/1, @@ -30,16 +34,20 @@ bind_int/3, bind_int64/3, bind_double/3, + %bind_text/3, + %bind_blob/3, + bind_null/2, step/1, + reset/1, + 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, @@ -108,9 +116,15 @@ bind_int64(_Statement, _Index, _Value) -> bind_double(_Statement, _Index, _Value) -> erlang:nif_error(nif_library_not_loaded). +bind_null(_Statement, _Index) -> + erlang:nif_error(nif_library_not_loaded). + step(_Statement) -> erlang:nif_error(nif_library_not_loaded). +reset(_Statement) -> + 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). @@ -210,13 +224,13 @@ interrupt(_Db) -> %% @doc Get the last insert rowid. %% -%-spec last_insert_rowid(esqlite3(), reference(), pid()) -> ok | {error, _}. -%last_insert_rowid(_Db, _Ref, _Dest) -> -% erlang:nif_error(nif_library_not_loaded). +-spec last_insert_rowid(esqlite3()) -> integer() | {error, _}. +last_insert_rowid(_Connection) -> + erlang:nif_error(nif_library_not_loaded). -%% @doc Get automcommit +%% @doc Get autocommit %% -%-spec get_autocommit(esqlite3(), reference(), pid()) -> ok | {error, _}. -%get_autocommit(_Db, _Ref, _Dest) -> -% erlang:nif_error(nif_library_not_loaded). +-spec get_autocommit(esqlite3()) -> true | false | {error, _}. +get_autocommit(_Connection) -> + erlang:nif_error(nif_library_not_loaded).