Packages
ecto
3.10.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/limit_offset.ex
import Kernel, except: [apply: 3]
defmodule Ecto.Query.Builder.LimitOffset do
@moduledoc false
alias Ecto.Query.Builder
@doc """
Validates `with_ties` at runtime.
"""
@spec with_ties!(any) :: boolean
def with_ties!(with_ties) when is_boolean(with_ties), do: with_ties
def with_ties!(with_ties),
do: raise("`with_ties` expression must evaluate to a boolean at runtime, got: `#{inspect(with_ties)}`")
@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(:limit | :with_ties | :offset, Macro.t(), [Macro.t()], Macro.t(), Macro.Env.t()) ::
Macro.t()
def build(type, query, binding, expr, env) do
{query, vars} = Builder.escape_binding(query, binding, env)
{expr, {params, _acc}} = escape(type, expr, {[], %{}}, vars, env)
params = Builder.escape_params(params)
quoted = build_quoted(type, expr, params, env)
Builder.apply_query(query, __MODULE__, [type, quoted], env)
end
defp escape(type, expr, params_acc, vars, env) when type in [:limit, :offset] do
Builder.escape(expr, :integer, params_acc, vars, env)
end
defp escape(:with_ties, expr, params_acc, _vars, _env) when is_boolean(expr) do
{expr, params_acc}
end
defp escape(:with_ties, {:^, _, [expr]}, params_acc, _vars, _env) do
{quote(do: Ecto.Query.Builder.LimitOffset.with_ties!(unquote(expr))), params_acc}
end
defp escape(:with_ties, expr, _params_acc, _vars, _env) do
Builder.error!(
"`with_ties` expression must be a compile time boolean or an interpolated value using ^, got: `#{Macro.to_string(expr)}`"
)
end
defp build_quoted(:limit, expr, params, env) do
quote do: %Ecto.Query.LimitExpr{
expr: unquote(expr),
params: unquote(params),
file: unquote(env.file),
line: unquote(env.line)
}
end
defp build_quoted(:offset, expr, params, env) do
quote do: %Ecto.Query.QueryExpr{
expr: unquote(expr),
params: unquote(params),
file: unquote(env.file),
line: unquote(env.line)
}
end
defp build_quoted(:with_ties, expr, _params, _env), do: expr
@doc """
The callback applied by `build/4` to build the query.
"""
@spec apply(Ecto.Queryable.t(), :limit | :with_ties | :offset, term) :: Ecto.Query.t()
def apply(%Ecto.Query{} = query, :limit, expr) do
%{query | limit: expr}
end
def apply(%Ecto.Query{limit: limit} = query, :with_ties, expr) do
%{query | limit: apply_limit(limit, expr)}
end
def apply(%Ecto.Query{} = query, :offset, expr) do
%{query | offset: expr}
end
def apply(query, kind, expr) do
apply(Ecto.Queryable.to_query(query), kind, expr)
end
@doc """
Applies the `with_ties` value to the `limit` struct.
"""
def apply_limit(nil, _with_ties) do
Builder.error!("`with_ties` can only be applied to queries containing a `limit`")
end
# Runtime
def apply_limit(%_{} = limit, with_ties) do
%{limit | with_ties: with_ties}
end
# Compile
def apply_limit(limit, with_ties) do
quote do
Ecto.Query.Builder.LimitOffset.apply_limit(unquote(limit), unquote(with_ties))
end
end
end