Packages
ecto
3.0.2
3.14.1
3.14.0
3.13.6
3.13.5
3.13.4
3.13.3
3.13.2
3.13.1
3.13.0
3.12.6
3.12.5
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.11.2
3.11.1
3.11.0
3.10.3
3.10.2
3.10.1
3.10.0
3.9.6
3.9.5
3.9.4
3.9.3
3.9.2
3.9.1
3.9.0
3.8.4
3.8.3
3.8.2
3.8.1
3.8.0
3.7.2
3.7.1
3.7.0
3.6.2
3.6.1
3.6.0
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.5.0-rc.1
3.5.0-rc.0
3.4.6
3.4.5
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
3.0.0-rc.1
3.0.0-rc.0
2.2.12
2.2.11
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.2.0-rc.1
2.2.0-rc.0
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.1.0-rc.5
2.1.0-rc.4
2.1.0-rc.3
2.1.0-rc.2
2.1.0-rc.1
2.1.0-rc.0
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
2.0.0-rc.6
2.0.0-rc.5
2.0.0-rc.4
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
2.0.0-beta.2
2.0.0-beta.1
2.0.0-beta.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.16.0
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
0.13.0
0.12.1
0.12.0
0.12.0-rc
0.11.3
0.11.2
0.11.1
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
A toolkit for data mapping and language integrated query for Elixir
Current section
Files
Jump to
Current section
Files
lib/ecto/query/builder/group_by.ex
import Kernel, except: [apply: 2]
defmodule Ecto.Query.Builder.GroupBy do
@moduledoc false
alias Ecto.Query.Builder
@doc """
Escapes a list of quoted expressions.
See `Ecto.Builder.escape/2`.
iex> escape(:group_by, quote do [x.x, 13] end, {[], :acc}, [x: 0], __ENV__)
{[{:{}, [], [{:{}, [], [:., [], [{:{}, [], [:&, [], [0]]}, :x]]}, [], []]},
13],
{[], :acc}}
"""
@spec escape(:group_by | :partition_by, Macro.t, {list, term}, Keyword.t, Macro.Env.t) ::
{Macro.t, {list, term}}
def escape(kind, {:^, _, [expr]}, params_acc, _vars, _env) do
{quote(do: Ecto.Query.Builder.GroupBy.group_by!(unquote(kind), unquote(expr))), params_acc}
end
def escape(kind, expr, params_acc, vars, env) do
expr
|> List.wrap
|> Enum.map_reduce(params_acc, &do_escape(&1, &2, kind, vars, env))
end
defp do_escape({:^, _, [expr]}, params_acc, kind, _vars, _env) do
{quote(do: Ecto.Query.Builder.GroupBy.field!(unquote(kind), unquote(expr))), params_acc}
end
defp do_escape(field, params_acc, _kind, _vars, _env) when is_atom(field) do
{Macro.escape(to_field(field)), params_acc}
end
defp do_escape(expr, params_acc, _kind, vars, env) do
Builder.escape(expr, :any, params_acc, vars, env)
end
@doc """
Called at runtime to verify a field.
"""
def field!(_kind, field) when is_atom(field),
do: to_field(field)
def field!(kind, other) do
raise ArgumentError,
"expected a field as an atom in `#{kind}`, got: `#{inspect other}`"
end
@doc """
Called at runtime to verify group_by.
"""
def group_by!(kind, group_by) do
Enum.map List.wrap(group_by), fn
field when is_atom(field) ->
to_field(field)
_ ->
raise ArgumentError,
"expected a list of fields in `#{kind}`, got: `#{inspect group_by}`"
end
end
defp to_field(field), do: {{:., [], [{:&, [], [0]}, field]}, [], []}
@doc """
Builds a quoted expression.
The quoted expression should evaluate to a query at runtime.
If possible, it does all calculations at compile time to avoid
runtime work.
"""
@spec build(Macro.t, [Macro.t], Macro.t, Macro.Env.t) :: Macro.t
def build(query, binding, expr, env) do
{query, binding} = Builder.escape_binding(query, binding, env)
{expr, {params, _}} = escape(:group_by, expr, {[], :acc}, binding, env)
params = Builder.escape_params(params)
group_by = quote do: %Ecto.Query.QueryExpr{
expr: unquote(expr),
params: unquote(params),
file: unquote(env.file),
line: unquote(env.line)}
Builder.apply_query(query, __MODULE__, [group_by], env)
end
@doc """
The callback applied by `build/4` to build the query.
"""
@spec apply(Ecto.Queryable.t, term) :: Ecto.Query.t
def apply(%Ecto.Query{group_bys: group_bys} = query, expr) do
%{query | group_bys: group_bys ++ [expr]}
end
def apply(query, expr) do
apply(Ecto.Queryable.to_query(query), expr)
end
end