Current section
Files
Jump to
Current section
Files
src/boto_query.erl
%% @private
-module(boto_query).
-export([query/2]).
query(Args, Query) ->
Graph = boto_server:graph(),
do_query(Graph, Args, Query).
do_query(Graph, Args, Query) ->
ArgsKeys = maps:keys(Args),
{QueryClean, NestedQuery} = extract_nested(Query),
Plan = planner(Graph, ArgsKeys, QueryClean),
RawResolved = lists:foldl(fun do_resolve/2, Args, Plan),
CleanResolved = maps:filter(fun(K, _V) -> lists:member(K, QueryClean) end, RawResolved),
nested_query(Graph, CleanResolved, NestedQuery).
planner(Graph, ArgsKeys, Query) ->
Fun = fun(Requested) ->
FlatFun = fun(Arg) -> boto_graph:path(Graph, Arg, Requested) end,
case lists:flatmap(FlatFun, ArgsKeys) of
[] ->
boto_graph:path(Graph, noarg, Requested);
Plan ->
Plan
end
end,
ResultPlan = lists:flatmap(Fun, Query),
lists:uniq(ResultPlan).
do_resolve({Mod, Name}, Args) ->
Resolved = apply(Mod, resolve, [Name, Args]),
maps:merge(Args, Resolved).
nested_query(Graph, Resolved, NestedQuery) ->
Fun = fun({ArgKey, Query}, Resolving) ->
Update =
case maps:get(ArgKey, Resolving) of
One when is_map(One) ->
do_query(Graph, One, Query);
Many when is_list(Many) ->
lists:map(fun(One) -> do_query(Graph, One, Query) end, Many)
end,
maps:put(ArgKey, Update, Resolving)
end,
lists:foldl(Fun, Resolved, NestedQuery).
extract_nested(Query) ->
NestedQuery = lists:filter(fun is_tuple/1, Query),
QueryClean = lists:map(fun extract_nested_field/1, Query),
{QueryClean, NestedQuery}.
extract_nested_field({K, _V}) ->
K;
extract_nested_field(K) ->
K.