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