Current section

Files

Jump to
ecto3_mnesia lib ecto adapters mnesia query.ex
Raw

lib/ecto/adapters/mnesia/query.ex

defmodule Ecto.Adapters.Mnesia.Query do
@moduledoc false
import Ecto.Adapters.Mnesia.Table, only: [
record_field_index: 2
]
alias Ecto.Adapters.Mnesia
alias Ecto.Query.QueryExpr
require Qlc
defstruct [
type: nil,
sources: nil,
query: nil,
sort: nil,
answers: nil,
new_record: nil
]
@type t :: %__MODULE__{
type: :all | :update_all | :delete_all,
sources: Keyword.t(),
query: (params :: list() -> query_handle :: :qlc.query_handle()),
sort: (query_handle :: :qlc.query_handle() -> query_handle :: :qlc.query_handle()),
answers: (query_handle :: :qlc.query_handle() -> list(tuple())),
new_record: (tuple(), list() -> tuple())
}
@spec from_ecto_query(type :: atom(), ecto_query :: Ecto.Query.t()) ::
mnesia_query :: t()
def from_ecto_query(
type,
%Ecto.Query{
select: select,
joins: joins,
sources: sources,
wheres: wheres,
updates: updates,
order_bys: order_bys,
limit: limit
}
) do
sources = sources(sources)
query = Mnesia.Qlc.query(select, joins, sources).(wheres)
sort = Mnesia.Qlc.sort(order_bys, select, sources)
answers = Mnesia.Qlc.answers(limit)
new_record = new_record(Enum.at(sources, 0), updates)
%Mnesia.Query{
type: type,
sources: sources,
query: query,
sort: sort,
answers: answers,
new_record: new_record
}
end
defp sources(sources) do
sources
|> Tuple.to_list()
|> Enum.map(fn ({table_name, schema, _}) ->
{String.to_atom(table_name), schema}
end)
end
defp new_record({table_name, schema}, updates) do
fn (record, params) ->
case updates do
[%QueryExpr{expr: [set: replacements]}] ->
replacements
|> Enum.reduce(record, fn ({field, {:^, [], [param_index]}}, record) ->
record_field_index = record_field_index(field, table_name)
value = Enum.at(params, param_index)
List.replace_at(record, record_field_index, value)
end)
|> List.insert_at(0, schema)
|> List.to_tuple()
_ -> record
end
end
end
end