{-# LANGUAGE
DataKinds
, DeriveGeneric
, FlexibleContexts
, FlexibleInstances
, GADTs
, GeneralizedNewtypeDeriving
, LambdaCase
, MultiParamTypeClasses
, OverloadedStrings
, RankNTypes
, KindSignatures
#-}
module Squeal.PostgreSQL.Expression.Window
(
partitionBy
, rank
, rowNumber
, denseRank
, percentRank
, cumeDist
, ntile
, lag
, lead
, firstValue
, lastValue
, nthValue
, unsafeWindowFunction1
, unsafeWindowFunctionN
, WindowFunction (..)
, WindowDefinition (..)
, WinFun0
, WinFun1
, WinFunN
) where
import Control.DeepSeq
import Data.ByteString
import qualified GHC.Generics as GHC
import qualified Generics.SOP as SOP
import Squeal.PostgreSQL.Alias
import Squeal.PostgreSQL.Expression
import Squeal.PostgreSQL.Expression.Aggregate
import Squeal.PostgreSQL.Expression.Sort
import Squeal.PostgreSQL.List
import Squeal.PostgreSQL.Render
import Squeal.PostgreSQL.Schema
instance Aggregate
(Expression outer commons grp schemas params from)
(NP (Expression outer commons grp schemas params from))
(WindowFunction outer commons grp schemas params from) where
countStar = UnsafeWindowFunction "count(*)"
count = unsafeWindowFunction1 "count"
sum_ = unsafeWindowFunction1 "sum"
arrayAgg = unsafeWindowFunction1 "array_agg"
jsonAgg = unsafeWindowFunction1 "json_agg"
jsonbAgg = unsafeWindowFunction1 "jsonb_agg"
bitAnd = unsafeWindowFunction1 "bit_and"
bitOr = unsafeWindowFunction1 "bit_or"
boolAnd = unsafeWindowFunction1 "bool_and"
boolOr = unsafeWindowFunction1 "bool_or"
every = unsafeWindowFunction1 "every"
max_ = unsafeWindowFunction1 "max"
min_ = unsafeWindowFunction1 "min"
avg = unsafeWindowFunction1 "avg"
corr = unsafeWindowFunctionN "corr"
covarPop = unsafeWindowFunctionN "covar_pop"
covarSamp = unsafeWindowFunctionN "covar_samp"
regrAvgX = unsafeWindowFunctionN "regr_avgx"
regrAvgY = unsafeWindowFunctionN "regr_avgy"
regrCount = unsafeWindowFunctionN "regr_count"
regrIntercept = unsafeWindowFunctionN "regr_intercept"
regrR2 = unsafeWindowFunctionN "regr_r2"
regrSlope = unsafeWindowFunctionN "regr_slope"
regrSxx = unsafeWindowFunctionN "regr_sxx"
regrSxy = unsafeWindowFunctionN "regr_sxy"
regrSyy = unsafeWindowFunctionN "regr_syy"
stddev = unsafeWindowFunction1 "stddev"
stddevPop = unsafeWindowFunction1 "stddev_pop"
stddevSamp = unsafeWindowFunction1 "stddev_samp"
variance = unsafeWindowFunction1 "variance"
varPop = unsafeWindowFunction1 "var_pop"
varSamp = unsafeWindowFunction1 "var_samp"
data WindowDefinition outer commons grp schemas params from where
WindowDefinition
:: SOP.SListI bys
=> NP (Expression outer commons grp schemas params from) bys
-> [SortExpression outer commons grp schemas params from]
-> WindowDefinition outer commons grp schemas params from
instance OrderBy WindowDefinition where
orderBy sortsR (WindowDefinition parts sortsL)
= WindowDefinition parts (sortsL ++ sortsR)
instance RenderSQL (WindowDefinition outer commons schemas from grp params) where
renderSQL (WindowDefinition part ord) =
renderPartitionByClause part <> renderOrderByClause ord
where
renderPartitionByClause = \case
Nil -> ""
parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
renderOrderByClause = \case
[] -> ""
srts -> " ORDER" <+> "BY"
<+> commaSeparated (renderSQL <$> srts)
partitionBy
:: SOP.SListI bys
=> NP (Expression outer commons grp schemas params from) bys
-> WindowDefinition outer commons grp schemas params from
partitionBy bys = WindowDefinition bys []
newtype WindowFunction
(outer :: FromType)
(commons :: FromType)
(grp :: Grouping)
(schemas :: SchemasType)
(params :: [NullityType])
(from :: FromType)
(ty :: NullityType)
= UnsafeWindowFunction { renderWindowFunction :: ByteString }
deriving (GHC.Generic,Show,Eq,Ord,NFData)
instance RenderSQL (WindowFunction outer commons grp schemas params from ty) where
renderSQL = renderWindowFunction
type WinFun0 x
= forall outer commons grp schemas params from
. WindowFunction outer commons grp schemas params from x
type WinFun1 x y
= forall outer commons grp schemas params from
. Expression outer commons grp schemas params from x
-> WindowFunction outer commons grp schemas params from y
type WinFunN xs y
= forall outer commons grp schemas params from
. NP (Expression outer commons grp schemas params from) xs
-> WindowFunction outer commons grp schemas params from y
unsafeWindowFunction1 :: ByteString -> WinFun1 x y
unsafeWindowFunction1 fun x
= UnsafeWindowFunction $ fun <> parenthesized (renderSQL x)
unsafeWindowFunctionN :: SOP.SListI xs => ByteString -> WinFunN xs y
unsafeWindowFunctionN fun xs = UnsafeWindowFunction $ fun <>
parenthesized (renderCommaSeparated renderSQL xs)
rank :: WinFun0 ('NotNull 'PGint8)
rank = UnsafeWindowFunction "rank()"
rowNumber :: WinFun0 ('NotNull 'PGint8)
rowNumber = UnsafeWindowFunction "row_number()"
denseRank :: WinFun0 ('NotNull 'PGint8)
denseRank = UnsafeWindowFunction "dense_rank()"
percentRank :: WinFun0 ('NotNull 'PGfloat8)
percentRank = UnsafeWindowFunction "percent_rank()"
cumeDist :: WinFun0 ('NotNull 'PGfloat8)
cumeDist = UnsafeWindowFunction "cume_dist()"
ntile :: WinFun1 ('NotNull 'PGint4) ('NotNull 'PGint4)
ntile = unsafeWindowFunction1 "ntile"
lag :: WinFunN '[ty, 'NotNull 'PGint4, ty] ty
lag = unsafeWindowFunctionN "lag"
lead :: WinFunN '[ty, 'NotNull 'PGint4, ty] ty
lead = unsafeWindowFunctionN "lead"
firstValue :: WinFun1 ty ty
firstValue = unsafeWindowFunction1 "first_value"
lastValue :: WinFun1 ty ty
lastValue = unsafeWindowFunction1 "last_value"
nthValue :: WinFunN '[null ty, 'NotNull 'PGint4] ('Null ty)
nthValue = unsafeWindowFunctionN "nth_value"