Packages
ecto
3.0.9
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/windows.ex
import Kernel, except: [apply: 2]
defmodule Ecto.Query.Builder.Windows do
@moduledoc false
alias Ecto.Query.Builder
alias Ecto.Query.Builder.{GroupBy, OrderBy}
@doc """
Escapes a window params.
## Examples
iex> escape(quote do [order_by: [desc: 13]] end, {[], :acc}, [x: 0], __ENV__)
{[order_by: [desc: 13]], {[], :acc}}
"""
@spec escape([Macro.t], {list, term}, Keyword.t, Macro.Env.t | {Macro.Env.t, fun}) :: {Macro.t, {list, term}}
def escape(kw, params_acc, vars, env) when is_list(kw) do
Enum.map_reduce(kw, params_acc, &do_escape(&1, &2, vars, env))
end
def escape(kw, _params_acc, _vars, _env) do
error!(kw)
end
defp do_escape({:partition_by, fields}, params_acc, vars, env) do
{fields, params_acc} = GroupBy.escape(:partition_by, fields, params_acc, vars, env)
{{:partition_by, fields}, params_acc}
end
defp do_escape({:order_by, fields}, params_acc, vars, env) do
{fields, params_acc} = OrderBy.escape(:order_by, fields, params_acc, vars, env)
{{:order_by, fields}, params_acc}
end
defp do_escape({:frame, frame_clause}, params_acc, vars, env) do
{frame_clause, params_acc} = escape_frame(frame_clause, params_acc, vars, env)
{{:frame, frame_clause}, params_acc}
end
defp do_escape(other, _params_acc, _vars, _env) do
error!(other)
end
defp escape_frame({:fragment, _, _} = fragment, params_acc, vars, env) do
Builder.escape(fragment, :any, params_acc, vars, env)
end
defp escape_frame(other, _, _, _) do
Builder.error!("expected a fragment in `:frame`, got: `#{inspect other}`")
end
defp error!(other) do
Builder.error!(
"expected window definition to be a keyword list " <>
"with partition_by, order_by or frame as keys, got: `#{inspect other}`"
)
end
@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], Keyword.t, Macro.Env.t) :: Macro.t
def build(query, binding, windows, env) when is_list(windows) do
{query, binding} = Builder.escape_binding(query, binding, env)
windows = Enum.map(windows, &build_window(binding, &1, env))
Builder.apply_query(query, __MODULE__, [windows], env)
end
def build(_, _, windows, _) do
Builder.error!(
"expected window definitions to be a keyword list with window names as keys and " <>
"a keyword list with the window definition as value, got: `#{inspect windows}`"
)
end
defp build_window(vars, {name, expr}, env) do
{expr, {params, _}} = escape(expr, {[], :acc}, vars, env)
params = Builder.escape_params(params)
window = quote do
%Ecto.Query.QueryExpr{
expr: unquote(expr),
params: unquote(params),
file: unquote(env.file),
line: unquote(env.line)
}
end
{name, window}
end
@doc """
The callback applied by `build/4` to build the query.
"""
@spec apply(Ecto.Queryable.t, Keyword.t) :: Ecto.Query.t
def apply(%Ecto.Query{windows: windows} = query, definitions) do
merged = Keyword.merge(windows, definitions, fn name, _, _ ->
Builder.error! "window with name #{name} is already defined"
end)
%{query | windows: merged}
end
def apply(query, definitions) do
apply(Ecto.Queryable.to_query(query), definitions)
end
end