diff --git a/src/esqlite3.erl b/src/esqlite3.erl index 2834e8e..77de6f3 100644 --- a/src/esqlite3.erl +++ b/src/esqlite3.erl @@ -59,7 +59,9 @@ bind/2, q/2, q/3, - fetchall/1 + fetchall/1, + + status/0, status/1, status/2 ]). -define(DEFAULT_TIMEOUT, infinity). @@ -87,6 +89,15 @@ -type prepare_flags() :: persistent | no_vtab. +-type status_info() :: #{ memory_used => stats(), + pagecache_used => stats(), + pagecache_overflow => stats(), + malloc_size := stats(), + parser_stack := stats(), + pagecache_size := stats(), + malloc_count := stats() }. +-type stats() :: #{ used := non_neg_integer(), highwater := non_neg_integer() }. + %% erlang -> sqlite type conversions %% %% 'undefined' -> null @@ -299,12 +310,11 @@ prepare(Connection, Sql) -> %% @doc Compile a SQL statement. Returns a cached compiled statement which can be used in %% queries. -%% --spec prepare(Connection, Sql, PrepareFlags) -> PrepareResult - when Connection :: esqlite3(), - Sql :: sql(), - PrepareFlags :: list(prepare_flags()), - PrepareResult :: {ok, esqlite3_stmt()} | {error, _}. +-spec prepare(Connection, Sql, PrepareFlags) -> PrepareResult when + Connection :: esqlite3(), + Sql :: sql(), + PrepareFlags :: list(prepare_flags()), + PrepareResult :: {ok, esqlite3_stmt()} | {error, _}. prepare(#esqlite3{db=Connection}, Sql, PrepareFlags) -> case esqlite3_nif:prepare(Connection, Sql, props_to_prepare_flag(PrepareFlags)) of {ok, Stmt} -> @@ -313,19 +323,19 @@ prepare(#esqlite3{db=Connection}, Sql, PrepareFlags) -> Error end. --spec bind_int(Statement, Index, Value) -> BindResult - when Statement :: esqlite3_stmt(), - Index :: integer(), - Value :: integer(), - BindResult :: ok | {error, _}. +-spec bind_int(Statement, Index, Value) -> BindResult when + Statement :: esqlite3_stmt(), + Index :: integer(), + Value :: integer(), + BindResult :: ok | {error, _}. bind_int(#esqlite3_stmt{stmt=Stmt}, Index, Value) -> esqlite3_nif:bind_int(Stmt, Index, Value). --spec bind_int64(Statement, Index, Value) -> BindResult - when Statement :: esqlite3_stmt(), - Index :: integer(), - Value :: integer(), - BindResult :: ok | {error, _}. +-spec bind_int64(Statement, Index, Value) -> BindResult when + Statement :: esqlite3_stmt(), + Index :: integer(), + Value :: integer(), + BindResult :: ok | {error, _}. bind_int64(#esqlite3_stmt{stmt=Stmt}, Index, Value) -> esqlite3_nif:bind_int64(Stmt, Index, Value). @@ -424,10 +434,52 @@ backup_remaining(#esqlite3_backup{backup=Backup}) -> backup_pagecount(#esqlite3_backup{backup=Backup}) -> esqlite3_nif:backup_pagecount(Backup). + +%% @doc Get all internal status information from sqlite. +%% +-spec status() -> StatusInfo when + StatusInfo :: status_info(). +status() -> + status(false). + +%% @doc Specify which internal status information you need, when true +%% is passed, the highwater information from the status information +%% will be reset. +-spec status(ArgsOrResetHighWater) -> Status when + ArgsOrResetHighWater :: list(atom()) | boolean(), + Status :: status_info(). +status(Args) when is_list(Args) -> + status(Args, false); +status(ResetHighWater) when ResetHighWater =:= true orelse ResetHighWater =:= false -> + status([memory_used,pagecache_used, pagecache_overflow, malloc_size, + parser_stack, pagecache_size, malloc_count], ResetHighWater); +status(Op) when is_atom(Op) -> + status(Op, false). + +status(Args, ResetHighWater) when is_list(Args) -> + status1(Args, #{}, ResetHighWater); +status(Op, ResetHighWater) -> + esqlite3_nif:status(op_arg(Op), reset_arg(ResetHighWater)). + %% %% Helpers %% +status1([], Acc, _ResetArg) -> Acc; +status1([S|Rest], Acc, ResetArg) -> + status1(Rest, Acc#{ S => status(S, ResetArg)}, ResetArg). + +reset_arg(true) -> 1; +reset_arg(false) -> 0. + +op_arg(memory_used) -> 0; +op_arg(pagecache_used) -> 1; +op_arg(pagecache_overflow) -> 2; +op_arg(malloc_size) -> 5; +op_arg(parser_stack) -> 6; +op_arg(pagecache_size) -> 7; +op_arg(malloc_count) -> 8. + props_to_prepare_flag(Props) -> Flag = case proplists:get_value(no_vtab, Props, false) of true -> ?SQLITE_PREPARE_NO_VTAB;