Skip to content

Commit b654fa0

Browse files
committed
support subqueries in order_by, group_by, distinct, windows
ecto_sql support for elixir-ecto#607
1 parent 942f8ac commit b654fa0

File tree

4 files changed

+45
-18
lines changed

4 files changed

+45
-18
lines changed

lib/ecto/adapters/myxql/connection.ex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ if Code.ensure_loaded?(MyXQL) do
7575
## Query
7676

7777
@parent_as __MODULE__
78-
alias Ecto.Query.{BooleanExpr, JoinExpr, QueryExpr, WithExpr}
78+
alias Ecto.Query.{BooleanExpr, ByExpr, JoinExpr, QueryExpr, WithExpr}
7979

8080
@impl true
8181
def all(query, as_prefix \\ []) do
@@ -319,10 +319,10 @@ if Code.ensure_loaded?(MyXQL) do
319319
end
320320

321321
defp distinct(nil, _sources, _query), do: []
322-
defp distinct(%QueryExpr{expr: true}, _sources, _query), do: "DISTINCT "
323-
defp distinct(%QueryExpr{expr: false}, _sources, _query), do: []
322+
defp distinct(%ByExpr{expr: true}, _sources, _query), do: "DISTINCT "
323+
defp distinct(%ByExpr{expr: false}, _sources, _query), do: []
324324

325-
defp distinct(%QueryExpr{expr: exprs}, _sources, query) when is_list(exprs) do
325+
defp distinct(%ByExpr{expr: exprs}, _sources, query) when is_list(exprs) do
326326
error!(query, "DISTINCT with multiple columns is not supported by MySQL")
327327
end
328328

@@ -511,7 +511,7 @@ if Code.ensure_loaded?(MyXQL) do
511511
defp group_by(%{group_bys: group_bys} = query, sources) do
512512
[
513513
" GROUP BY "
514-
| Enum.map_intersperse(group_bys, ", ", fn %QueryExpr{expr: expr} ->
514+
| Enum.map_intersperse(group_bys, ", ", fn %ByExpr{expr: expr} ->
515515
Enum.map_intersperse(expr, ", ", &expr(&1, sources, query))
516516
end)
517517
]
@@ -549,7 +549,7 @@ if Code.ensure_loaded?(MyXQL) do
549549
defp order_by(%{order_bys: order_bys} = query, sources) do
550550
[
551551
" ORDER BY "
552-
| Enum.map_intersperse(order_bys, ", ", fn %QueryExpr{expr: expr} ->
552+
| Enum.map_intersperse(order_bys, ", ", fn %ByExpr{expr: expr} ->
553553
Enum.map_intersperse(expr, ", ", &order_by_expr(&1, sources, query))
554554
end)
555555
]

lib/ecto/adapters/postgres/connection.ex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ if Code.ensure_loaded?(Postgrex) do
155155
end
156156

157157
@parent_as __MODULE__
158-
alias Ecto.Query.{BooleanExpr, JoinExpr, QueryExpr, WithExpr}
158+
alias Ecto.Query.{BooleanExpr, ByExpr, JoinExpr, QueryExpr, WithExpr}
159159

160160
@impl true
161161
def all(query, as_prefix \\ []) do
@@ -551,11 +551,11 @@ if Code.ensure_loaded?(Postgrex) do
551551
end
552552

553553
defp distinct(nil, _, _), do: {[], []}
554-
defp distinct(%QueryExpr{expr: []}, _, _), do: {[], []}
555-
defp distinct(%QueryExpr{expr: true}, _, _), do: {" DISTINCT", []}
556-
defp distinct(%QueryExpr{expr: false}, _, _), do: {[], []}
554+
defp distinct(%ByExpr{expr: []}, _, _), do: {[], []}
555+
defp distinct(%ByExpr{expr: true}, _, _), do: {" DISTINCT", []}
556+
defp distinct(%ByExpr{expr: false}, _, _), do: {[], []}
557557

558-
defp distinct(%QueryExpr{expr: exprs}, sources, query) do
558+
defp distinct(%ByExpr{expr: exprs}, sources, query) do
559559
{[
560560
" DISTINCT ON (",
561561
Enum.map_intersperse(exprs, ", ", fn {_, expr} -> expr(expr, sources, query) end),
@@ -772,7 +772,7 @@ if Code.ensure_loaded?(Postgrex) do
772772
[
773773
" GROUP BY "
774774
| Enum.map_intersperse(group_bys, ", ", fn
775-
%QueryExpr{expr: expr} ->
775+
%ByExpr{expr: expr} ->
776776
Enum.map_intersperse(expr, ", ", &expr(&1, sources, query))
777777
end)
778778
]

lib/ecto/adapters/tds/connection.ex

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ if Code.ensure_loaded?(Tds) do
149149

150150
@parent_as __MODULE__
151151
alias Ecto.Query
152-
alias Ecto.Query.{BooleanExpr, JoinExpr, QueryExpr, WithExpr}
152+
alias Ecto.Query.{BooleanExpr, ByExpr, JoinExpr, QueryExpr, WithExpr}
153153

154154
@impl true
155155
def all(query, as_prefix \\ []) do
@@ -390,10 +390,10 @@ if Code.ensure_loaded?(Tds) do
390390
end
391391

392392
defp distinct(nil, _sources, _query), do: []
393-
defp distinct(%QueryExpr{expr: true}, _sources, _query), do: "DISTINCT "
394-
defp distinct(%QueryExpr{expr: false}, _sources, _query), do: []
393+
defp distinct(%ByExpr{expr: true}, _sources, _query), do: "DISTINCT "
394+
defp distinct(%ByExpr{expr: false}, _sources, _query), do: []
395395

396-
defp distinct(%QueryExpr{expr: exprs}, _sources, query) when is_list(exprs) do
396+
defp distinct(%ByExpr{expr: exprs}, _sources, query) when is_list(exprs) do
397397
error!(
398398
query,
399399
"DISTINCT with multiple columns is not supported by MsSQL. " <>
@@ -584,7 +584,7 @@ if Code.ensure_loaded?(Tds) do
584584
defp group_by(%{group_bys: group_bys} = query, sources) do
585585
[
586586
" GROUP BY "
587-
| Enum.map_intersperse(group_bys, ", ", fn %QueryExpr{expr: expr} ->
587+
| Enum.map_intersperse(group_bys, ", ", fn %ByExpr{expr: expr} ->
588588
Enum.map_intersperse(expr, ", ", &expr(&1, sources, query))
589589
end)
590590
]
@@ -595,7 +595,7 @@ if Code.ensure_loaded?(Tds) do
595595
defp order_by(%{order_bys: order_bys} = query, sources) do
596596
[
597597
" ORDER BY "
598-
| Enum.map_intersperse(order_bys, ", ", fn %QueryExpr{expr: expr} ->
598+
| Enum.map_intersperse(order_bys, ", ", fn %ByExpr{expr: expr} ->
599599
Enum.map_intersperse(expr, ", ", &order_by_expr(&1, sources, query))
600600
end)
601601
]

test/ecto/adapters/postgres_test.exs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,10 @@ defmodule Ecto.Adapters.PostgresTest do
530530

531531
query = Schema |> distinct(false) |> select([r], {r.x, r.y}) |> plan()
532532
assert all(query) == ~s{SELECT s0."x", s0."y" FROM "schema" AS s0}
533+
534+
query = (from row in Schema, as: :r, select: row.x) |> distinct(exists(from other_schema in "schema", where: other_schema.x == parent_as(:r).x, select: [other_schema.x])) |> plan()
535+
536+
assert all(query) == ~s{SELECT DISTINCT ON (exists((SELECT ss0."x" AS "result" FROM "schema" AS ss0 WHERE (ss0."x" = s0."x")))) s0."x" FROM "schema" AS s0}
533537
end
534538

535539
test "distinct with order by" do
@@ -618,6 +622,14 @@ defmodule Ecto.Adapters.PostgresTest do
618622
assert all(query) ==
619623
~s{SELECT s0."x" FROM "schema" AS s0 ORDER BY s0."x" ASC NULLS FIRST, s0."y" DESC NULLS FIRST}
620624

625+
query =
626+
(from row in Schema, as: :r)
627+
|> order_by(asc: exists(from other_schema in "schema", where: other_schema.x == parent_as(:r).x, select: [other_schema.x]))
628+
|> select([r], r.x)
629+
|> plan()
630+
631+
assert all(query) == ~s{SELECT s0."x" FROM "schema" AS s0 ORDER BY exists((SELECT ss0."x" AS "result" FROM "schema" AS ss0 WHERE (ss0."x" = s0."x")))}
632+
621633
query =
622634
Schema
623635
|> order_by([r], asc_nulls_last: r.x, desc_nulls_last: r.y)
@@ -1057,6 +1069,10 @@ defmodule Ecto.Adapters.PostgresTest do
10571069

10581070
query = Schema |> group_by([r], []) |> select([r], r.x) |> plan()
10591071
assert all(query) == ~s{SELECT s0."x" FROM "schema" AS s0}
1072+
1073+
query = (from row in Schema, as: :r, select: row.x) |> group_by([r], exists(from other_schema in "schema", where: other_schema.x == parent_as(:r).x, select: [other_schema.x])) |> plan()
1074+
1075+
assert all(query) == ~s{SELECT s0."x" FROM "schema" AS s0 GROUP BY exists((SELECT ss0."x" AS "result" FROM "schema" AS ss0 WHERE (ss0."x" = s0."x")))}
10601076
end
10611077

10621078
test "arrays and sigils" do
@@ -1364,6 +1380,17 @@ defmodule Ecto.Adapters.PostgresTest do
13641380
~s{SELECT s0."x" FROM "schema" AS s0 WINDOW "w" AS (PARTITION BY s0."x")}
13651381
end
13661382

1383+
test "window with subquery" do
1384+
query =
1385+
(from row in Schema, as: :r)
1386+
|> select([r], r.x)
1387+
|> windows([r], w: [order_by: exists(from other_schema in "schema", where: other_schema.x == parent_as(:r).x, select: [other_schema.x])])
1388+
|> plan
1389+
1390+
assert all(query) ==
1391+
~s{SELECT s0."x" FROM "schema" AS s0 WINDOW "w" AS (ORDER BY exists((SELECT ss0."x" AS "result" FROM "schema" AS ss0 WHERE (ss0."x" = s0."x"))))}
1392+
end
1393+
13671394
test "two windows" do
13681395
query =
13691396
Schema

0 commit comments

Comments
 (0)