on f92d8d6 help sign in
rel8/src/Rel8/Expr/Aggregate.hs
166 lines 4.5 kB history raw
1{-# language DataKinds #-}
2{-# language ScopedTypeVariables #-}
3{-# language TypeApplications #-}
4{-# language TypeFamilies #-}
6{-# options_ghc -fno-warn-redundant-constraints #-}
8module Rel8.Expr.Aggregate
9 ( count, countDistinct, countStar, countWhere
10 , and, or
11 , min, max
12 , sum, sumWhere
13 , stringAgg
14 , groupByExpr
15 , listAggExpr, nonEmptyAggExpr
16 , sgroupByExpr
17 )
18where
20-- base
21import Data.Int ( Int64 )
22import Data.List.NonEmpty ( NonEmpty )
23import Prelude hiding ( and, max, min, null, or, sum )
25-- opaleye
26import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
28-- rel8
29import Rel8.Aggregate ( Aggregate, Aggregator(..), unsafeMakeAggregate )
30import Rel8.Expr ( Expr )
31import Rel8.Expr.Bool ( caseExpr )
32import Rel8.Expr.Opaleye
33 ( castExpr
34 , fromPrimExpr
35 , fromPrimExpr
36 , toPrimExpr
37 )
38import Rel8.Expr.Null ( null )
39import Rel8.Expr.Serialize ( litExpr )
40import Rel8.Schema.Nullability ( Nullability, Nullabilizes, nullabilization )
41import Rel8.Type.Array ( fromPrimArray )
42import Rel8.Type.Eq ( DBEq )
43import Rel8.Type.Num ( DBNum )
44import Rel8.Type.Ord ( DBMax, DBMin )
45import Rel8.Type.String ( DBString )
46import Rel8.Type.Sum ( DBSum )
49count :: Expr a -> Aggregate (Expr Int64)
50count = unsafeMakeAggregate toPrimExpr fromPrimExpr $
51 Just Aggregator
52 { operation = Opaleye.AggrCount
53 , ordering = []
54 , distinction = Opaleye.AggrAll
55 }
58countDistinct :: DBEq a => Expr a -> Aggregate (Expr Int64)
59countDistinct = unsafeMakeAggregate toPrimExpr fromPrimExpr $
60 Just Aggregator
61 { operation = Opaleye.AggrCount
62 , ordering = []
63 , distinction = Opaleye.AggrDistinct
64 }
67countStar :: Aggregate (Expr Int64)
68countStar = count (litExpr True)
71countWhere :: Expr Bool -> Aggregate (Expr Int64)
72countWhere condition = count (caseExpr [(condition, litExpr (Just True))] null)
75and :: Expr Bool -> Aggregate (Expr Bool)
76and = unsafeMakeAggregate toPrimExpr fromPrimExpr $
77 Just Aggregator
78 { operation = Opaleye.AggrBoolAnd
79 , ordering = []
80 , distinction = Opaleye.AggrAll
81 }
84or :: Expr Bool -> Aggregate (Expr Bool)
85or = unsafeMakeAggregate toPrimExpr fromPrimExpr $
86 Just Aggregator
87 { operation = Opaleye.AggrBoolOr
88 , ordering = []
89 , distinction = Opaleye.AggrAll
90 }
93-- | Produce an aggregation for @Expr a@ using the @max@ function.
94max :: (DBMax db, Nullabilizes db a) => Expr a -> Aggregate (Expr a)
95max = unsafeMakeAggregate toPrimExpr fromPrimExpr $
96 Just Aggregator
97 { operation = Opaleye.AggrSum
98 , ordering = []
99 , distinction = Opaleye.AggrAll
100 }
103-- | Produce an aggregation for @Expr a@ using the @max@ function.
104min :: (DBMin db, Nullabilizes db a) => Expr a -> Aggregate (Expr a)
105min = unsafeMakeAggregate toPrimExpr fromPrimExpr $
106 Just Aggregator
107 { operation = Opaleye.AggrSum
108 , ordering = []
109 , distinction = Opaleye.AggrAll
110 }
112-- | Corresponds to @sum@.
113sum :: (DBSum db, Nullabilizes db a) => Expr a -> Aggregate (Expr a)
114sum = unsafeMakeAggregate toPrimExpr (castExpr . fromPrimExpr) $
115 Just Aggregator
116 { operation = Opaleye.AggrSum
117 , ordering = []
118 , distinction = Opaleye.AggrAll
119 }
122sumWhere :: (DBNum db, DBSum db, Nullabilizes db a)
123 => Expr Bool -> Expr a -> Aggregate (Expr a)
124sumWhere condition a = sum (caseExpr [(condition, a)] 0)
127stringAgg :: (DBString db, Nullabilizes db a)
128 => Expr db -> Expr a -> Aggregate (Expr a)
129stringAgg delimiter =
130 unsafeMakeAggregate toPrimExpr (castExpr . fromPrimExpr) $
131 Just Aggregator
132 { operation = Opaleye.AggrStringAggr (toPrimExpr delimiter)
133 , ordering = []
134 , distinction = Opaleye.AggrAll
135 }
138-- | Aggregate a value by grouping by it.
139groupByExpr :: (DBEq db, Nullabilizes db a) => Expr a -> Aggregate (Expr a)
140groupByExpr = sgroupByExpr nullabilization
143listAggExpr :: Expr a -> Aggregate (Expr [a])
144listAggExpr = unsafeMakeAggregate toPrimExpr from $ Just
145 Aggregator
146 { operation = Opaleye.AggrArr
147 , ordering = []
148 , distinction = Opaleye.AggrAll
149 }
150 where
151 from = fromPrimExpr . fromPrimArray
154nonEmptyAggExpr :: Expr a -> Aggregate (Expr (NonEmpty a))
155nonEmptyAggExpr = unsafeMakeAggregate toPrimExpr from $ Just
156 Aggregator
157 { operation = Opaleye.AggrArr
158 , ordering = []
159 , distinction = Opaleye.AggrAll
160 }
161 where
162 from = fromPrimExpr . fromPrimArray
165sgroupByExpr :: DBEq db => Nullability db a -> Expr a -> Aggregate (Expr a)
166sgroupByExpr _ = unsafeMakeAggregate toPrimExpr fromPrimExpr Nothing