@@ -16,11 +16,13 @@ Squeal expressions are the atoms used to build statements.
16 , FlexibleContexts
16 , FlexibleContexts
17 , FlexibleInstances
17 , FlexibleInstances
18 , FunctionalDependencies
18 , FunctionalDependencies
19 , GeneralizedNewtypeDeriving
20 , GeneralizedNewtypeDeriving
20 , LambdaCase
21 , LambdaCase
21 , MagicHash
22 , MagicHash
22 , OverloadedStrings
23 , OverloadedStrings
23 , ScopedTypeVariables
24 , ScopedTypeVariables
24 , TypeApplications
26 , TypeApplications
25 , TypeFamilies
27 , TypeFamilies
26 , TypeInType
28 , TypeInType
@@ -141,6 +143,18 @@ module Squeal.PostgreSQL.Expression
141 , count, countDistinct
143 , count, countDistinct
142 , every, everyDistinct
144 , every, everyDistinct
143 , max_, maxDistinct, min_, minDistinct
145 , max_, maxDistinct, min_, minDistinct
146+ -- * Window Functions
147+ , WindowDefinition (..)
149+ , WindowFunction (..)
156+ , SortExpression (..)
144 -- * Types
158 -- * Types
145 , TypeExpression (..)
159 , TypeExpression (..)
146 , PGTyped (..)
160 , PGTyped (..)
@@ -1778,3 +1792,138 @@ instance PGTyped schemas ty
1778instance (KnownNat n, PGTyped schemas ty)
1792instance (KnownNat n, PGTyped schemas ty)
1779 => PGTyped schemas (nullity ('PGfixarray n ty)) where
1793 => PGTyped schemas (nullity ('PGfixarray n ty)) where
1780 pgtype = fixarray @n (pgtype @schemas @ty)
1794 pgtype = fixarray @n (pgtype @schemas @ty)
1796+{-----------------------------------------
1798+-----------------------------------------}
1800+-- | `SortExpression`s are used by `sortBy` to optionally sort the results
1801+-- of a `Query`. `Asc` or `Desc` set the sort direction of a `NotNull` result
1802+-- column to ascending or descending. Ascending order puts smaller values
1803+-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
1804+-- descending order is determined with the `.>` operator. `AscNullsFirst`,
1805+-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
1806+-- determine whether nulls appear before or after non-null values in the sort
1807+-- ordering of a `Null` result column.
1808+data SortExpression commons schemas params grp from where
1810+ :: Expression commons schemas params grp from ('NotNull ty)
1811+ -> SortExpression commons schemas params grp from
1813+ :: Expression commons schemas params grp from ('NotNull ty)
1814+ -> SortExpression commons schemas params grp from
1816+ :: Expression commons schemas params grp from ('Null ty)
1817+ -> SortExpression commons schemas params grp from
1819+ :: Expression commons schemas params grp from ('Null ty)
1820+ -> SortExpression commons schemas params grp from
1822+ :: Expression commons schemas params grp from ('Null ty)
1823+ -> SortExpression commons schemas params grp from
1825+ :: Expression commons schemas params grp from ('Null ty)
1826+ -> SortExpression commons schemas params grp from
1827+deriving instance Show (SortExpression commons schemas params grp from)
1829+class OrderBy expr where
1831+ :: [SortExpression commons schemas params grp from]
1832+ -> expr commons schemas params grp from
1833+ -> expr commons schemas params grp from
1835+-- | Render a `SortExpression`.
1836+instance RenderSQL (SortExpression commons schemas params grp from) where
1838+ Asc expression -> renderSQL expression <+> "ASC"
1839+ Desc expression -> renderSQL expression <+> "DESC"
1840+ AscNullsFirst expression -> renderSQL expression
1841+ <+> "ASC NULLS FIRST"
1842+ DescNullsFirst expression -> renderSQL expression
1843+ <+> "DESC NULLS FIRST"
1844+ AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
1845+ DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
1847+data WindowDefinition commons schemas params grp from where
1850+ => NP (Expression commons schemas params grp from) bys
1851+ -> [SortExpression commons schemas params grp from]
1852+ -> WindowDefinition commons schemas params grp from
1854+instance OrderBy WindowDefinition where
1855+ orderBy sortsR (WindowDefinition parts sortsL)
1856+ = WindowDefinition parts (sortsL ++ sortsR)
1858+instance RenderSQL (WindowDefinition commons schemas from grp params) where
1859+ renderSQL (WindowDefinition part ord) =
1860+ renderPartitionByClause part <> renderOrderByClause ord
1862+ renderPartitionByClause = \case
1864+ parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
1865+ renderOrderByClause = \case
1867+ srts -> " ORDER" <+> "BY"
1868+ <+> commaSeparated (renderSQL <$> srts)
1872+ => NP (Expression commons schemas params grp from) bys
1873+ -> WindowDefinition commons schemas params grp from
1874+partitionBy bys = WindowDefinition bys []
1876+newtype WindowFunction
1877+ (commons :: FromType)
1878+ (schemas :: SchemasType)
1879+ (params :: [NullityType])
1882+ (ty :: NullityType)
1883+ = UnsafeWindowFunction { renderWindowFunction :: ByteString }
1884+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
1886+instance RenderSQL (WindowFunction commons schemas params grp from ty) where
1887+ renderSQL = renderWindowFunction
1889+{- | rank of the current row with gaps; same as `rowNumber` of its first peer
1892+ expr :: WindowExpression commons schemas params 'Ungrouped '["tab" ::: '["a" ::: ty]] ('NotNull 'PGint8)
1893+ expr = rank `Over` (partitionBy #a)
1897+rank() OVER (PARTITION BY "a")
1899+rank :: WindowFunction commons schemas from grp params ('NotNull 'PGint8)
1900+rank = UnsafeWindowFunction "rank()"
1902+{- | number of the current row within its partition, counting from 1
1903+>>> printSQL rowNumber
1906+rowNumber :: WindowFunction commons schemas from grp params ('NotNull 'PGint8)
1907+rowNumber = UnsafeWindowFunction "row_number()"
1909+{- | rank of the current row without gaps; this function counts peer groups
1910+>>> printSQL denseRank
1913+denseRank :: WindowFunction commons schemas from grp params ('NotNull 'PGint8)
1914+denseRank = UnsafeWindowFunction "dense_rank()"
1916+{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
1917+>>> printSQL percentRank
1920+percentRank :: WindowFunction commons schemas from grp params ('NotNull 'PGfloat8)
1921+percentRank = UnsafeWindowFunction "percent_rank()"
1923+{- | cumulative distribution: (number of partition rows
1924+preceding or peer with current row) / total partition rows
1925+>>> printSQL cumeDist
1928+cumeDist :: WindowFunction commons schemas from grp params ('NotNull 'PGfloat8)
1929+cumeDist = UnsafeWindowFunction "cume_dist()"