2016-02-14 5 views
1

У меня есть функция возврата на postgreSQL, например.Как я могу получить набор, возвращенный из STR в модель через ecto?

CREATE FUNCTION set_ret_func(foo int, bar int) 
    RETURNS TABLE(total bigint, result bigint) AS $$ 
    SELECT a.val + $1 as total, b.val + $2 as result 
    FROM a, b 
    $$ LANGUAGE SQL; 

эта функция дает мне «гибкого зрения», что я могу легко назвать как:

SELECT * from set_ret_func('30'::int, '89'::int) 

озираясь я обнаружил, что полиморфные ассоциации можно вызвать с помощью Ecto.Repo делать что-то вроде

from(x in {"table_name", Model}, select: x.total) 
|> Repo.all 

Это заставило меня задуматься, могу ли я использовать Ecto.Query или фрагмент/1 в Ecto.Query.API в файле from/2, чтобы я смог вызвать функцию set set в Schema (они будуткак матч на column_name, типа) на то, что в соответствии с моим воображением выглядело бы что-то вроде:

from(srf in {fragment("set_ret_func(?::int, ?::int)", var1, var2), Model}, 
    select: srf.total) 

Есть ли фактический способ назвать это STRs и ввергнут их в модели?

ответ

1

Честно говоря, самый простой способ сделать это - Ecto.Adapters.SQL.query. Вы можете загрузить его в модель. Вот краткий фрагмент, который должен быть примерно правильно:

with {:ok, %{columns: cols, rows: rows}} <- Ecto.Adapters.SQL.query(Repo, "SELECT * FROM set_rec_func(?,?)", [var1, var2]) 
    fields = Enum.map(cols, &String.to_existing_atom/1) do 
    for row <- rows, values = Enum.zip(fields, rows) do 
    struct(Model, values) |> Ecto.put_meta(state: :loaded) 
    end 
end 

Хотя это не совсем то, что ваш экто запрос пытался сделать, что было выбрать только одно поле, а не вся модель. На самом деле не так много магии модели, которая происходит в Ecto. Вся настоящая магия происходит в API Ecto.Query и в API Ecto.Changeset. Чтобы предотвратить будущую путаницу, фактически Ecto 2.0 (в течение нескольких дней) полностью отбрасывает слово «Модель». Все они просто нормальные структуры связаны с некоторыми метаданных схемы.