on 6360f10 help sign in
rel8/src/Rel8/Expr/Aggregate.hs
158 lines 4.3 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 , unsafeFromPrimExpr
36 , unsafeToPrimExpr
37 )
38import Rel8.Expr.Null ( null )
39import Rel8.Expr.Serialize ( litExpr )
40import Rel8.Schema.Nullability ( Nullability, Nullabilizes, nullabilization )
41import Rel8.Type.Eq ( DBEq )
42import Rel8.Type.Num ( DBNum )
43import Rel8.Type.Ord ( DBMax, DBMin )
44import Rel8.Type.String ( DBString )
45import Rel8.Type.Sum ( DBSum )
48count :: Expr a -> Aggregate (Expr Int64)
49count = unsafeMakeAggregate unsafeToPrimExpr unsafeFromPrimExpr $
50 Just Aggregator
51 { operation = Opaleye.AggrCount
52 , ordering = []
53 , distinction = Opaleye.AggrAll
54 }
57countDistinct :: DBEq a => Expr a -> Aggregate (Expr Int64)
58countDistinct = unsafeMakeAggregate unsafeToPrimExpr unsafeFromPrimExpr $
59 Just Aggregator
60 { operation = Opaleye.AggrCount
61 , ordering = []
62 , distinction = Opaleye.AggrDistinct
63 }
66countStar :: Aggregate (Expr Int64)
67countStar = count (litExpr True)
70countWhere :: Expr Bool -> Aggregate (Expr Int64)
71countWhere condition = count (caseExpr [(condition, litExpr (Just True))] null)
74and :: Expr Bool -> Aggregate (Expr Bool)
75and = unsafeMakeAggregate unsafeToPrimExpr unsafeFromPrimExpr $
76 Just Aggregator
77 { operation = Opaleye.AggrBoolAnd
78 , ordering = []
79 , distinction = Opaleye.AggrAll
80 }
83or :: Expr Bool -> Aggregate (Expr Bool)
84or = unsafeMakeAggregate unsafeToPrimExpr unsafeFromPrimExpr $
85 Just Aggregator
86 { operation = Opaleye.AggrBoolOr
87 , ordering = []
88 , distinction = Opaleye.AggrAll
89 }
92max :: (DBMax db, Nullabilizes db a) => Expr a -> Aggregate (Expr a)
93max = unsafeMakeAggregate unsafeToPrimExpr unsafeFromPrimExpr $
94 Just Aggregator
95 { operation = Opaleye.AggrSum
96 , ordering = []
97 , distinction = Opaleye.AggrAll
98 }
101min :: (DBMin db, Nullabilizes db a) => Expr a -> Aggregate (Expr a)
102min = unsafeMakeAggregate unsafeToPrimExpr unsafeFromPrimExpr $
103 Just Aggregator
104 { operation = Opaleye.AggrSum
105 , ordering = []
106 , distinction = Opaleye.AggrAll
107 }
110sum :: (DBSum db, Nullabilizes db a) => Expr a -> Aggregate (Expr a)
111sum = unsafeMakeAggregate unsafeToPrimExpr (castExpr . unsafeFromPrimExpr) $
112 Just Aggregator
113 { operation = Opaleye.AggrSum
114 , ordering = []
115 , distinction = Opaleye.AggrAll
116 }
119sumWhere :: (DBNum db, DBSum db, Nullabilizes db a)
120 => Expr Bool -> Expr a -> Aggregate (Expr a)
121sumWhere condition a = sum (caseExpr [(condition, a)] 0)
124stringAgg :: (DBString db, Nullabilizes db a)
125 => Expr db -> Expr a -> Aggregate (Expr a)
126stringAgg delimiter =
127 unsafeMakeAggregate unsafeToPrimExpr (castExpr . unsafeFromPrimExpr) $
128 Just Aggregator
129 { operation = Opaleye.AggrStringAggr (unsafeToPrimExpr delimiter)
130 , ordering = []
131 , distinction = Opaleye.AggrAll
132 }
135groupByExpr :: (DBEq db, Nullabilizes db a) => Expr a -> Aggregate (Expr a)
136groupByExpr = sgroupByExpr nullabilization
139listAggExpr :: Expr a -> Aggregate (Expr [a])
140listAggExpr = unsafeMakeAggregate unsafeToPrimExpr fromPrimExpr $ Just
141 Aggregator
142 { operation = Opaleye.AggrArr
143 , ordering = []
144 , distinction = Opaleye.AggrAll
145 }
148nonEmptyAggExpr :: Expr a -> Aggregate (Expr (NonEmpty a))
149nonEmptyAggExpr = unsafeMakeAggregate unsafeToPrimExpr fromPrimExpr $ Just
150 Aggregator
151 { operation = Opaleye.AggrArr
152 , ordering = []
153 , distinction = Opaleye.AggrAll
154 }
157sgroupByExpr :: DBEq db => Nullability db a -> Expr a -> Aggregate (Expr a)
158sgroupByExpr _ = unsafeMakeAggregate unsafeToPrimExpr unsafeFromPrimExpr Nothing