rel8-internal
Safe HaskellNone
LanguageHaskell2010

Rel8.Internal.Aggregate

Synopsis

Documentation

data Aggregator' (fold :: Fold) i a Source #

Aggregator' is the most general form of "aggregator", of which Aggregator and Aggregator1 are special cases. Aggregator's are comprised of aggregation functions and/or GROUP BY clauses.

Aggregation functions operating on individual Exprs such as sum can be combined into Aggregators operating on larger types using the Applicative, Profunctor and ProductProfunctor interfaces. Working with Profunctors can sometimes be awkward so for every sum we also provide a sumOn which bundles an lmap. For complex aggregations, we recommend using these functions along with ApplicativeDo, BlockArguments, OverloadedRecordDot and RecordWildCards:

data Input f = Input
  { orderId :: Column f OrderId
  , customerId :: Column f CustomerId
  , productId :: Column f ProductId
  , quantity :: Column f Int64
  , price :: Column f Scientific
  }
  deriving (Generic, Rel8able)


totalPrice :: Input Expr -> Expr Scientific
totalPrice input = fromIntegral input.quantity * input.price


data Result f = Result
  { customerId :: Column f CustomerId
  , totalOrders :: Column f Int64
  , productsOrdered :: Column f Int64
  , totalPrice :: Column f Scientific
  }
  deriving (Generic, Rel8able)


allResults :: Query (Result Expr)
allResults =
  aggregate
    do
      customerId <- groupByOn (.customerId)
      totalOrders <- countDistinctOn (.orderId)
      productsOrdered <- countDistinctOn (.productId)
      totalPrice <- sumOn totalPrice
      pure Result {..}
    do
      order <- each orderSchema
      orderLine <- each orderLineSchema
      where_ $ order.id ==. orderLine.orderId
      pure
        Input
          { orderId = order.id
          , customerId = order.customerId
          , productId = orderLine.productId
          , quantity = orderLine.quantity
          , price = orderLine.price
          }

Constructors

Aggregator !(Fallback fold a) !(Aggregator i a) 

Instances

Instances details
ProductProfunctor (Aggregator' fold) Source # 
Instance details

Defined in Rel8.Internal.Aggregate

Methods

purePP :: b -> Aggregator' fold a b

(****) :: Aggregator' fold a (b -> c) -> Aggregator' fold a b -> Aggregator' fold a c

empty :: Aggregator' fold () ()

(***!) :: Aggregator' fold a b -> Aggregator' fold a' b' -> Aggregator' fold (a, a') (b, b')

SumProfunctor (Aggregator' fold) Source # 
Instance details

Defined in Rel8.Internal.Aggregate

Methods

(+++!) :: Aggregator' fold a b -> Aggregator' fold a' b' -> Aggregator' fold (Either a a') (Either b b')

Profunctor (Aggregator' fold) Source # 
Instance details

Defined in Rel8.Internal.Aggregate

Methods

dimap :: (a -> b) -> (c -> d) -> Aggregator' fold b c -> Aggregator' fold a d

lmap :: (a -> b) -> Aggregator' fold b c -> Aggregator' fold a c

rmap :: (b -> c) -> Aggregator' fold a b -> Aggregator' fold a c

(#.) :: forall a b c q. Coercible c b => q b c -> Aggregator' fold a b -> Aggregator' fold a c

(.#) :: forall a b c q. Coercible b a => Aggregator' fold b c -> q a b -> Aggregator' fold a c

Applicative (Aggregator' fold i) Source # 
Instance details

Defined in Rel8.Internal.Aggregate

Methods

pure :: a -> Aggregator' fold i a #

(<*>) :: Aggregator' fold i (a -> b) -> Aggregator' fold i a -> Aggregator' fold i b #

liftA2 :: (a -> b -> c) -> Aggregator' fold i a -> Aggregator' fold i b -> Aggregator' fold i c #

(*>) :: Aggregator' fold i a -> Aggregator' fold i b -> Aggregator' fold i b #

(<*) :: Aggregator' fold i a -> Aggregator' fold i b -> Aggregator' fold i a #

Functor (Aggregator' fold i) Source # 
Instance details

Defined in Rel8.Internal.Aggregate

Methods

fmap :: (a -> b) -> Aggregator' fold i a -> Aggregator' fold i b #

(<$) :: a -> Aggregator' fold i b -> Aggregator' fold i a #

Apply (Aggregator' fold i) Source # 
Instance details

Defined in Rel8.Internal.Aggregate

Methods

(<.>) :: Aggregator' fold i (a -> b) -> Aggregator' fold i a -> Aggregator' fold i b

(.>) :: Aggregator' fold i a -> Aggregator' fold i b -> Aggregator' fold i b

(<.) :: Aggregator' fold i a -> Aggregator' fold i b -> Aggregator' fold i a

liftF2 :: (a -> b -> c) -> Aggregator' fold i a -> Aggregator' fold i b -> Aggregator' fold i c

type Aggregator = Aggregator' 'Full Source #

An Aggregator takes a Query producing a collection of rows of type a and transforms it into a Query producing a single row of type b. If the given Query produces an empty collection of rows, then the single row in the resulting Query contains the identity values of the aggregation functions comprising the Aggregator (i.e., 0 for sum, false for or, etc.).

Aggregator is a special form of Aggregator' parameterised by Full.

type Aggregator1 = Aggregator' 'Semi Source #

An Aggregator1 takes a collection of rows of type a, groups them, and transforms each group into a single row of type b. This corresponds to aggregators using GROUP BY in SQL. If given an empty collection of rows, Aggregator1 will have no groups and will therefore also return an empty collection of rows.

Aggregator1 is a special form of Aggregator' parameterised by Semi.

toAggregator :: forall a (fold :: Fold) i (fold' :: Fold). a -> Aggregator' fold i a -> Aggregator' fold' i a Source #

Given a value to fall back on if given an empty collection of rows, toAggregator turns an Aggregator1 into an Aggregator.

toAggregator1 :: forall (fold :: Fold) i a. Aggregator' fold i a -> Aggregator1 i a Source #

filterWhereExplicit :: forall a i (fold :: Fold). IfPP a a -> (i -> Expr Bool) -> Aggregator i a -> Aggregator' fold i a Source #

unsafeMakeAggregator :: forall i o (fold :: Fold) i' o'. (i -> i') -> (o' -> o) -> Fallback fold o -> Aggregator i' o' -> Aggregator' fold i o Source #