Packages
ecto
3.8.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/cte.ex
import Kernel, except: [apply: 3]
defmodule Ecto.Query.Builder.CTE do
@moduledoc false
alias Ecto.Query.Builder
@doc """
Escapes the CTE name.
iex> escape(quote(do: "FOO"), __ENV__)
"FOO"
"""
@spec escape(Macro.t, Macro.Env.t) :: Macro.t
def escape(name, _env) when is_bitstring(name), do: name
def escape({:^, _, [expr]}, _env), do: expr
def escape(expr, env) do
case Macro.expand_once(expr, env) do
^expr ->
Builder.error! "`#{Macro.to_string(expr)}` is not a valid CTE name. " <>
"It must be a literal string or an interpolated variable."
expr ->
escape(expr, env)
end
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, Macro.t, Macro.Env.t) :: Macro.t
def build(query, name, cte, env) do
Builder.apply_query(query, __MODULE__, [escape(name, env), build_cte(name, cte, env)], env)
end
@spec build_cte(Macro.t, Macro.t, Macro.Env.t) :: Macro.t
def build_cte(_name, {:^, _, [expr]}, _env) do
quote do: Ecto.Queryable.to_query(unquote(expr))
end
def build_cte(_name, {:fragment, _, _} = fragment, env) do
{expr, {params, :acc}} = Builder.escape(fragment, :any, {[], :acc}, [], env)
params = Builder.escape_params(params)
quote do
%Ecto.Query.QueryExpr{
expr: unquote(expr),
params: unquote(params),
file: unquote(env.file),
line: unquote(env.line)
}
end
end
def build_cte(name, cte, env) do
case Macro.expand_once(cte, env) do
^cte ->
Builder.error! "`#{Macro.to_string(cte)}` is not a valid CTE (named: #{Macro.to_string(name)}). " <>
"The CTE must be an interpolated query, such as ^existing_query or a fragment."
cte ->
build_cte(name, cte, env)
end
end
@doc """
The callback applied by `build/4` to build the query.
"""
@spec apply(Ecto.Queryable.t, bitstring, Ecto.Queryable.t) :: Ecto.Query.t
def apply(%Ecto.Query{with_ctes: with_expr} = query, name, with_query) do
with_expr = with_expr || %Ecto.Query.WithExpr{}
queries = List.keystore(with_expr.queries, name, 0, {name, with_query})
with_expr = %{with_expr | queries: queries}
%{query | with_ctes: with_expr}
end
def apply(query, name, with_query) do
apply(Ecto.Queryable.to_query(query), name, with_query)
end
end