on db148ff help sign in
rel8/src/Rel8/Table/Aggregate.hs
91 lines 3.0 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, nonEmptyAgg
10 , listAggWithOrder, nonEmptyAggWithOrder
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
22 ( groupByExpr
23 , listAggExpr
24 , listAggExprWithOrder
25 , nonEmptyAggExpr
26 , nonEmptyAggExprWithOrder
27 )
28import Rel8.Order ( Order )
29import Rel8.Schema.Dict ( Dict( Dict ) )
30import Rel8.Schema.HTable ( htabulate, hfield )
31import Rel8.Schema.HTable.Vectorize ( hvectorize )
32import Rel8.Table ( Table, toColumns, fromColumns )
33import Rel8.Table.Eq ( EqTable, eqTable )
34import Rel8.Table.List ( ListTable )
35import Rel8.Table.NonEmpty ( NonEmptyTable )
38-- | Group equal tables together. This works by aggregating each column in the
39-- given table with 'groupByExpr'.
40groupBy :: forall exprs. EqTable exprs => exprs -> Aggregate exprs
41groupBy (toColumns -> exprs) = fromColumns $ htabulate $ \field ->
42 case hfield (eqTable @exprs) field of
43 Dict -> case hfield exprs field of
44 DB expr -> Aggregation $ groupByExpr expr
47-- | Aggregate rows into a single row containing an array of all aggregated
48-- rows. This can be used to associate multiple rows with a single row, without
49-- changing the over cardinality of the query. This allows you to essentially
50-- return a tree-like structure from queries.
51--
52-- For example, if we have a table of orders and each orders contains multiple
53-- items, we could aggregate the table of orders, pairing each order with its
54-- items:
55--
56-- @
57-- ordersWithItems :: Query (Order Expr, ListTable (Item Expr))
58-- ordersWithItems = do
59-- order <- each orderSchema
60-- items <- aggregate $ listAgg <$> itemsFromOrder order
61-- return (order, items)
62-- @
63listAgg :: Table Expr a => a -> Aggregate (ListTable a)
64listAgg (toColumns -> exprs) = fromColumns $
65 hvectorize
66 (\_ (Identity (DB a)) -> Aggregation $ listAggExpr a)
67 (pure exprs)
70-- | Like 'listAgg', but the result is guaranteed to be a non-empty list.
71nonEmptyAgg :: Table Expr a => a -> Aggregate (NonEmptyTable a)
72nonEmptyAgg (toColumns -> exprs) = fromColumns $
73 hvectorize
74 (\_ (Identity (DB a)) -> Aggregation $ nonEmptyAggExpr a)
75 (pure exprs)
78listAggWithOrder :: Table Expr a
79 => Order o -> o -> a -> Aggregate (ListTable a)
80listAggWithOrder order o (toColumns -> exprs) = fromColumns $
81 hvectorize
82 (\_ (Identity (DB x)) -> Aggregation $ listAggExprWithOrder order o x)
83 (pure exprs)
86nonEmptyAggWithOrder :: Table Expr a
87 => Order o -> o -> a -> Aggregate (NonEmptyTable a)
88nonEmptyAggWithOrder order o (toColumns -> exprs) = fromColumns $
89 hvectorize
90 (\_ (Identity (DB x)) -> Aggregation $ nonEmptyAggExprWithOrder order o x)
91 (pure exprs)