on master help sign in
Add Rel8.Aggregate.Context for backwards compatibility
25c7638Shane O'Brien
rel8.cabal+3
@@ -48,6 +48,9 @@ library
48 Rel8.Expr.Time
48 Rel8.Expr.Time
49 Rel8.Tabulate
49 Rel8.Tabulate
50
50
51+ -- deprecated
52+ Rel8.Aggregate.Context
53+
51 other-modules:
54 other-modules:
52 Rel8.Aggregate
55 Rel8.Aggregate
53
56
src/Rel8.hs−5
@@ -198,11 +198,6 @@ module Rel8
198 , and
198 , and
199 , or
199 , or
200
200
201− , Aggregates
202− , sequenceAggregate
203− , distributeAggregate
204−
205−
206 -- ** Ordering
201 -- ** Ordering
207 , orderBy
202 , orderBy
208 , Order
203 , Order
src/Rel8/Aggregate/Context.hsnew file+84
@@ -0,0 +1,84 @@
1+{-# language FlexibleContexts #-}
2+{-# language NamedFieldPuns #-}
3+{-# language ScopedTypeVariables #-}
4+{-# language TypeApplications #-}
5+{-# language TypeFamilies #-}
6+{-# language ViewPatterns #-}
7+
8+module Rel8.Aggregate.Context
9+{-# DEPRECATED "This is purely for backwards compatibility with prehistoric Rel8 and will be removed at some point." #-}
10+ ( Aggregates
11+ , aggregate
12+ , groupBy
13+ , listAgg
14+ , nonEmptyAgg
15+ )
16+where
17+
18+-- base
19+import Data.Functor.Identity ( Identity( Identity ) )
20+import Prelude
21+
22+-- opaleye
23+import qualified Opaleye.Aggregate as Opaleye
24+
25+-- rel8
26+import Rel8.Aggregate ( Aggregates, Col(..) )
27+import Rel8.Expr ( Col(..) )
28+import Rel8.Expr.Aggregate ( groupByExpr, listAggExpr, nonEmptyAggExpr )
29+import Rel8.Query ( Query )
30+import Rel8.Query.Opaleye ( mapOpaleye )
31+import Rel8.Schema.Dict ( Dict( Dict ) )
32+import Rel8.Schema.HTable ( htabulate, hfield )
33+import Rel8.Schema.HTable.Vectorize ( hvectorize )
34+import Rel8.Table ( toColumns, fromColumns )
35+import Rel8.Table.Eq ( EqTable, eqTable )
36+import Rel8.Table.List ( ListTable )
37+import Rel8.Table.NonEmpty ( NonEmptyTable )
38+import Rel8.Table.Opaleye ( aggregator )
39+
40+
41+-- | Apply an aggregation to all rows returned by a 'Query'.
42+aggregate :: Aggregates aggregates exprs => Query aggregates -> Query exprs
43+aggregate = mapOpaleye (Opaleye.aggregate aggregator) . fmap (fromColumns . toColumns)
44+
45+
46+-- | Group equal tables together. This works by aggregating each column in the
47+-- given table with 'groupByExpr'.
48+groupBy :: forall exprs aggregates. (EqTable exprs, Aggregates aggregates exprs)
49+ => exprs -> aggregates
50+groupBy (toColumns -> exprs) = fromColumns $ htabulate $ \field ->
51+ case hfield (eqTable @exprs) field of
52+ Dict -> case hfield exprs field of
53+ DB expr -> Aggregation $ groupByExpr expr
54+
55+
56+-- | Aggregate rows into a single row containing an array of all aggregated
57+-- rows. This can be used to associate multiple rows with a single row, without
58+-- changing the over cardinality of the query. This allows you to essentially
59+-- return a tree-like structure from queries.
60+--
61+-- For example, if we have a table of orders and each orders contains multiple
62+-- items, we could aggregate the table of orders, pairing each order with its
63+-- items:
64+--
65+-- @
66+-- ordersWithItems :: Query (Order Expr, ListTable (Item Expr))
67+-- ordersWithItems = do
68+-- order <- each orderSchema
69+-- items <- aggregate $ listAgg <$> itemsFromOrder order
70+-- return (order, items)
71+-- @
72+listAgg :: Aggregates aggregates exprs => exprs -> ListTable aggregates
73+listAgg (toColumns -> exprs) = fromColumns $
74+ hvectorize
75+ (\_ (Identity (DB a)) -> Aggregation $ listAggExpr a)
76+ (pure exprs)
77+
78+
79+-- | Like 'listAgg', but the result is guaranteed to be a non-empty list.
80+nonEmptyAgg :: Aggregates aggregates exprs => exprs -> NonEmptyTable aggregates
81+nonEmptyAgg (toColumns -> exprs) = fromColumns $
82+ hvectorize
83+ (\_ (Identity (DB a)) -> Aggregation $ nonEmptyAggExpr a)
84+ (pure exprs)
src/Rel8/Table/Aggregate.hs+1−11
@@ -9,8 +9,6 @@ module Rel8.Table.Aggregate
9 ( groupBy
9 ( groupBy
10 , listAgg
10 , listAgg
11 , nonEmptyAgg
11 , nonEmptyAgg
12− , sequenceAggregate
13− , distributeAggregate
14 )
12 )
15where
13where
16
14
@@ -19,7 +17,7 @@ import Data.Functor.Identity ( Identity( Identity ) )
19import Prelude
17import Prelude
20
18
21-- rel8
19-- rel8
22−import Rel8.Aggregate ( Aggregate, Aggregates, Col(..) )
20+import Rel8.Aggregate ( Aggregate, Col(..) )
23import Rel8.Expr ( Expr, Col(..) )
21import Rel8.Expr ( Expr, Col(..) )
24import Rel8.Expr.Aggregate ( groupByExpr, listAggExpr, nonEmptyAggExpr )
22import Rel8.Expr.Aggregate ( groupByExpr, listAggExpr, nonEmptyAggExpr )
25import Rel8.Schema.Dict ( Dict( Dict ) )
23import Rel8.Schema.Dict ( Dict( Dict ) )
@@ -69,11 +67,3 @@ nonEmptyAgg (toColumns -> exprs) = fromColumns $
69 hvectorize
67 hvectorize
70 (\_ (Identity (DB a)) -> Aggregation $ nonEmptyAggExpr a)
68 (\_ (Identity (DB a)) -> Aggregation $ nonEmptyAggExpr a)
71 (pure exprs)
69 (pure exprs)
72−
73−
74−sequenceAggregate :: Aggregates aggregates exprs => aggregates -> Aggregate exprs
75−sequenceAggregate = fromColumns . toColumns
76−
77−
78−distributeAggregate :: Aggregates aggregates exprs => Aggregate exprs -> aggregates
79−distributeAggregate = fromColumns . toColumns