Skip to content

Commit 1858dcf

Browse files
committed
cope with distinct: true
1 parent 45fd270 commit 1858dcf

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

lib/ecto/adapters/postgres/connection.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,16 @@ if Code.ensure_loaded?(Postgrex) do
533533
do: "TRUE"
534534

535535
defp select_fields(fields, sources, query) do
536+
# NB: append order_by fields if distinct: true specified
537+
fields = case query.distinct do
538+
%Ecto.Query.ByExpr{expr: true} ->
539+
order_by_fields = Enum.map(query.order_bys, & Keyword.values(&1.expr)) |> List.flatten()
540+
Enum.reduce(order_by_fields, fields, fn
541+
{{:., _, [{:&, [], [idx]}, _]}, _, _} = field, acc when idx > 0 -> acc ++ [field]
542+
_field, acc -> acc
543+
end)
544+
_ -> fields
545+
end
536546
Enum.map_intersperse(fields, ", ", fn
537547
{:&, _, [idx]} ->
538548
case elem(sources, idx) do

test/ecto/adapters/postgres_test.exs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,32 @@ defmodule Ecto.Adapters.PostgresTest do
579579
~s{SELECT DISTINCT ON (s0."x") s0."x" FROM "schema" AS s0 ORDER BY s0."x" DESC}
580580
end
581581

582+
test "distinct true with assocs" do
583+
query =
584+
Schema |> join(:inner, [r], assoc(r, :permalink)) |> order_by([r, p], [p.id]) |> distinct([r], true) |> select([r], r.x) |> plan()
585+
586+
assert all(query) ==
587+
~s{SELECT DISTINCT s0."x", s1."id" FROM "schema" AS s0 INNER JOIN "schema3" AS s1 ON s1."id" = s0."y" ORDER BY s1."id"}
588+
589+
query =
590+
Schema |> join(:inner, [r], assoc(r, :permalink)) |> order_by([r, p], [p.id]) |> distinct([r], true) |> select([r], struct(r, [:x])) |> plan()
591+
592+
assert all(query) ==
593+
~s{SELECT DISTINCT s0."x", s1."id" FROM "schema" AS s0 INNER JOIN "schema3" AS s1 ON s1."id" = s0."y" ORDER BY s1."id"}
594+
595+
query =
596+
Schema |> join(:inner, [r], subquery(from p in Schema3, where: not is_nil(p.binary)), on: true) |> order_by([r, p], [p.id]) |> distinct([r], true) |> select([r], struct(r, [:x])) |> plan()
597+
598+
assert all(query) ==
599+
~s{SELECT DISTINCT s0."x", s1."id" FROM "schema" AS s0 INNER JOIN (SELECT ss0."id" AS "id", ss0."list1" AS "list1", ss0."list2" AS "list2", ss0."binary" AS "binary" FROM "schema3" AS ss0 WHERE (NOT (ss0."binary" IS NULL))) AS s1 ON TRUE ORDER BY s1."id"}
600+
601+
query =
602+
Schema |> join(:inner, [r], assoc(r, :permalink)) |> order_by([r], [r.id]) |> distinct([r], true) |> select([r], r.x) |> plan()
603+
604+
assert all(query) ==
605+
~s{SELECT DISTINCT s0."x" FROM "schema" AS s0 INNER JOIN "schema3" AS s1 ON s1."id" = s0."y" ORDER BY s0."id"}
606+
end
607+
582608
test "coalesce" do
583609
query = Schema |> select([s], coalesce(s.x, 5)) |> plan()
584610
assert all(query) == ~s{SELECT coalesce(s0."x", 5) FROM "schema" AS s0}

0 commit comments

Comments
 (0)