on ca7aaef help sign in
rel8/src/Rel8/Table/Aggregate.hs
79 lines 2.7 kB history raw
1{-# language FlexibleContexts #-}
2{-# language NamedFieldPuns #-}
3{-# language ScopedTypeVariables #-}
4{-# language TypeApplications #-}
5{-# language TypeFamilies #-}
6{-# language ViewPatterns #-}
8module Rel8.Table.Aggregate
9 ( groupBy
10 , listAgg
11 , nonEmptyAgg
12 , sequenceAggregate
13 , distributeAggregate
14 )
15where
17-- base
18import Data.Functor.Identity ( Identity( Identity ) )
19import Prelude
21-- rel8
22import Rel8.Aggregate ( Aggregate, Aggregates, Col(..) )
23import Rel8.Expr ( Expr, Col(..) )
24import Rel8.Expr.Aggregate ( groupByExpr, listAggExpr, nonEmptyAggExpr )
25import Rel8.Schema.Dict ( Dict( Dict ) )
26import Rel8.Schema.HTable ( htabulate, hfield )
27import Rel8.Schema.HTable.Vectorize ( hvectorize )
28import Rel8.Table ( Table, toColumns, fromColumns )
29import Rel8.Table.Eq ( EqTable, eqTable )
30import Rel8.Table.List ( ListTable )
31import Rel8.Table.NonEmpty ( NonEmptyTable )
34-- | Group equal tables together. This works by aggregating each column in the
35-- given table with 'groupByExpr'.
36groupBy :: forall exprs. EqTable exprs => exprs -> Aggregate exprs
37groupBy (toColumns -> exprs) = fromColumns $ htabulate $ \field ->
38 case hfield (eqTable @exprs) field of
39 Dict -> case hfield exprs field of
40 DB expr -> Aggregation $ groupByExpr expr
43-- | Aggregate rows into a single row containing an array of all aggregated
44-- rows. This can be used to associate multiple rows with a single row, without
45-- changing the over cardinality of the query. This allows you to essentially
46-- return a tree-like structure from queries.
47--
48-- For example, if we have a table of orders and each orders contains multiple
49-- items, we could aggregate the table of orders, pairing each order with its
50-- items:
51--
52-- @
53-- ordersWithItems :: Query (Order Expr, ListTable (Item Expr))
54-- ordersWithItems = do
55-- order <- each orderSchema
56-- items <- aggregate $ listAgg <$> itemsFromOrder order
57-- return (order, items)
58-- @
59listAgg :: Table Expr exprs => exprs -> Aggregate (ListTable exprs)
60listAgg (toColumns -> exprs) = fromColumns $
61 hvectorize
62 (\_ (Identity (DB a)) -> Aggregation $ listAggExpr a)
63 (pure exprs)
66-- | Like 'listAgg', but the result is guaranteed to be a non-empty list.
67nonEmptyAgg :: Table Expr exprs => exprs -> Aggregate (NonEmptyTable exprs)
68nonEmptyAgg (toColumns -> exprs) = fromColumns $
69 hvectorize
70 (\_ (Identity (DB a)) -> Aggregation $ nonEmptyAggExpr a)
71 (pure exprs)
74sequenceAggregate :: Aggregates aggregates exprs => aggregates -> Aggregate exprs
75sequenceAggregate = fromColumns . toColumns
78distributeAggregate :: Aggregates aggregates exprs => Aggregate exprs -> aggregates
79distributeAggregate = fromColumns . toColumns