rel8-1.5.0.0: src/Rel8/Query/Aggregate.hs
{-# language FlexibleContexts #-}
{-# language MonoLocalBinds #-}
{-# language ScopedTypeVariables #-}
module Rel8.Query.Aggregate
( aggregate
, aggregate1
, aggregateU
, countRows
)
where
-- base
import Control.Applicative (liftA2)
import Data.Int ( Int64 )
import Prelude
-- opaleye
import qualified Opaleye.Adaptors as Opaleye
import qualified Opaleye.Aggregate as Opaleye
-- rel8
import Rel8.Aggregate (Aggregator' (Aggregator), Aggregator)
import Rel8.Aggregate.Fold (Fallback (Fallback))
import Rel8.Expr ( Expr )
import Rel8.Expr.Aggregate ( countStar )
import Rel8.Expr.Bool (true)
import Rel8.Query ( Query )
import Rel8.Query.Maybe ( optional )
import Rel8.Query.Opaleye ( mapOpaleye )
import Rel8.Table (Table)
import Rel8.Table.Maybe (fromMaybeTable)
import Rel8.Table.Opaleye (unpackspec)
-- | Apply an 'Aggregator' to all rows returned by a 'Query'. If the 'Query'
-- is empty, then a single \"fallback\" row is returned, composed of the
-- identity elements of the constituent aggregation functions.
aggregate :: (Table Expr i, Table Expr a) => Aggregator i a -> Query i -> Query a
aggregate aggregator@(Aggregator (Fallback fallback) _) =
fmap (fromMaybeTable fallback) . optional . aggregate1 aggregator
-- | Apply an 'Rel8.Aggregator1' to all rows returned by a 'Query'. If
-- the 'Query' is empty, then zero rows are returned.
aggregate1 :: Table Expr i => Aggregator' fold i a -> Query i -> Query a
aggregate1 = aggregateU unpackspec
aggregateU :: Opaleye.Unpackspec i i -> Aggregator' fold i a -> Query i -> Query a
aggregateU unpack (Aggregator _ aggregator) =
mapOpaleye (Opaleye.aggregateExplicit unpack aggregator)
-- | Count the number of rows returned by a query. Note that this is different
-- from @countStar@, as even if the given query yields no rows, @countRows@
-- will return @0@.
countRows :: Query a -> Query (Expr Int64)
countRows = aggregate countStar . (true <$)