Current section

Files

Jump to
raw_sqlite3 src raw_sqlite3.erl
Raw

src/raw_sqlite3.erl

%% @doc Convenience and utility functions for the raw_sqlite3 library.
%%
%% NOTE: Currently the interface of the module should NOT be considered stable
%% since it's mostly a convenience, high-level functions. Users of the library
%% are expected to use sqltite3_nif module directly to build their own
%% high-level primitives since its interface is as stable as the SQLite C API
%% and is thoroughly type-specced and covered by tests.
-module(raw_sqlite3).
-include_lib("raw_sqlite3/include/sqlite3_nif.hrl").
-export([open/1, open/2, open/3,
close/1,
prepare/2,
bind/2,
step/1,
fetchall/1,
q/2, q/3,
exec/2, exec/3,
insert_many/3,
fold/4, fold/5,
map/3, map/4,
with_trxn/2,
make_flags/1,
atom_to_int_flag/1,
int_to_bool/1,
bool_to_int/1,
err_to_atom/1,
expand_error/1, expand_error/2]).
open(DbFile) ->
open(DbFile, ?SQLITE_OPEN_READWRITE bor ?SQLITE_OPEN_CREATE).
open(DbFile, Flags) ->
open(DbFile, Flags, "").
open(DbFile, Flags, Vfs) ->
expand_error(sqlite3_nif:sqlite3_open_v2(DbFile, Flags, Vfs)).
close(Db) ->
expand_error(sqlite3_nif:sqlite3_close_v2(Db)).
prepare(Db, Sql) ->
expand_error(Db, sqlite3_nif:sqlite3_prepare_v2(Db, Sql)).
bind(Stmt, Params) ->
expand_error(sqlite3_nif:sqlite3_bind(Stmt, Params)).
step(Stmt) ->
expand_error(sqlite3_nif:sqlite3_step(Stmt)).
fetchall(Stmt) ->
expand_error(fetchall(Stmt, [])).
fetchall(Stmt, Acc) ->
case sqlite3_nif:sqlite3_step(Stmt) of
ok ->
lists:reverse(Acc);
{error, _} = Err ->
Err;
Row ->
fetchall(Stmt, [Row | Acc])
end.
q(Db, Sql) ->
q(Db, Sql, []).
q(Db, Sql, Params) ->
case sqlite3_nif:sqlite3_prepare_v2(Db, Sql) of
{ok, Stmt, _} ->
case sqlite3_nif:sqlite3_bind(Stmt, Params) of
ok ->
fetchall(Stmt);
{error, _} = Err ->
expand_error(Db, Err)
end;
{error, _} = Err ->
expand_error(Db, Err)
end.
exec(Db, Sql) ->
exec(Db, Sql, []).
exec(_Db, <<>>, _Params) ->
ok;
exec(Db, <<$ , Rest/binary>>, Params) ->
exec(Db, Rest, Params);
exec(Db, Sql, Params) ->
case sqlite3_nif:sqlite3_prepare_v2(Db, Sql) of
{ok, Stmt, Leftover} ->
case exec_one(Stmt, Params) of
ok ->
exec(Db, Leftover, Params);
{error, _} = Err ->
expand_error(Db, Err)
end;
{error, _} = Err ->
expand_error(Db, Err)
end.
insert_many(Db, Sql, ParameterList) ->
case sqlite3_nif:sqlite3_prepare_v2(Db, Sql) of
{ok, Stmt, _Leftover} ->
expand_error(Db, insert_many(Stmt, ParameterList));
{error, _} = Err ->
expand_error(Db, Err)
end.
insert_many(_Stmt, []) ->
ok;
insert_many(Stmt, [Params | Rest]) ->
case sqlite3_nif:sqlite3_bind(Stmt, Params) of
ok ->
case sqlite3_nif:sqlite3_step(Stmt) of
ok ->
?SQLITE_OK = sqlite3_nif:sqlite3_reset(Stmt),
insert_many(Stmt, Rest);
Err ->
Err
end;
Err ->
Err
end.
exec_one(Stmt, Params) ->
case sqlite3_nif:sqlite3_bind(Stmt, Params) of
ok ->
case fetchall(Stmt, []) of
{error, _} = Err ->
Err;
_ ->
ok
end;
{error, _} = Err ->
Err
end.
fold(Db, Sql, Fun, Acc) ->
fold(Db, Sql, [], Fun, Acc).
fold(Db, Sql, Params, Fun, Acc) ->
case sqlite3_nif:sqlite3_prepare_v2(Db, Sql) of
{ok, Stmt, _Leftover} ->
case sqlite3_nif:sqlite3_bind(Stmt, Params) of
ok ->
expand_error(Db, do_fold(Stmt, Fun, Acc));
{error, _} = Err ->
expand_error(Db, Err)
end;
{error, _} = Err ->
expand_error(Db, Err)
end.
do_fold(Stmt, Fun, Acc) ->
case sqlite3_nif:sqlite3_step(Stmt) of
ok ->
{ok, Acc};
{error, _} = Err ->
Err;
Row ->
do_fold(Stmt, Fun, Fun(Row, Acc))
end.
map(Db, Sql, Fun) ->
map(Db, Sql, [], Fun).
map(Db, Sql, Params, Fun) ->
case sqlite3_nif:sqlite3_prepare_v2(Db, Sql) of
{ok, Stmt, _Leftover} ->
case sqlite3_nif:sqlite3_bind(Stmt, Params) of
ok ->
expand_error(do_map(Stmt, Fun, []));
{error, _} = Err ->
expand_error(Db, Err)
end;
{error, _} = Err ->
expand_error(Db, Err)
end.
do_map(Stmt, Fun, Acc) ->
case sqlite3_nif:sqlite3_step(Stmt) of
ok ->
{ok, lists:reverse(Acc)};
{error, _} = Err ->
Err;
Row ->
do_map(Stmt, Fun, [Fun(Row) | Acc])
end.
with_trxn(Db, F) ->
case exec(Db, "BEGIN") of
ok ->
try
Rv = F(),
ok = exec(Db, "COMMIT"),
Rv
catch
_:Reason:Stacktrace ->
ok = exec(Db, "ROLLBACK"),
{error, #{reason => Reason, stacktrace => Stacktrace}}
end;
{error, _} = Err -> Err
end.
make_flags(Atoms) ->
lists:foldl(fun(Flag, Acc) ->
atom_to_int_flag(Flag) bor Acc
end, 0, Atoms).
bool_to_int(true) ->
1;
bool_to_int(false) ->
0.
int_to_bool(0) ->
false;
int_to_bool(X) when is_integer(X) ->
true.
atom_to_int_flag('SQLITE_OPEN_READONLY') ->
?SQLITE_OPEN_READONLY;
atom_to_int_flag('SQLITE_OPEN_READWRITE') ->
?SQLITE_OPEN_READWRITE;
atom_to_int_flag('SQLITE_OPEN_CREATE') ->
?SQLITE_OPEN_CREATE;
atom_to_int_flag('SQLITE_OPEN_URI') ->
?SQLITE_OPEN_URI;
atom_to_int_flag('SQLITE_OPEN_MEMORY') ->
?SQLITE_OPEN_MEMORY;
atom_to_int_flag('SQLITE_OPEN_NOMUTEX') ->
?SQLITE_OPEN_NOMUTEX;
atom_to_int_flag('SQLITE_OPEN_FULLMUTEX') ->
?SQLITE_OPEN_FULLMUTEX;
atom_to_int_flag('SQLITE_OPEN_SHAREDCACHE') ->
?SQLITE_OPEN_SHAREDCACHE;
atom_to_int_flag('SQLITE_OPEN_PRIVATECACHE') ->
?SQLITE_OPEN_PRIVATECACHE;
atom_to_int_flag('SQLITE_OPEN_NOFOLLOW') ->
?SQLITE_OPEN_NOFOLLOW;
atom_to_int_flag('SQLITE_DBCONFIG_MAINDBNAME') ->
?SQLITE_DBCONFIG_MAINDBNAME;
atom_to_int_flag('SQLITE_DBCONFIG_ENABLE_FKEY') ->
?SQLITE_DBCONFIG_ENABLE_FKEY;
atom_to_int_flag('SQLITE_DBCONFIG_ENABLE_TRIGGER') ->
?SQLITE_DBCONFIG_ENABLE_TRIGGER;
atom_to_int_flag('SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER') ->
?SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER;
atom_to_int_flag('SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION') ->
?SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION;
atom_to_int_flag('SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE') ->
?SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE;
atom_to_int_flag('SQLITE_DBCONFIG_ENABLE_QPSG') ->
?SQLITE_DBCONFIG_ENABLE_QPSG;
atom_to_int_flag('SQLITE_DBCONFIG_TRIGGER_EQP') ->
?SQLITE_DBCONFIG_TRIGGER_EQP;
atom_to_int_flag('SQLITE_DBCONFIG_RESET_DATABASE') ->
?SQLITE_DBCONFIG_RESET_DATABASE;
atom_to_int_flag('SQLITE_DBCONFIG_DEFENSIVE') ->
?SQLITE_DBCONFIG_DEFENSIVE;
atom_to_int_flag('SQLITE_DBCONFIG_WRITABLE_SCHEMA') ->
?SQLITE_DBCONFIG_WRITABLE_SCHEMA;
atom_to_int_flag('SQLITE_DBCONFIG_LEGACY_ALTER_TABLE') ->
?SQLITE_DBCONFIG_LEGACY_ALTER_TABLE;
atom_to_int_flag('SQLITE_DBCONFIG_DQS_DML') ->
?SQLITE_DBCONFIG_DQS_DML;
atom_to_int_flag('SQLITE_DBCONFIG_DQS_DDL') ->
?SQLITE_DBCONFIG_DQS_DDL;
atom_to_int_flag('SQLITE_DBCONFIG_ENABLE_VIEW') ->
?SQLITE_DBCONFIG_ENABLE_VIEW;
atom_to_int_flag('SQLITE_DBCONFIG_LEGACY_FILE_FORMAT') ->
?SQLITE_DBCONFIG_LEGACY_FILE_FORMAT;
atom_to_int_flag('SQLITE_DBCONFIG_TRUSTED_SCHEMA') ->
?SQLITE_DBCONFIG_TRUSTED_SCHEMA;
atom_to_int_flag('SQLITE_LIMIT_LENGTH') ->
?SQLITE_LIMIT_LENGTH;
atom_to_int_flag('SQLITE_LIMIT_SQL_LENGTH') ->
?SQLITE_LIMIT_SQL_LENGTH;
atom_to_int_flag('SQLITE_LIMIT_COLUMN') ->
?SQLITE_LIMIT_COLUMN;
atom_to_int_flag('SQLITE_LIMIT_EXPR_DEPTH') ->
?SQLITE_LIMIT_EXPR_DEPTH;
atom_to_int_flag('SQLITE_LIMIT_COMPOUND_SELECT') ->
?SQLITE_LIMIT_COMPOUND_SELECT;
atom_to_int_flag('SQLITE_LIMIT_VDBE_OP') ->
?SQLITE_LIMIT_VDBE_OP;
atom_to_int_flag('SQLITE_LIMIT_FUNCTION_ARG') ->
?SQLITE_LIMIT_FUNCTION_ARG;
atom_to_int_flag('SQLITE_LIMIT_ATTACHED') ->
?SQLITE_LIMIT_ATTACHED;
atom_to_int_flag('SQLITE_LIMIT_LIKE_PATTERN_LENGTH') ->
?SQLITE_LIMIT_LIKE_PATTERN_LENGTH;
atom_to_int_flag('SQLITE_LIMIT_VARIABLE_NUMBER') ->
?SQLITE_LIMIT_VARIABLE_NUMBER;
atom_to_int_flag('SQLITE_LIMIT_TRIGGER_DEPTH') ->
?SQLITE_LIMIT_TRIGGER_DEPTH;
atom_to_int_flag('SQLITE_LIMIT_WORKER_THREADS') ->
?SQLITE_LIMIT_WORKER_THREADS;
atom_to_int_flag('SQLITE_DBSTATUS_LOOKASIDE_USED') ->
?SQLITE_DBSTATUS_LOOKASIDE_USED;
atom_to_int_flag('SQLITE_DBSTATUS_CACHE_USED') ->
?SQLITE_DBSTATUS_CACHE_USED;
atom_to_int_flag('SQLITE_DBSTATUS_SCHEMA_USED') ->
?SQLITE_DBSTATUS_SCHEMA_USED;
atom_to_int_flag('SQLITE_DBSTATUS_STMT_USED') ->
?SQLITE_DBSTATUS_STMT_USED;
atom_to_int_flag('SQLITE_DBSTATUS_LOOKASIDE_HIT') ->
?SQLITE_DBSTATUS_LOOKASIDE_HIT;
atom_to_int_flag('SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE') ->
?SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE;
atom_to_int_flag('SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL') ->
?SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL;
atom_to_int_flag('SQLITE_DBSTATUS_CACHE_HIT') ->
?SQLITE_DBSTATUS_CACHE_HIT;
atom_to_int_flag('SQLITE_DBSTATUS_CACHE_MISS') ->
?SQLITE_DBSTATUS_CACHE_MISS;
atom_to_int_flag('SQLITE_DBSTATUS_CACHE_WRITE') ->
?SQLITE_DBSTATUS_CACHE_WRITE;
atom_to_int_flag('SQLITE_DBSTATUS_DEFERRED_FKS') ->
?SQLITE_DBSTATUS_DEFERRED_FKS;
atom_to_int_flag('SQLITE_DBSTATUS_CACHE_USED_SHARED') ->
?SQLITE_DBSTATUS_CACHE_USED_SHARED;
atom_to_int_flag('SQLITE_DBSTATUS_CACHE_SPILL') ->
?SQLITE_DBSTATUS_CACHE_SPILL;
atom_to_int_flag('SQLITE_STMTSTATUS_FULLSCAN_STEP') ->
?SQLITE_STMTSTATUS_FULLSCAN_STEP;
atom_to_int_flag('SQLITE_STMTSTATUS_SORT') ->
?SQLITE_STMTSTATUS_SORT;
atom_to_int_flag('SQLITE_STMTSTATUS_AUTOINDEX') ->
?SQLITE_STMTSTATUS_AUTOINDEX;
atom_to_int_flag('SQLITE_STMTSTATUS_VM_STEP') ->
?SQLITE_STMTSTATUS_VM_STEP;
atom_to_int_flag('SQLITE_STMTSTATUS_REPREPARE') ->
?SQLITE_STMTSTATUS_REPREPARE;
atom_to_int_flag('SQLITE_STMTSTATUS_RUN') ->
?SQLITE_STMTSTATUS_RUN;
atom_to_int_flag('SQLITE_STMTSTATUS_MEMUSED') ->
?SQLITE_STMTSTATUS_MEMUSED;
atom_to_int_flag('SQLITE_CHECKPOINT_PASSIVE') ->
?SQLITE_CHECKPOINT_PASSIVE;
atom_to_int_flag('SQLITE_CHECKPOINT_FULL') ->
?SQLITE_CHECKPOINT_FULL;
atom_to_int_flag('SQLITE_CHECKPOINT_RESTART') ->
?SQLITE_CHECKPOINT_RESTART;
atom_to_int_flag('SQLITE_CHECKPOINT_TRUNCATE') ->
?SQLITE_CHECKPOINT_TRUNCATE.
err_to_atom(?SQLITE_OK) ->
'SQLITE_OK';
err_to_atom(?SQLITE_ERROR) ->
'SQLITE_ERROR';
err_to_atom(?SQLITE_INTERNAL) ->
'SQLITE_INTERNAL';
err_to_atom(?SQLITE_PERM) ->
'SQLITE_PERM';
err_to_atom(?SQLITE_ABORT) ->
'SQLITE_ABORT';
err_to_atom(?SQLITE_BUSY) ->
'SQLITE_BUSY';
err_to_atom(?SQLITE_LOCKED) ->
'SQLITE_LOCKED';
err_to_atom(?SQLITE_NOMEM) ->
'SQLITE_NOMEM';
err_to_atom(?SQLITE_READONLY) ->
'SQLITE_READONLY';
err_to_atom(?SQLITE_INTERRUPT) ->
'SQLITE_INTERRUPT';
err_to_atom(?SQLITE_IOERR) ->
'SQLITE_IOERR';
err_to_atom(?SQLITE_CORRUPT) ->
'SQLITE_CORRUPT';
err_to_atom(?SQLITE_NOTFOUND) ->
'SQLITE_NOTFOUND';
err_to_atom(?SQLITE_FULL) ->
'SQLITE_FULL';
err_to_atom(?SQLITE_CANTOPEN) ->
'SQLITE_CANTOPEN';
err_to_atom(?SQLITE_PROTOCOL) ->
'SQLITE_PROTOCOL';
err_to_atom(?SQLITE_EMPTY) ->
'SQLITE_EMPTY';
err_to_atom(?SQLITE_SCHEMA) ->
'SQLITE_SCHEMA';
err_to_atom(?SQLITE_TOOBIG) ->
'SQLITE_TOOBIG';
err_to_atom(?SQLITE_CONSTRAINT) ->
'SQLITE_CONSTRAINT';
err_to_atom(?SQLITE_MISMATCH) ->
'SQLITE_MISMATCH';
err_to_atom(?SQLITE_MISUSE) ->
'SQLITE_MISUSE';
err_to_atom(?SQLITE_NOLFS) ->
'SQLITE_NOLFS';
err_to_atom(?SQLITE_AUTH) ->
'SQLITE_AUTH';
err_to_atom(?SQLITE_FORMAT) ->
'SQLITE_FORMAT';
err_to_atom(?SQLITE_RANGE) ->
'SQLITE_RANGE';
err_to_atom(?SQLITE_NOTADB) ->
'SQLITE_NOTADB';
err_to_atom(?SQLITE_NOTICE) ->
'SQLITE_NOTICE';
err_to_atom(?SQLITE_WARNING) ->
'SQLITE_WARNING';
err_to_atom(?SQLITE_ROW) ->
'SQLITE_ROW';
err_to_atom(?SQLITE_DONE) ->
'SQLITE_DONE';
err_to_atom(?SQLITE_ERROR_MISSING_COLLSEQ) ->
'SQLITE_ERROR_MISSING_COLLSEQ';
err_to_atom(?SQLITE_ERROR_RETRY) ->
'SQLITE_ERROR_RETRY';
err_to_atom(?SQLITE_ERROR_SNAPSHOT) ->
'SQLITE_ERROR_SNAPSHOT';
err_to_atom(?SQLITE_IOERR_READ) ->
'SQLITE_IOERR_READ';
err_to_atom(?SQLITE_IOERR_SHORT_READ) ->
'SQLITE_IOERR_SHORT_READ';
err_to_atom(?SQLITE_IOERR_WRITE) ->
'SQLITE_IOERR_WRITE';
err_to_atom(?SQLITE_IOERR_FSYNC) ->
'SQLITE_IOERR_FSYNC';
err_to_atom(?SQLITE_IOERR_DIR_FSYNC) ->
'SQLITE_IOERR_DIR_FSYNC';
err_to_atom(?SQLITE_IOERR_TRUNCATE) ->
'SQLITE_IOERR_TRUNCATE';
err_to_atom(?SQLITE_IOERR_FSTAT) ->
'SQLITE_IOERR_FSTAT';
err_to_atom(?SQLITE_IOERR_UNLOCK) ->
'SQLITE_IOERR_UNLOCK';
err_to_atom(?SQLITE_IOERR_RDLOCK) ->
'SQLITE_IOERR_RDLOCK';
err_to_atom(?SQLITE_IOERR_DELETE) ->
'SQLITE_IOERR_DELETE';
err_to_atom(?SQLITE_IOERR_BLOCKED) ->
'SQLITE_IOERR_BLOCKED';
err_to_atom(?SQLITE_IOERR_NOMEM) ->
'SQLITE_IOERR_NOMEM';
err_to_atom(?SQLITE_IOERR_ACCESS) ->
'SQLITE_IOERR_ACCESS';
err_to_atom(?SQLITE_IOERR_CHECKRESERVEDLOCK) ->
'SQLITE_IOERR_CHECKRESERVEDLOCK';
err_to_atom(?SQLITE_IOERR_LOCK) ->
'SQLITE_IOERR_LOCK';
err_to_atom(?SQLITE_IOERR_CLOSE) ->
'SQLITE_IOERR_CLOSE';
err_to_atom(?SQLITE_IOERR_DIR_CLOSE) ->
'SQLITE_IOERR_DIR_CLOSE';
err_to_atom(?SQLITE_IOERR_SHMOPEN) ->
'SQLITE_IOERR_SHMOPEN';
err_to_atom(?SQLITE_IOERR_SHMSIZE) ->
'SQLITE_IOERR_SHMSIZE';
err_to_atom(?SQLITE_IOERR_SHMLOCK) ->
'SQLITE_IOERR_SHMLOCK';
err_to_atom(?SQLITE_IOERR_SHMMAP) ->
'SQLITE_IOERR_SHMMAP';
err_to_atom(?SQLITE_IOERR_SEEK) ->
'SQLITE_IOERR_SEEK';
err_to_atom(?SQLITE_IOERR_DELETE_NOENT) ->
'SQLITE_IOERR_DELETE_NOENT';
err_to_atom(?SQLITE_IOERR_MMAP) ->
'SQLITE_IOERR_MMAP';
err_to_atom(?SQLITE_IOERR_GETTEMPPATH) ->
'SQLITE_IOERR_GETTEMPPATH';
err_to_atom(?SQLITE_IOERR_CONVPATH) ->
'SQLITE_IOERR_CONVPATH';
err_to_atom(?SQLITE_IOERR_VNODE) ->
'SQLITE_IOERR_VNODE';
err_to_atom(?SQLITE_IOERR_AUTH) ->
'SQLITE_IOERR_AUTH';
err_to_atom(?SQLITE_IOERR_BEGIN_ATOMIC) ->
'SQLITE_IOERR_BEGIN_ATOMIC';
err_to_atom(?SQLITE_IOERR_COMMIT_ATOMIC) ->
'SQLITE_IOERR_COMMIT_ATOMIC';
err_to_atom(?SQLITE_IOERR_ROLLBACK_ATOMIC) ->
'SQLITE_IOERR_ROLLBACK_ATOMIC';
err_to_atom(?SQLITE_IOERR_DATA) ->
'SQLITE_IOERR_DATA';
err_to_atom(?SQLITE_LOCKED_SHAREDCACHE) ->
'SQLITE_LOCKED_SHAREDCACHE';
err_to_atom(?SQLITE_LOCKED_VTAB) ->
'SQLITE_LOCKED_VTAB';
err_to_atom(?SQLITE_BUSY_RECOVERY) ->
'SQLITE_BUSY_RECOVERY';
err_to_atom(?SQLITE_BUSY_SNAPSHOT) ->
'SQLITE_BUSY_SNAPSHOT';
err_to_atom(?SQLITE_BUSY_TIMEOUT) ->
'SQLITE_BUSY_TIMEOUT';
err_to_atom(?SQLITE_CANTOPEN_NOTEMPDIR) ->
'SQLITE_CANTOPEN_NOTEMPDIR';
err_to_atom(?SQLITE_CANTOPEN_ISDIR) ->
'SQLITE_CANTOPEN_ISDIR';
err_to_atom(?SQLITE_CANTOPEN_FULLPATH) ->
'SQLITE_CANTOPEN_FULLPATH';
err_to_atom(?SQLITE_CANTOPEN_CONVPATH) ->
'SQLITE_CANTOPEN_CONVPATH';
err_to_atom(?SQLITE_CANTOPEN_DIRTYWAL) ->
'SQLITE_CANTOPEN_DIRTYWAL';
err_to_atom(?SQLITE_CANTOPEN_SYMLINK) ->
'SQLITE_CANTOPEN_SYMLINK';
err_to_atom(?SQLITE_CORRUPT_VTAB) ->
'SQLITE_CORRUPT_VTAB';
err_to_atom(?SQLITE_CORRUPT_SEQUENCE) ->
'SQLITE_CORRUPT_SEQUENCE';
err_to_atom(?SQLITE_CORRUPT_INDEX) ->
'SQLITE_CORRUPT_INDEX';
err_to_atom(?SQLITE_READONLY_RECOVERY) ->
'SQLITE_READONLY_RECOVERY';
err_to_atom(?SQLITE_READONLY_CANTLOCK) ->
'SQLITE_READONLY_CANTLOCK';
err_to_atom(?SQLITE_READONLY_ROLLBACK) ->
'SQLITE_READONLY_ROLLBACK';
err_to_atom(?SQLITE_READONLY_DBMOVED) ->
'SQLITE_READONLY_DBMOVED';
err_to_atom(?SQLITE_READONLY_CANTINIT) ->
'SQLITE_READONLY_CANTINIT';
err_to_atom(?SQLITE_READONLY_DIRECTORY) ->
'SQLITE_READONLY_DIRECTORY';
err_to_atom(?SQLITE_ABORT_ROLLBACK) ->
'SQLITE_ABORT_ROLLBACK';
err_to_atom(?SQLITE_CONSTRAINT_CHECK) ->
'SQLITE_CONSTRAINT_CHECK';
err_to_atom(?SQLITE_CONSTRAINT_COMMITHOOK) ->
'SQLITE_CONSTRAINT_COMMITHOOK';
err_to_atom(?SQLITE_CONSTRAINT_FOREIGNKEY) ->
'SQLITE_CONSTRAINT_FOREIGNKEY';
err_to_atom(?SQLITE_CONSTRAINT_FUNCTION) ->
'SQLITE_CONSTRAINT_FUNCTION';
err_to_atom(?SQLITE_CONSTRAINT_NOTNULL) ->
'SQLITE_CONSTRAINT_NOTNULL';
err_to_atom(?SQLITE_CONSTRAINT_PRIMARYKEY) ->
'SQLITE_CONSTRAINT_PRIMARYKEY';
err_to_atom(?SQLITE_CONSTRAINT_TRIGGER) ->
'SQLITE_CONSTRAINT_TRIGGER';
err_to_atom(?SQLITE_CONSTRAINT_UNIQUE) ->
'SQLITE_CONSTRAINT_UNIQUE';
err_to_atom(?SQLITE_CONSTRAINT_VTAB) ->
'SQLITE_CONSTRAINT_VTAB';
err_to_atom(?SQLITE_CONSTRAINT_ROWID) ->
'SQLITE_CONSTRAINT_ROWID';
err_to_atom(?SQLITE_CONSTRAINT_PINNED) ->
'SQLITE_CONSTRAINT_PINNED';
err_to_atom(?SQLITE_NOTICE_RECOVER_WAL) ->
'SQLITE_NOTICE_RECOVER_WAL';
err_to_atom(?SQLITE_NOTICE_RECOVER_ROLLBACK) ->
'SQLITE_NOTICE_RECOVER_ROLLBACK';
err_to_atom(?SQLITE_WARNING_AUTOINDEX) ->
'SQLITE_WARNING_AUTOINDEX';
err_to_atom(?SQLITE_AUTH_USER) ->
'SQLITE_AUTH_USER';
err_to_atom(?SQLITE_OK_LOAD_PERMANENTLY) ->
'SQLITE_OK_LOAD_PERMANENTLY';
err_to_atom(?SQLITE_OK_SYMLINK) ->
'SQLITE_OK_SYMLINK';
err_to_atom(_) ->
'unknown_error'.
expand_error({ok, _Result} = OK) ->
OK;
expand_error({error, Err}) when is_integer(Err) ->
{error, err_to_atom(Err)};
expand_error(Err) when is_integer(Err) ->
err_to_atom(Err);
expand_error(Otherwise) ->
Otherwise.
expand_error(_Db, {ok, _Result} = OK) ->
OK;
expand_error(Db, {error, Err}) when is_integer(Err) ->
{error, {err_to_atom(Err), sqlite3_nif:sqlite3_errmsg(Db)}};
expand_error(_Db, Err) when is_integer(Err) ->
err_to_atom(Err);
expand_error(_Db, Otherwise) ->
Otherwise.