Skip to content

Commit 2c18421

Browse files
committed
support max_total_entries option + test
1 parent 1c9705f commit 2c18421

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

lib/scrivener/paginater/ecto/query.ex

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,30 @@ defimpl Scrivener.Paginater, for: Ecto.Query do
6767
|> exclude(:order_by)
6868
|> exclude(:select)
6969
|> select([{x, source_index}], struct(x, ^[field]))
70+
|> maybe_limit_by_max_total_entries(options)
7071
|> subquery()
7172
|> select(count("*"))
7273
|> repo.one(options)
7374
end
7475

7576
defp aggregate(query, repo, options) do
76-
repo.aggregate(query, :count, options)
77+
query
78+
|> maybe_limit_by_max_total_entries(options)
79+
|> repo.aggregate(:count, options)
80+
end
81+
82+
defp maybe_limit_by_max_total_entries(query, options) do
83+
case Keyword.get(options, :max_total_entries) do
84+
nil ->
85+
query
86+
87+
max_total_entries when is_integer(max_total_entries) and max_total_entries > 0 ->
88+
limit(query, ^max_total_entries)
89+
90+
otherwise ->
91+
raise ArgumentError,
92+
"max_total_entries must be a positive integer, got: #{inspect(otherwise)}"
93+
end
7794
end
7895

7996
defp total_pages(0, _), do: 1

test/scrivener/paginator/ecto/query_test.exs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,32 @@ defmodule Scrivener.Paginator.Ecto.QueryTest do
233233
assert page.total_entries == 130
234234
end
235235

236+
test "will respect max_total_entries passed to paginate" do
237+
create_posts()
238+
239+
page =
240+
Post
241+
|> Post.published()
242+
|> Scrivener.Ecto.Repo.paginate(options: [max_total_entries: 4])
243+
244+
assert length(page.entries) == 5
245+
assert page.total_entries == 4
246+
end
247+
248+
test "will respect max_total_entries passed to paginate with a group by clause on field on joined table" do
249+
create_posts()
250+
251+
page =
252+
Post
253+
|> join(:inner, [p], c in assoc(p, :comments))
254+
|> group_by([p, c], c.body)
255+
|> select([p, c], {c.body, count("*")})
256+
|> Scrivener.Ecto.Repo.paginate(options: [max_total_entries: 1])
257+
258+
assert length(page.entries) == 2
259+
assert page.total_entries == 1
260+
end
261+
236262
test "will use total_pages if page_numer is too large" do
237263
posts = create_posts()
238264

0 commit comments

Comments
 (0)