Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions lib/ecto/query.ex
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ defmodule Ecto.Query do
defp wrap_in_subquery(%Ecto.Query{} = query), do: %Ecto.SubQuery{query: query}
defp wrap_in_subquery(queryable), do: %Ecto.SubQuery{query: Ecto.Queryable.to_query(queryable)}

@joins [:join, :inner_join, :cross_join, :left_join, :right_join, :full_join,
@joins [:join, :inner_join, :cross_join, :cross_lateral_join, :left_join, :right_join, :full_join,
:inner_lateral_join, :left_lateral_join]

@doc """
Expand Down Expand Up @@ -751,6 +751,7 @@ defmodule Ecto.Query do

Ecto.Query.exclude(query, :inner_join)
Ecto.Query.exclude(query, :cross_join)
Ecto.Query.exclude(query, :cross_lateral_join)
Ecto.Query.exclude(query, :left_join)
Ecto.Query.exclude(query, :right_join)
Ecto.Query.exclude(query, :full_join)
Expand Down Expand Up @@ -939,6 +940,7 @@ defmodule Ecto.Query do
defp join_qual(:right_join), do: :right
defp join_qual(:inner_join), do: :inner
defp join_qual(:cross_join), do: :cross
defp join_qual(:cross_lateral_join), do: :cross_lateral
defp join_qual(:left_lateral_join), do: :left_lateral
defp join_qual(:inner_lateral_join), do: :inner_lateral

Expand Down Expand Up @@ -975,10 +977,10 @@ defmodule Ecto.Query do
Receives a source that is to be joined to the query and a condition for
the join. The join condition can be any expression that evaluates
to a boolean value. The qualifier must be one of `:inner`, `:left`,
`:right`, `:cross`, `:full`, `:inner_lateral` or `:left_lateral`.
`:right`, `:cross`, `:cross_lateral`, `:full`, `:inner_lateral` or `:left_lateral`.

For a keyword query the `:join` keyword can be changed to `:inner_join`,
`:left_join`, `:right_join`, `:cross_join`, `:full_join`, `:inner_lateral_join`
`:left_join`, `:right_join`, `:cross_join`, `:cross_lateral_join`, `:full_join`, `:inner_lateral_join`
or `:left_lateral_join`. `:join` is equivalent to `:inner_join`.

Currently it is possible to join on:
Expand Down
4 changes: 2 additions & 2 deletions lib/ecto/query/builder/join.ex
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ defmodule Ecto.Query.Builder.Join do
unless is_binary(prefix) or is_nil(prefix) do
Builder.error! "`prefix` must be a compile time string, got: `#{Macro.to_string(prefix)}`"
end

as = case as do
{:^, _, [as]} -> as
as when is_atom(as) -> as
Expand Down Expand Up @@ -299,7 +299,7 @@ defmodule Ecto.Query.Builder.Join do
end
end

@qualifiers [:inner, :inner_lateral, :left, :left_lateral, :right, :full, :cross]
@qualifiers [:inner, :inner_lateral, :left, :left_lateral, :right, :full, :cross, :cross_lateral]

@doc """
Called at runtime to check dynamic qualifier.
Expand Down
1 change: 1 addition & 0 deletions lib/ecto/query/inspect.ex
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ defimpl Inspect, for: Ecto.Query do
defp join_qual(:right), do: :right_join
defp join_qual(:full), do: :full_join
defp join_qual(:cross), do: :cross_join
defp join_qual(:cross_lateral), do: :cross_join_lateral

defp collect_sources(%{from: nil, joins: joins}) do
["query" | join_sources(joins)]
Expand Down
2 changes: 1 addition & 1 deletion lib/ecto/query/planner.ex
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ defmodule Ecto.Query.Planner do
defp normalize_subquery_types([{source_alias, type_value} | types], [field | fields], select_aliases, acc) do
if Map.has_key?(select_aliases, source_alias) do
raise ArgumentError, """
the alias, #{inspect(source_alias)}, provided to `selected_as/2` conflicts
the alias, #{inspect(source_alias)}, provided to `selected_as/2` conflicts
with the subquery's automatic aliasing.

For example, the following query is not allowed because the alias `:y`
Expand Down
13 changes: 13 additions & 0 deletions test/ecto/query_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ defmodule Ecto.QueryTest do

inner_query = from p in "posts", inner_join: b in "blogs"
cross_query = from p in "posts", cross_join: b in "blogs"
cross_lateral_query = from p in "posts", cross_lateral_join: b in "blogs"
left_query = from p in "posts", left_join: b in "blogs"
right_query = from p in "posts", right_join: b in "blogs"
full_query = from p in "posts", full_join: b in "blogs"
Expand All @@ -716,6 +717,7 @@ defmodule Ecto.QueryTest do

refute inner_query.joins == base.joins
refute cross_query.joins == base.joins
refute cross_lateral_query.joins == base.joins
refute left_query.joins == base.joins
refute right_query.joins == base.joins
refute full_query.joins == base.joins
Expand All @@ -728,6 +730,9 @@ defmodule Ecto.QueryTest do
excluded_cross_query = exclude(cross_query, :cross_join)
assert excluded_cross_query.joins == base.joins

excluded_cross_lateral_query = exclude(cross_lateral_query, :cross_lateral_join)
assert excluded_cross_lateral_query.joins == base.joins

excluded_left_query = exclude(left_query, :left_join)
assert excluded_left_query.joins == base.joins

Expand All @@ -751,6 +756,8 @@ defmodule Ecto.QueryTest do
as: :blogs_i,
cross_join: bc in "blogs",
as: :blogs_c,
cross_lateral_join: bcl in "blogs",
as: :blogs_bcl,
left_join: bl in "blogs",
as: :blogs_l,
right_join: br in "blogs",
Expand All @@ -777,6 +784,12 @@ defmodule Ecto.QueryTest do
refute Map.has_key?(excluded_cross_join_query.aliases, :blogs_c)
assert Map.has_key?(excluded_cross_join_query.aliases, :base)

excluded_cross_lateral_join_query = exclude(query, :cross_lateral_join)
assert length(excluded_cross_lateral_join_query.joins) == original_joins_number - 1
assert map_size(excluded_cross_lateral_join_query.aliases) == original_aliases_number - 1
refute Map.has_key?(excluded_cross_lateral_join_query.aliases, :blogs_bcl)
assert Map.has_key?(excluded_cross_lateral_join_query.aliases, :base)

excluded_left_join_query = exclude(query, :left_join)
assert length(excluded_left_join_query.joins) == original_joins_number - 1
assert map_size(excluded_left_join_query.aliases) == original_aliases_number - 1
Expand Down