{-# language MonoLocalBinds #-}

module Rel8.Table.Window
  ( cumulative
  , cumulative_
  , currentRow
  )
where

-- base
import Prelude

-- opaleye
import qualified Opaleye.Window as Opaleye

-- rel8
import Rel8.Aggregate ( Aggregates )
import qualified Rel8.Expr.Window as Expr
import Rel8.Schema.HTable ( hfield, htabulateA )
import Rel8.Table ( fromColumns, toColumns )
import Rel8.Window ( Window( Window ) )


-- | 'cumulative' allows the use of aggregation functions in 'Window'
-- expressions. In particular, @'cumulative' 'Rel8.sum'@
-- (when combined with 'Rel8.Window.orderPartitionBy') gives a running total,
-- also known as a \"cumulative sum\", hence the name @cumulative@.
cumulative :: Aggregates aggregates exprs => (a -> aggregates) -> Window a exprs
cumulative :: forall aggregates exprs a.
Aggregates aggregates exprs =>
(a -> aggregates) -> Window a exprs
cumulative a -> aggregates
f =
  forall (f :: Context) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (context :: Context) a.
Table context a =>
Columns a context -> a
fromColumns forall a b. (a -> b) -> a -> b
$
    forall (t :: HTable) (m :: Context) (context :: Context).
(HTable t, Apply m) =>
(forall a. HField t a -> m (context a)) -> m (t context)
htabulateA forall a b. (a -> b) -> a -> b
$ \HField (Columns exprs) a
field ->
      forall a b. (a -> Aggregate b) -> Window a (Expr b)
Expr.cumulative ((forall (t :: HTable) (context :: Context) a.
HTable t =>
t context -> HField t a -> context a
`hfield` HField (Columns exprs) a
field) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (context :: Context) a.
Table context a =>
a -> Columns a context
toColumns forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> aggregates
f)


-- | A version of 'cumulative' for use with nullary aggregators like
-- 'Rel8.Expr.Aggregate.countStar'.
cumulative_ :: Aggregates aggregates exprs => aggregates -> Window a exprs
cumulative_ :: forall aggregates exprs a.
Aggregates aggregates exprs =>
aggregates -> Window a exprs
cumulative_ = forall aggregates exprs a.
Aggregates aggregates exprs =>
(a -> aggregates) -> Window a exprs
cumulative forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> b -> a
const


-- | Return every column of the current row of a window query.
currentRow :: Window a a
currentRow :: forall a. Window a a
currentRow = forall a b. Windows a b -> Window a b
Window forall a b. (a -> b) -> a -> b
$ forall a b.
WindowFunction a b -> Window a -> Order a -> Windows a b
Opaleye.over (forall a b. (a -> b) -> WindowFunction a b
Opaleye.noWindowFunction forall a. a -> a
id) forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty