{-# LANGUAGE DataKinds #-}
module Opaleye.Aggregate
(
aggregate
, aggregateOrdered
, distinctAggregator
, Aggregator
, groupBy
, Opaleye.Aggregate.sum
, sumInt4
, sumInt8
, count
, countStar
, avg
, Opaleye.Aggregate.max
, Opaleye.Aggregate.min
, boolOr
, boolAnd
, arrayAgg
, jsonAgg
, stringAgg
, countRows
) where
import Control.Applicative (pure)
import Data.Profunctor (lmap)
import qualified Data.Profunctor as P
import qualified Opaleye.Internal.Aggregate as A
import Opaleye.Internal.Aggregate (Aggregator, orderAggregate)
import qualified Opaleye.Internal.Column as IC
import qualified Opaleye.Internal.QueryArr as Q
import qualified Opaleye.Internal.HaskellDB.PrimQuery as HPQ
import qualified Opaleye.Internal.PackMap as PM
import qualified Opaleye.Internal.Tag as Tag
import qualified Opaleye.Field as F
import qualified Opaleye.Order as Ord
import qualified Opaleye.Select as S
import qualified Opaleye.SqlTypes as T
import qualified Opaleye.Join as J
aggregate :: Aggregator a b -> S.Select a -> S.Select b
aggregate :: Aggregator a b -> Select a -> Select b
aggregate Aggregator a b
agg Select a
q = State Tag (b, PrimQuery) -> Select b
forall a. State Tag (a, PrimQuery) -> Query a
Q.productQueryArr (State Tag (b, PrimQuery) -> Select b)
-> State Tag (b, PrimQuery) -> Select b
forall a b. (a -> b) -> a -> b
$ do
(a
a, PrimQuery
pq) <- Select a -> State Tag (a, PrimQuery)
forall a. Select a -> State Tag (a, PrimQuery)
Q.runSimpleSelect Select a
q
Tag
t <- State Tag Tag
Tag.fresh
(b, PrimQuery) -> State Tag (b, PrimQuery)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Aggregator a b -> (a, PrimQuery, Tag) -> (b, PrimQuery)
forall a b. Aggregator a b -> (a, PrimQuery, Tag) -> (b, PrimQuery)
A.aggregateU Aggregator a b
agg (a
a, PrimQuery
pq, Tag
t))
aggregateOrdered :: Ord.Order a -> Aggregator a b -> S.Select a -> S.Select b
aggregateOrdered :: Order a -> Aggregator a b -> Select a -> Select b
aggregateOrdered Order a
o Aggregator a b
agg = Aggregator a b -> Select a -> Select b
forall a b. Aggregator a b -> Select a -> Select b
aggregate (Order a -> Aggregator a b -> Aggregator a b
forall a b. Order a -> Aggregator a b -> Aggregator a b
orderAggregate Order a
o Aggregator a b
agg)
distinctAggregator :: Aggregator a b -> Aggregator a b
distinctAggregator :: Aggregator a b -> Aggregator a b
distinctAggregator (A.Aggregator (PM.PackMap forall (f :: * -> *).
Applicative f =>
((Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr)
-> f PrimExpr)
-> a -> f b
pm)) =
PackMap
(Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr) PrimExpr a b
-> Aggregator a b
forall a b.
PackMap
(Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr) PrimExpr a b
-> Aggregator a b
A.Aggregator ((forall (f :: * -> *).
Applicative f =>
((Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr)
-> f PrimExpr)
-> a -> f b)
-> PackMap
(Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr) PrimExpr a b
forall a b s t.
(forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t)
-> PackMap a b s t
PM.PackMap (\(Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr) -> f PrimExpr
f a
c -> ((Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr)
-> f PrimExpr)
-> a -> f b
forall (f :: * -> *).
Applicative f =>
((Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr)
-> f PrimExpr)
-> a -> f b
pm ((Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr) -> f PrimExpr
f ((Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr)
-> f PrimExpr)
-> ((Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr)
-> (Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr))
-> (Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr)
-> f PrimExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe (AggrOp, [OrderExpr], AggrDistinct)
-> Maybe (AggrOp, [OrderExpr], AggrDistinct))
-> (Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr)
-> (Maybe (AggrOp, [OrderExpr], AggrDistinct), PrimExpr)
forall (p :: * -> * -> *) a b c.
Strong p =>
p a b -> p (a, c) (b, c)
P.first' (((AggrOp, [OrderExpr], AggrDistinct)
-> (AggrOp, [OrderExpr], AggrDistinct))
-> Maybe (AggrOp, [OrderExpr], AggrDistinct)
-> Maybe (AggrOp, [OrderExpr], AggrDistinct)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(AggrOp
a,[OrderExpr]
b,AggrDistinct
_) -> (AggrOp
a,[OrderExpr]
b,AggrDistinct
HPQ.AggrDistinct)))) a
c))
groupBy :: Aggregator (F.Field_ n a) (F.Field_ n a)
groupBy :: Aggregator (Field_ n a) (Field_ n a)
groupBy = Maybe AggrOp -> Aggregator (Field_ n a) (Field_ n a)
forall (n :: Nullability) a (n' :: Nullability) b.
Maybe AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr' Maybe AggrOp
forall a. Maybe a
Nothing
sum :: Aggregator (F.Field a) (F.Field a)
sum :: Aggregator (Field a) (Field a)
sum = AggrOp -> Aggregator (Field a) (Field a)
forall (n :: Nullability) a (n' :: Nullability) b.
AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr AggrOp
HPQ.AggrSum
sumInt4 :: Aggregator (F.Field T.SqlInt4) (F.Field T.SqlInt8)
sumInt4 :: Aggregator (Field SqlInt4) (Field SqlInt8)
sumInt4 = (Field SqlInt4 -> Field SqlInt8)
-> Aggregator (Field SqlInt4) (Field SqlInt4)
-> Aggregator (Field SqlInt4) (Field SqlInt8)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Field SqlInt4 -> Field SqlInt8
forall (n :: Nullability) a (n' :: Nullability) b.
Field_ n a -> Field_ n' b
F.unsafeCoerceField Aggregator (Field SqlInt4) (Field SqlInt4)
forall a. Aggregator (Field a) (Field a)
Opaleye.Aggregate.sum
sumInt8 :: Aggregator (F.Field T.SqlInt8) (F.Field T.SqlNumeric)
sumInt8 :: Aggregator (Field SqlInt8) (Field SqlNumeric)
sumInt8 = (Field SqlInt8 -> Field SqlNumeric)
-> Aggregator (Field SqlInt8) (Field SqlInt8)
-> Aggregator (Field SqlInt8) (Field SqlNumeric)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Field SqlInt8 -> Field SqlNumeric
forall (n :: Nullability) a (n' :: Nullability) b.
Field_ n a -> Field_ n' b
F.unsafeCoerceField Aggregator (Field SqlInt8) (Field SqlInt8)
forall a. Aggregator (Field a) (Field a)
Opaleye.Aggregate.sum
count :: Aggregator (F.Field a) (F.Field T.SqlInt8)
count :: Aggregator (Field a) (Field SqlInt8)
count = AggrOp -> Aggregator (Field a) (Field SqlInt8)
forall (n :: Nullability) a (n' :: Nullability) b.
AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr AggrOp
HPQ.AggrCount
countStar :: Aggregator a (F.Field T.SqlInt8)
countStar :: Aggregator a (Field SqlInt8)
countStar = (a -> Field SqlInt4)
-> Aggregator (Field SqlInt4) (Field SqlInt8)
-> Aggregator a (Field SqlInt8)
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap (Field SqlInt4 -> a -> Field SqlInt4
forall a b. a -> b -> a
const (Field SqlInt4
0 :: F.Field T.SqlInt4)) Aggregator (Field SqlInt4) (Field SqlInt8)
forall a. Aggregator (Field a) (Field SqlInt8)
count
avg :: Aggregator (F.Field T.SqlFloat8) (F.Field T.SqlFloat8)
avg :: Aggregator (Field SqlFloat8) (Field SqlFloat8)
avg = AggrOp -> Aggregator (Field SqlFloat8) (Field SqlFloat8)
forall (n :: Nullability) a (n' :: Nullability) b.
AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr AggrOp
HPQ.AggrAvg
max :: Ord.SqlOrd a => Aggregator (F.Field a) (F.Field a)
max :: Aggregator (Field a) (Field a)
max = AggrOp -> Aggregator (Field a) (Field a)
forall (n :: Nullability) a (n' :: Nullability) b.
AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr AggrOp
HPQ.AggrMax
min :: Ord.SqlOrd a => Aggregator (F.Field a) (F.Field a)
min :: Aggregator (Field a) (Field a)
min = AggrOp -> Aggregator (Field a) (Field a)
forall (n :: Nullability) a (n' :: Nullability) b.
AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr AggrOp
HPQ.AggrMin
boolOr :: Aggregator (F.Field T.SqlBool) (F.Field T.SqlBool)
boolOr :: Aggregator (Field SqlBool) (Field SqlBool)
boolOr = AggrOp -> Aggregator (Field SqlBool) (Field SqlBool)
forall (n :: Nullability) a (n' :: Nullability) b.
AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr AggrOp
HPQ.AggrBoolOr
boolAnd :: Aggregator (F.Field T.SqlBool) (F.Field T.SqlBool)
boolAnd :: Aggregator (Field SqlBool) (Field SqlBool)
boolAnd = AggrOp -> Aggregator (Field SqlBool) (Field SqlBool)
forall (n :: Nullability) a (n' :: Nullability) b.
AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr AggrOp
HPQ.AggrBoolAnd
arrayAgg :: Aggregator (F.Field a) (F.Field (T.SqlArray a))
arrayAgg :: Aggregator (Field a) (Field (SqlArray a))
arrayAgg = AggrOp -> Aggregator (Field a) (Field (SqlArray a))
forall (n :: Nullability) a (n' :: Nullability) b.
AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr AggrOp
HPQ.AggrArr
jsonAgg :: Aggregator (F.Field a) (F.Field T.SqlJson)
jsonAgg :: Aggregator (Field a) (Field SqlJson)
jsonAgg = AggrOp -> Aggregator (Field a) (Field SqlJson)
forall (n :: Nullability) a (n' :: Nullability) b.
AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr AggrOp
HPQ.JsonArr
stringAgg :: F.Field T.SqlText
-> Aggregator (F.Field T.SqlText) (F.Field T.SqlText)
stringAgg :: Field SqlText -> Aggregator (Field SqlText) (Field SqlText)
stringAgg = Maybe AggrOp -> Aggregator (Field SqlText) (Field SqlText)
forall (n :: Nullability) a (n' :: Nullability) b.
Maybe AggrOp -> Aggregator (Field_ n a) (Field_ n' b)
A.makeAggr' (Maybe AggrOp -> Aggregator (Field SqlText) (Field SqlText))
-> (Field SqlText -> Maybe AggrOp)
-> Field SqlText
-> Aggregator (Field SqlText) (Field SqlText)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AggrOp -> Maybe AggrOp
forall a. a -> Maybe a
Just (AggrOp -> Maybe AggrOp)
-> (Field SqlText -> AggrOp) -> Field SqlText -> Maybe AggrOp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrimExpr -> AggrOp
HPQ.AggrStringAggr (PrimExpr -> AggrOp)
-> (Field SqlText -> PrimExpr) -> Field SqlText -> AggrOp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field SqlText -> PrimExpr
forall (n :: Nullability) a. Field_ n a -> PrimExpr
IC.unColumn
countRows :: S.Select a -> S.Select (F.Field T.SqlInt8)
countRows :: Select a -> Select (Field SqlInt8)
countRows = (FieldNullable SqlInt8 -> Field SqlInt8)
-> SelectArr () (FieldNullable SqlInt8) -> Select (Field SqlInt8)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Field SqlInt8 -> FieldNullable SqlInt8 -> Field SqlInt8
forall a. Field a -> FieldNullable a -> Field a
F.fromNullable Field SqlInt8
0)
(SelectArr () (FieldNullable SqlInt8) -> Select (Field SqlInt8))
-> (Select a -> SelectArr () (FieldNullable SqlInt8))
-> Select a
-> Select (Field SqlInt8)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (((), FieldNullable SqlInt8) -> FieldNullable SqlInt8)
-> SelectArr () ((), FieldNullable SqlInt8)
-> SelectArr () (FieldNullable SqlInt8)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((), FieldNullable SqlInt8) -> FieldNullable SqlInt8
forall a b. (a, b) -> b
snd
(SelectArr () ((), FieldNullable SqlInt8)
-> SelectArr () (FieldNullable SqlInt8))
-> (Select a -> SelectArr () ((), FieldNullable SqlInt8))
-> Select a
-> SelectArr () (FieldNullable SqlInt8)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\Select (Field SqlInt4)
q -> Select ()
-> Select (Field SqlInt8)
-> (((), Field SqlInt8) -> Field SqlBool)
-> SelectArr () ((), FieldNullable SqlInt8)
forall fieldsL fieldsR nullableFieldsR.
(Default Unpackspec fieldsL fieldsL,
Default Unpackspec fieldsR fieldsR,
Default NullMaker fieldsR nullableFieldsR) =>
Select fieldsL
-> Select fieldsR
-> ((fieldsL, fieldsR) -> Field SqlBool)
-> Select (fieldsL, nullableFieldsR)
J.leftJoin (() -> Select ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
(Aggregator (Field SqlInt4) (Field SqlInt8)
-> Select (Field SqlInt4) -> Select (Field SqlInt8)
forall a b. Aggregator a b -> Select a -> Select b
aggregate Aggregator (Field SqlInt4) (Field SqlInt8)
forall a. Aggregator (Field a) (Field SqlInt8)
count Select (Field SqlInt4)
q)
(Field SqlBool -> ((), Field SqlInt8) -> Field SqlBool
forall a b. a -> b -> a
const (Bool -> Field SqlBool
T.sqlBool Bool
True)))
(Select (Field SqlInt4)
-> SelectArr () ((), FieldNullable SqlInt8))
-> (Select a -> Select (Field SqlInt4))
-> Select a
-> SelectArr () ((), FieldNullable SqlInt8)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Field SqlInt4) -> Select a -> Select (Field SqlInt4)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Field SqlInt4 -> a -> Field SqlInt4
forall a b. a -> b -> a
const (Field SqlInt4
0 :: F.Field T.SqlInt4))