Current section

Files

Jump to
query_builder lib query.ex
Raw

lib/query.ex

defmodule QueryBuilder.Query do
@moduledoc false
defstruct(
ecto_query: nil,
operations: []
)
end
defimpl Inspect, for: QueryBuilder.Query do
def inspect(query, opts) do
query
|> Ecto.Queryable.to_query()
|> Inspect.inspect(opts)
end
end
defimpl Ecto.Queryable, for: QueryBuilder.Query do
def to_query(%{ecto_query: ecto_query} = query) do
source_schema = QueryBuilder.Utils.root_schema(ecto_query)
%{ecto_query: ecto_query, operations: operations} =
case authorizer() do
nil ->
query
authorizer ->
authorizer.reject_unauthorized(query, source_schema)
end
operations = Enum.reverse(operations)
assoc_list =
Enum.reduce(operations, [], fn %{assocs: assocs, type: type} = operation, accumulated_assocs ->
opts =
case type do
:preload ->
[join: :inner_if_cardinality_is_one, preload: true]
:left_join ->
[join: :left, join_filters: operation.join_filters]
_ ->
[]
end
opts = [{:authorizer, authorizer()} | opts]
QueryBuilder.AssocList.build(source_schema, accumulated_assocs, assocs, opts)
end)
{ecto_query, assoc_list} =
QueryBuilder.JoinMaker.make_joins(ecto_query, assoc_list)
ecto_query =
Enum.reduce(operations, ecto_query, fn
%{type: :left_join}, ecto_query ->
ecto_query
%{type: type, args: args}, ecto_query ->
Module.concat(QueryBuilder.Query, to_string(type) |> Macro.camelize())
|> apply(type, [ecto_query | [assoc_list | args]])
end)
Ecto.Queryable.to_query(ecto_query)
end
defp authorizer() do
Application.get_env(:query_builder, :authorizer)
end
end