diff --git a/lib/ecto/repo/queryable.ex b/lib/ecto/repo/queryable.ex index dc462a6a60..c4a7cb4175 100644 --- a/lib/ecto/repo/queryable.ex +++ b/lib/ecto/repo/queryable.ex @@ -140,12 +140,12 @@ defmodule Ecto.Repo.Queryable do def exists?(name, queryable, opts) do queryable = - Query.exclude(queryable, :select) - |> Query.exclude(:preload) + Query.exclude(queryable, :preload) + |> rewrite_combinations() + |> Query.exclude(:select) |> Query.exclude(:distinct) |> Query.select(1) |> Query.limit(1) - |> rewrite_combinations() case all(name, queryable, opts) do [1] -> true @@ -155,13 +155,10 @@ defmodule Ecto.Repo.Queryable do defp rewrite_combinations(%{combinations: []} = query), do: query - defp rewrite_combinations(%{combinations: combinations} = query) do - combinations = - Enum.map(combinations, fn {type, query} -> - {type, query |> Query.exclude(:select) |> Query.select(1)} - end) - - %{query | combinations: combinations} + defp rewrite_combinations(query) do + query + |> Query.subquery() + |> Queryable.Ecto.SubQuery.to_query() end def one(name, queryable, tuplet) do diff --git a/test/ecto/repo_test.exs b/test/ecto/repo_test.exs index 97c01bfe4b..bd6248f711 100644 --- a/test/ecto/repo_test.exs +++ b/test/ecto/repo_test.exs @@ -565,18 +565,29 @@ defmodule Ecto.RepoTest do "#Ecto.Query" end - test "overrides any select" do + test "overrides any select without combinations" do from(MySchema, select: true) |> TestRepo.exists?() assert_received {:all, query} assert inspect(query) == "#Ecto.Query" + end - from(MySchema, union: ^from(MySchema, select: true)) |> TestRepo.exists?() - assert_received {:all, query} + test "wraps combinations in a subquery before overriding the select" do + query = from(m in MySchema, select: m.id, distinct: true) + combination = from(m in MySchema, select: m.id) - assert inspect(query) == - "#Ecto.Query" + for type <- [:union, :union_all, :except, :except_all, :intersect, :intersect_all] do + TestRepo.exists?(%{query | combinations: [{type, combination}]}) + assert_received {:all, exists_query} + + assert %{from: %{source: %Ecto.SubQuery{query: inner_query}}, combinations: []} = exists_query + assert %{select: %{expr: 1}, limit: %{expr: 1}, distinct: nil} = exists_query + assert [{^type, inner_combination}] = inner_query.combinations + assert inner_query.select.expr != 1 + assert inner_query.distinct != nil + assert inner_combination.select.expr != 1 + end end end