Thanks.
a) select only?
I’ll be glad to select
a list.
list = ~w(ean date brand)a
q = from p in Product, select: ^list
Repo.to_sql(:all, q)
{"SELECT p0.\"ean\", p0.\"date\", p0.\"brand\" FROM \"products\" AS p0", []}
But I need to format the date field, not date but an expression like “extract(epoch from date)*1000”.
@LostKobrakai do you know how to do that?
??
q = from p in Product, select: Enum.map(^list, fn x -> x end)
** (Ecto.Query.CompileError) `Enum.map(^list, fn x -> x end)` is not a valid query expression. If you want to invoke Enum.map/2 in a query, make sure that the module Enum is required and that map/2 is a macro
??
list = [:ean, "extract(epoch from date)*1000", :brand]
from p in Product, select: ^list
** (ArgumentError) expected a list of fields in `select/2` inside `select`, got: `[:ean, "extract(epoch from date)*1000", :brand]`
(ecto) lib/ecto/query/builder/select.ex:138: Ecto.Query.Builder.Select.fields!/2
(ecto) lib/ecto/query/builder/select.ex:155: Ecto.Query.Builder.Select.select!/5
b) select + select_merge?
Maps are unordered and I guess the order in the generated sql is an implementation detail.
select_merge
expects a map or struct in select
, can not use a list.
Note that it does preserve ordering when there is no expression.
q = from p in Product, select: %{}
q = from p in q, select_merge: map(p, [:ean])
q = from p in q, select_merge: map(p, [:date])
q = from p in q, select_merge: map(p, [:brand])
Repo.to_sql(:all, q)
{"SELECT p0.\"ean\", p0.\"date\", p0.\"brand\" FROM \"products\" AS p0", []}
Go and see struct with the fragment?
%Ecto.Query.SelectExpr{
expr: {:merge, [],
[
{:merge, [],
[
{:&, [], [0]},
{:%{}, [],
[
date: {:fragment, [],
[
raw: "extract(epoch from ",
expr: {{:., [], [{:&, [], [0]}, :date]}, [], []},
raw: ")*1000"
]}
]}
]},
{:&, [], [0]}
]},
fields: nil,
file: "iex",
line: 6,
params: [],
take: %{0 => {:map, [:ean, :brand]}}
}
date fragment goes to .expr
, ean and brand to .take
, separate fields in struct, ordering can not be preserved.
Whatever detail, implementation does not preserve ordering in this use case.