on 4475085 help sign in
rel8/src/Rel8/Table/Aggregate.hs
80 lines 2.6 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 , headAgg
11 , listAgg, nonEmptyAgg
12 )
13where
15-- base
16import Data.Functor.Identity ( Identity( Identity ) )
17import Prelude
19-- rel8
20import Rel8.Aggregate ( Aggregate, Col( A ) )
21import Rel8.Expr ( Expr, Col( E ) )
22import Rel8.Expr.Aggregate
23 ( groupByExpr
24 , headAggExpr
25 , slistAggExpr
26 , snonEmptyAggExpr
27 )
28import Rel8.Schema.Dict ( Dict( Dict ) )
29import Rel8.Schema.HTable ( hfield, hmap, htabulate )
30import Rel8.Schema.HTable.Vectorize ( hvectorize )
31import Rel8.Schema.Spec ( SSpec( SSpec, info ) )
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 E expr -> A $ groupByExpr expr
47-- | Keep only the first row.
48headAgg :: Table Expr a => a -> Aggregate a
49headAgg = fromColumns . hmap (\(E a) -> A $ headAggExpr a) . toColumns
52-- | Aggregate rows into a single row containing an array of all aggregated
53-- rows. This can be used to associate multiple rows with a single row, without
54-- changing the over cardinality of the query. This allows you to essentially
55-- return a tree-like structure from queries.
56--
57-- For example, if we have a table of orders and each orders contains multiple
58-- items, we could aggregate the table of orders, pairing each order with its
59-- items:
60--
61-- @
62-- ordersWithItems :: Query (Order Expr, ListTable (Item Expr))
63-- ordersWithItems = do
64-- order <- each orderSchema
65-- items <- aggregate $ listAgg <$> itemsFromOrder order
66-- return (order, items)
67-- @
68listAgg :: Table Expr a => a -> Aggregate (ListTable a)
69listAgg (toColumns -> exprs) = fromColumns $
70 hvectorize
71 (\SSpec {info} (Identity (E a)) -> A $ slistAggExpr info a)
72 (pure exprs)
75-- | Like 'listAgg', but the result is guaranteed to be a non-empty list.
76nonEmptyAgg :: Table Expr a => a -> Aggregate (NonEmptyTable a)
77nonEmptyAgg (toColumns -> exprs) = fromColumns $
78 hvectorize
79 (\SSpec {info} (Identity (E a)) -> A $ snonEmptyAggExpr info a)
80 (pure exprs)