1{-# language FlexibleContexts #-}
2{-# language NamedFieldPuns #-}
3{-# language ScopedTypeVariables #-}
4{-# language TypeApplications #-}
5{-# language TypeFamilies #-}
6{-# language ViewPatterns #-}
8module Rel8.Table.Aggregate
10 , listAgg, nonEmptyAgg
15import Data.Functor.Identity ( Identity( Identity ) )
19import Rel8.Aggregate ( Aggregate, Aggregates )
20import Rel8.Expr ( Expr )
21import Rel8.Expr.Aggregate
26import Rel8.Schema.Dict ( Dict( Dict ) )
27import Rel8.Schema.HTable ( HTable, hfield, htabulate )
28import Rel8.Schema.HTable.Vectorize ( hvectorize )
29import Rel8.Schema.Null ( Sql )
30import Rel8.Schema.Spec ( Spec( Spec, info ) )
31import Rel8.Table ( toColumns, fromColumns )
32import Rel8.Table.Eq ( EqTable, eqTable )
33import Rel8.Table.List ( ListTable )
34import Rel8.Table.NonEmpty ( NonEmptyTable )
35import Rel8.Type.Eq ( DBEq )
38-- | Group equal tables together. This works by aggregating each column in the
39-- given table with 'groupByExpr'.
41-- For example, if we have a table of items, we could group the items by the
42-- order they belong to:
45-- itemsByOrder :: Query (OrderId Expr, ListTable Expr (Item Expr))
46-- itemsByOrder = aggregate $ do
47-- item <- each itemSchema
48-- let orderId = groupBy (itemOrderId item)
49-- let orderItems = listAgg item
50-- pure (orderId, orderItems)
52groupBy :: forall exprs aggregates. (EqTable exprs, Aggregates aggregates exprs)
53 => exprs -> aggregates
54groupBy = fromColumns . hgroupBy (eqTable @exprs) . toColumns
57hgroupBy :: HTable t => t (Dict (Sql DBEq)) -> t Expr -> t Aggregate
58hgroupBy eqs exprs = htabulate $ \field ->
59 case hfield eqs field of
60 Dict -> case hfield exprs field of
61 expr -> groupByExpr expr
64-- | Aggregate rows into a single row containing an array of all aggregated
65-- rows. This can be used to associate multiple rows with a single row, without
66-- changing the over cardinality of the query. This allows you to essentially
67-- return a tree-like structure from queries.
69-- For example, if we have a table of orders and each orders contains multiple
70-- items, we could aggregate the table of orders, pairing each order with its
74-- ordersWithItems :: Query (Order Expr, ListTable Expr (Item Expr))
75-- ordersWithItems = do
76-- order <- each orderSchema
77-- items <- aggregate $ listAgg <$> itemsFromOrder order
78-- return (order, items)
80listAgg :: Aggregates aggregates exprs => exprs -> ListTable Aggregate aggregates
81listAgg (toColumns -> exprs) = fromColumns $
83 (\Spec {info} (Identity a) -> slistAggExpr info a)
87-- | Like 'listAgg', but the result is guaranteed to be a non-empty list.
88nonEmptyAgg :: Aggregates aggregates exprs => exprs -> NonEmptyTable Aggregate aggregates
89nonEmptyAgg (toColumns -> exprs) = fromColumns $
91 (\Spec {info} (Identity a) -> snonEmptyAggExpr info a)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list