Packages
ecto
3.4.0
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")
"FOO"
"""
@spec escape(Macro.t) :: Macro.t
def escape(name) when is_bitstring(name), do: name
def escape({:^, _, [expr]}), do: expr
def escape(other) do
Builder.error! "`#{Macro.to_string(other)}` is not a valid CTE name. " <>
"It must be a literal string or an interpolated variable."
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), build_cte(name, cte, env)], env)
end
@spec build_cte(Macro.t, Macro.t, Macro.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
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."
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