Current section

Files

Jump to
sorcery lib services query tk_query.ex
Raw

lib/services/query/tk_query.ex

defmodule Sorcery.Query.TkQuery do
@moduledoc false
def from_tk_map(mod, args, tk_data) do
clauses = mod.clauses(args)
finds = mod.finds()
Enum.reduce(clauses, %{}, fn clause, acc ->
apply_clause(clause, args, acc, tk_data)
end)
|> apply_finds(finds)
|> prettify()
end
defp apply_finds(datak, finds) do
Enum.reduce(finds, %{}, fn
{lvark, :*}, acc -> Map.put(acc, lvark, datak[lvark])
{lvark, li}, acc ->
entities = Enum.map(datak[lvark], &(Map.take(&1, li)))
Map.put(acc, lvark, entities)
end)
end
defp prettify(data) do
Enum.reduce(data, %{}, fn {lvark, li}, acc ->
lvar = "#{lvark}"
table = Enum.reduce(li, %{}, fn entity, table -> Map.put(table, entity.id, entity) end)
Map.put(acc, lvar, table)
end)
end
defp apply_clause(%{lvar: lvark, attr: attr, right_type: :literal, op: op, right: right} = clause, _args, curr_data, all_data) do
set = get_set(clause, curr_data, all_data)
new_set = Enum.filter(set, fn entity ->
left = Map.get(entity, attr)
apply(Kernel, op, [left, right])
end)
Map.put(curr_data, lvark, new_set)
end
defp apply_clause(%{lvar: lvark, attr: attr, right_type: :arg, arg_name: arg_name, op: op} = clause, args, curr_data, all_data) do
set = get_set(clause, curr_data, all_data)
new_set = Enum.filter(set, fn entity ->
left = Map.get(entity, attr)
right = args[arg_name]
apply(Kernel, op, [left, right])
end)
Map.put(curr_data, lvark, new_set)
end
defp apply_clause(%{lvar: lvark, attr: attr, right_type: :lvar, op: op, other_lvar: other_lvark, other_lvar_attr: other_attr} = clause, _args, curr_data, all_data) do
other_set = Map.get(curr_data, other_lvark) || []
set = get_set(clause, curr_data, all_data)
new_set = Enum.filter(set, fn entity ->
left = Map.get(entity, attr)
Enum.any?(other_set, fn other_entity ->
right = Map.get(other_entity, other_attr)
apply(Kernel, op, [left, right])
end)
end)
Map.put(curr_data, lvark, new_set)
end
defp get_set(%{lvar: lvark, tk: tk}, curr_data, all_data) do
Map.get(curr_data, lvark) || Map.values(Map.get(all_data, tk))
end
end