Skip to content

Commit a46595e

Browse files
Support Ecto.Query.with_ties/3 (#471)
1 parent c1bd4d6 commit a46595e

7 files changed

Lines changed: 48 additions & 4 deletions

File tree

lib/ecto/adapters/myxql/connection.ex

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,10 @@ if Code.ensure_loaded?(MyXQL) do
463463
end
464464

465465
defp limit(%{limit: nil}, _sources), do: []
466-
defp limit(%{limit: %QueryExpr{expr: expr}} = query, sources) do
466+
defp limit(%{limit: %{with_ties: true}} = query, _sources) do
467+
error!(query, "MySQL adapter does not support the `:with_ties` limit option")
468+
end
469+
defp limit(%{limit: %{expr: expr}} = query, sources) do
467470
[" LIMIT " | expr(expr, sources, query)]
468471
end
469472

lib/ecto/adapters/postgres/connection.ex

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,14 @@ if Code.ensure_loaded?(Postgrex) do
594594
end
595595

596596
defp limit(%{limit: nil}, _sources), do: []
597-
defp limit(%{limit: %QueryExpr{expr: expr}} = query, sources) do
597+
defp limit(%{limit: %{with_ties: true}, order_bys: []} = query, _sources) do
598+
error!(query, "PostgreSQL adapter requires an `order_by` clause if the " <>
599+
"`:with_ties` limit option is `true`")
600+
end
601+
defp limit(%{limit: %{expr: expr, with_ties: true}} = query, sources) do
602+
[" FETCH FIRST ", expr(expr, sources, query) | " ROWS WITH TIES"]
603+
end
604+
defp limit(%{limit: %{expr: expr}} = query, sources) do
598605
[" LIMIT " | expr(expr, sources, query)]
599606
end
600607

lib/ecto/adapters/tds/connection.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,9 +579,13 @@ if Code.ensure_loaded?(Tds) do
579579

580580
defp limit(%Query{limit: nil}, _sources), do: []
581581

582+
defp limit(%Query{limit: %{with_ties: true}} = query, _sources) do
583+
error!(query, "Tds adapter does not support the `:with_ties` limit option")
584+
end
585+
582586
defp limit(
583587
%Query{
584-
limit: %QueryExpr{
588+
limit: %{
585589
expr: expr
586590
}
587591
} = query,

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
77
"deep_merge": {:hex, :deep_merge, "0.2.0", "c1050fa2edf4848b9f556fba1b75afc66608a4219659e3311d9c9427b5b680b3", [:mix], [], "hexpm", "e3bf435a54ed27b0ba3a01eb117ae017988804e136edcbe8a6a14c310daa966e"},
88
"earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"},
9-
"ecto": {:git, "https://github.com/elixir-ecto/ecto.git", "9561024c0ae494b7c1d3d9822fa079f00b127fdd", []},
9+
"ecto": {:git, "https://github.com/elixir-ecto/ecto.git", "ab0771ef7ea0825f0dadfe02bfbe04d946ca5f07", []},
1010
"ex_doc": {:hex, :ex_doc, "0.29.0", "4a1cb903ce746aceef9c1f9ae8a6c12b742a5461e6959b9d3b24d813ffbea146", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "f096adb8bbca677d35d278223361c7792d496b3fc0d0224c9d4bc2f651af5db1"},
1111
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
1212
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},

test/ecto/adapters/myxql_test.exs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,15 @@ defmodule Ecto.Adapters.MyXQLTest do
441441
assert all(query) == ~s{SELECT TRUE FROM `schema` AS s0 LIMIT 3 OFFSET 5}
442442
end
443443

444+
test "limit `:with_ties` option" do
445+
msg = ~r"MySQL adapter does not support the `:with_ties` limit option"
446+
query = Schema |> limit([r], 3) |> with_ties(true) |> select([], true) |> plan()
447+
448+
assert_raise Ecto.QueryError, msg, fn ->
449+
all(query)
450+
end
451+
end
452+
444453
test "lock" do
445454
query = Schema |> lock("LOCK IN SHARE MODE") |> select([], true) |> plan()
446455
assert all(query) == ~s{SELECT TRUE FROM `schema` AS s0 LOCK IN SHARE MODE}

test/ecto/adapters/postgres_test.exs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,18 @@ defmodule Ecto.Adapters.PostgresTest do
561561
assert all(query) == ~s{SELECT TRUE FROM "schema" AS s0 LIMIT 3 OFFSET 5}
562562
end
563563

564+
test "limit `:with_ties` option" do
565+
query = Schema |> order_by([r], r.x) |> limit([r], 3) |> with_ties(true) |> select([], true) |> plan()
566+
assert all(query) == ~s{SELECT TRUE FROM "schema" AS s0 ORDER BY s0."x" FETCH FIRST 3 ROWS WITH TIES}
567+
568+
msg = ~r"PostgreSQL adapter requires an `order_by` clause if the `:with_ties` limit option is `true`"
569+
query = Schema |> limit([r], 3) |> with_ties(true) |> select([], true) |> plan()
570+
571+
assert_raise Ecto.QueryError, msg, fn ->
572+
all(query)
573+
end
574+
end
575+
564576
test "lock" do
565577
query = Schema |> lock("FOR SHARE NOWAIT") |> select([], true) |> plan()
566578
assert all(query) == ~s{SELECT TRUE FROM "schema" AS s0 FOR SHARE NOWAIT}

test/ecto/adapters/tds_test.exs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,15 @@ defmodule Ecto.Adapters.TdsTest do
560560
end
561561
end
562562

563+
test "limit `:with_ties` option" do
564+
msg = ~r"Tds adapter does not support the `:with_ties` limit option"
565+
query = Schema |> limit([r], 3) |> with_ties(true) |> select([], true) |> plan()
566+
567+
assert_raise Ecto.QueryError, msg, fn ->
568+
all(query)
569+
end
570+
end
571+
563572
test "lock" do
564573
query = Schema |> lock("NOLOCK") |> select([], true) |> plan()
565574
assert all(query) == ~s{SELECT CAST(1 as bit) FROM [schema] AS s0 OPTION (NOLOCK)}

0 commit comments

Comments
 (0)