Current section
Files
Jump to
Current section
Files
src/eql.erl
-module(eql).
-export([ compile/1
, compile/2
, compile/3
, new_tab/1
, get_query/2
, get_query/3
]).
%% a query is either a binary string or a list of binary strings and atoms
%% the atoms are replaced during `get_query` with the provided parameters
%% resulting in an iolist
-type query() :: binary() | [binary() | atom()].
-type query_list() :: [{atom(), query()}].
-type compile_opt() :: flush | %% delete all (or for this namespace) queries first
namespace. %% store queries in ets table keyed on a 2-tuple of
%% the filename as an atom and the name of the query
%% returns a list of
-spec compile(file:filename_all()) -> {ok, query_list()} | any().
compile(File) ->
eql_parse:file(File).
compile(Tab, File) ->
compile(Tab, File, []).
-spec compile(atom() | ets:tid(), file:filename_all(), [compile_opt()]) -> ok | any().
compile(Tab, File, Opts) ->
maybe_flush(Tab, File, Opts),
case compile(File) of
{ok, Queries} when is_list(Queries) ->
case proplists:get_value(namespace, Opts, false) of
true ->
Namespace = file_to_namespace(File),
true = ets:insert(Tab, [{{Namespace, Name}, Query} || {Name, Query} <- Queries]),
ok;
false ->
true = ets:insert(Tab, Queries),
ok
end;
Error ->
Error
end.
new_tab(Name) ->
ets:new(Name, [named_table, set, {read_concurrency, true}]).
-spec get_query(atom(), query_list() | ets:tab(), proplists:proplist()) ->
{ok, iolist()} | undefined.
get_query(Name, TidOrList, Params) ->
case get_query(Name, TidOrList) of
{ok, Query} ->
{ok, lists:map(fun(Key) when is_atom(Key) ->
proplists:get_value(Key, Params);
(S) ->
S
end, Query)};
Other ->
Other
end.
-spec get_query(atom(), query_list() | ets:tab()) -> {ok, iolist()} | undefined.
get_query(Name, Tid) when is_reference(Tid)
; is_atom(Tid) ->
case ets:lookup(Tid, Name) of
[] ->
undefined;
[{_, Query}] ->
{ok, Query}
end;
get_query(Name, Proplist) ->
case lists:keyfind(Name, 1, Proplist) of
{Name, Value} -> {ok, Value};
false -> undefined
end.
%% internal functions
-spec file_to_namespace(file:filename_all()) -> atom().
file_to_namespace(File) ->
list_to_atom(filename:rootname(filename:basename(File))).
maybe_flush(Tab, File, Opts) ->
case proplists:get_value(flush, Opts, false) of
true ->
case proplists:get_value(namespace, Opts, false) of
true ->
Namespace = file_to_namespace(File),
ets:match_delete(Tab, {{Namespace, '_'}, '_'});
false ->
ets:delete_all_objects(Tab)
end;
false ->
ok
end.