Skip to content

Commit

Permalink
Merge pull request #4 from elixir-ecto/master
Browse files Browse the repository at this point in the history
Introduce Repo.aggregate/2 instead, see elixir-ecto#3175
  • Loading branch information
sthagen committed Dec 2, 2019
2 parents 4f50190 + a840b6c commit 4e80b62
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
45 changes: 39 additions & 6 deletions lib/ecto/repo.ex
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ defmodule Ecto.Repo do
@default_dynamic_repo opts[:default_dynamic_repo] || __MODULE__
@read_only opts[:read_only] || false
@before_compile adapter
@aggregates [:count, :avg, :max, :min, :sum]

def config do
{:ok, config} = Ecto.Repo.Supervisor.runtime_config(:runtime, __MODULE__, @otp_app, [])
Expand Down Expand Up @@ -308,8 +309,20 @@ defmodule Ecto.Repo do
Ecto.Repo.Queryable.one!(get_dynamic_repo(), queryable, opts)
end

def aggregate(queryable, aggregate, field, opts \\ [])
when aggregate in [:count, :avg, :max, :min, :sum] and is_atom(field) do
def aggregate(queryable, aggregate, opts \\ [])

def aggregate(queryable, aggregate, opts)
when aggregate in [:count] and is_list(opts) do
Ecto.Repo.Queryable.aggregate(get_dynamic_repo(), queryable, aggregate, opts)
end

def aggregate(queryable, aggregate, field)
when aggregate in @aggregates and is_atom(field) do
Ecto.Repo.Queryable.aggregate(get_dynamic_repo(), queryable, aggregate, field, [])
end

def aggregate(queryable, aggregate, field, opts)
when aggregate in @aggregates and is_atom(field) and is_list(opts) do
Ecto.Repo.Queryable.aggregate(get_dynamic_repo(), queryable, aggregate, field, opts)
end

Expand Down Expand Up @@ -491,7 +504,7 @@ defmodule Ecto.Repo do

## Ecto.Adapter.Queryable

@optional_callbacks get: 3, get!: 3, get_by: 3, get_by!: 3, aggregate: 4, exists?: 2,
@optional_callbacks get: 3, get!: 3, get_by: 3, get_by!: 3, aggregate: 3, aggregate: 4, exists?: 2,
one: 2, one!: 2, preload: 3, all: 2, stream: 2, update_all: 3, delete_all: 2

@doc """
Expand Down Expand Up @@ -606,12 +619,11 @@ defmodule Ecto.Repo do
) :: Ecto.Schema.t()

@doc """
Calculate the given `aggregate` over the given `field`.
Calculate the given `aggregate`.
If the query has a limit, offset or distinct set, it will be
automatically wrapped in a subquery in order to return the
proper result. The `field` may be set to `:*`, to select on
entries overall instead of a given field.
proper result.
Any preload or select in the query will be ignored in favor of
the column being aggregated.
Expand All @@ -629,6 +641,27 @@ defmodule Ecto.Repo do
See the "Shared options" section at the module documentation for more options.
## Examples
# Returns the number of visits per blog post
Repo.aggregate(Post, :count)
# Returns the number of visits per blog post in the "private" schema path
# (in Postgres) or database (in MySQL)
Repo.aggregate(Post, :count, prefix: "private")
"""
@callback aggregate(
queryable :: Ecto.Queryable.t(),
aggregate :: :count,
opts :: Keyword.t()
) :: term | nil

@doc """
Calculate the given `aggregate` over the given `field`.
See `aggregate/2` for general considerations and options.
## Examples
# Returns the number of visits per blog post
Expand Down
6 changes: 5 additions & 1 deletion lib/ecto/repo/queryable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ defmodule Ecto.Repo.Queryable do
one!(name, query_for_get_by(queryable, clauses), opts)
end

def aggregate(name, queryable, aggregate, opts) do
one!(name, query_for_aggregate(queryable, aggregate), opts)
end

def aggregate(name, queryable, aggregate, field, opts) do
one!(name, query_for_aggregate(queryable, aggregate, field), opts)
end
Expand Down Expand Up @@ -406,7 +410,7 @@ defmodule Ecto.Repo.Queryable do
Query.where(queryable, [], ^Enum.to_list(clauses))
end

defp query_for_aggregate(queryable, aggregate, :*) do
defp query_for_aggregate(queryable, aggregate) do
query =
case prepare_for_aggregate(queryable) do
%{distinct: nil, limit: nil, offset: nil} = query ->
Expand Down
2 changes: 1 addition & 1 deletion test/ecto/repo_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ defmodule Ecto.RepoTest do
assert_received {:all, query}
assert inspect(query) == "#Ecto.Query<from m0 in Ecto.RepoTest.MySchema, select: count(m0.id)>"

TestRepo.aggregate(MySchema, :count, :*)
TestRepo.aggregate(MySchema, :count)
assert_received {:all, query}
assert inspect(query) == "#Ecto.Query<from m0 in Ecto.RepoTest.MySchema, select: count()>"
end
Expand Down

0 comments on commit 4e80b62

Please sign in to comment.