@@ -1,13 +1,14 @@
2Module: Squeal.PostgreSQL.Expression
2Module: Squeal.PostgreSQL.Expression
3Description: Squeal expressions
3Description: Squeal expressions
4−Copyright: (c) Eitan Chatav, 2019
4+Copyright: (c) Eitan Chatav, 2017
5Maintainer: eitan@morphism.tech
5Maintainer: eitan@morphism.tech
6Stability: experimental
6Stability: experimental
8Squeal expressions are the atoms used to build statements.
8Squeal expressions are the atoms used to build statements.
11+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
11{-# LANGUAGE
12{-# LANGUAGE
12 AllowAmbiguousTypes
13 AllowAmbiguousTypes
13 , ConstraintKinds
14 , ConstraintKinds
@@ -33,214 +34,298 @@ Squeal expressions are the atoms used to build statements.
33module Squeal.PostgreSQL.Expression
34module Squeal.PostgreSQL.Expression
34 ( -- * Expression
35 ( -- * Expression
35 Expression (..)
36 Expression (..)
36− , Expr
37+ , HasParameter (parameter)
37− , type (-->)
38+ , param
38− , FunctionDB
39+ -- ** Null
39− , unsafeFunction
40+ , null_
40− , function
41+ , notNull
41− , unsafeLeftOp
42+ , coalesce
42− , leftOp
43+ , fromNull
43− , unsafeRightOp
44+ , isNull
44− , rightOp
45+ , isNotNull
45− , Operator
46+ , matchNull
46− , OperatorDB
47+ , nullIf
47 , unsafeBinaryOp
55 , unsafeBinaryOp
48− , binaryOp
56+ , unsafeUnaryOp
49− , FunctionVar
57+ , unsafeFunction
50− , unsafeFunctionVar
58+ , unsafeVariadicFunction
51− , type (--->)
59+ , atan2_
52− , FunctionNDB
60+ , cast
53− , unsafeFunctionN
61+ , quot_
54− , functionN
62+ , rem_
55− , PGSubset (..)
63+ , trunc
56− , PGIntersect (..)
64+ , round_
101+ -- *** Json and Jsonb operators
106+ -- *** Jsonb operators
133+ , jsonExtractPathAsText
134+ , jsonbExtractPathAsText
146+ -- * Window Functions
147+ , WindowDefinition (..)
149+ , WindowFunction (..)
162+ , SortExpression (..)
165+ , TypeExpression (..)
191+ , timestampWithTimeZone
57 -- * Re-export
202 -- * Re-export
63import Control.Category
209import Control.Category
64import Control.DeepSeq
210import Control.DeepSeq
65import Data.ByteString (ByteString)
211import Data.ByteString (ByteString)
212+import Data.ByteString.Lazy (toStrict)
66import Data.Function ((&))
213import Data.Function ((&))
67import Data.Semigroup hiding (All)
214import Data.Semigroup hiding (All)
215+import qualified Data.Aeson as JSON
68import Data.String
216import Data.String
69import Generics.SOP hiding (All, from)
218import Generics.SOP hiding (All, from)
219+import GHC.Generics ((:*:) (..))
70import GHC.OverloadedLabels
220import GHC.OverloadedLabels
71import GHC.TypeLits
221import GHC.TypeLits
72import Numeric
222import Numeric
73import Prelude hiding (id, (.))
223import Prelude hiding (id, (.))
225+import qualified Data.ByteString as ByteString
75import qualified GHC.Generics as GHC
226import qualified GHC.Generics as GHC
227+import qualified Generics.SOP as SOP
77−import Squeal.PostgreSQL.Alias
78−import Squeal.PostgreSQL.List
79import Squeal.PostgreSQL.Render
229import Squeal.PostgreSQL.Render
80import Squeal.PostgreSQL.Schema
230import Squeal.PostgreSQL.Schema
83−-- >>> import Squeal.PostgreSQL
85{-----------------------------------------
232{-----------------------------------------
86column expressions
233column expressions
87-----------------------------------------}
234-----------------------------------------}
89{- | `Expression`s are used in a variety of contexts,
236{- | `Expression`s are used in a variety of contexts,
90−such as in the target `Squeal.PostgreSQL.Query.List` of the
91−`Squeal.PostgreSQL.Query.select` command,
237+such as in the target list of the `Squeal.PostgreSQL.Query.select` command,
92as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
238as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
93`Squeal.PostgreSQL.Manipulation.update`,
239`Squeal.PostgreSQL.Manipulation.update`,
94−or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
240+or in search `Condition`s in a number of commands.
96The expression syntax allows the calculation of
242The expression syntax allows the calculation of
97values from primitive expression using arithmetic, logical,
243values from primitive expression using arithmetic, logical,
98and other operations.
244and other operations.
100−The type parameters of `Expression` are
102−* @outer :: @ `FromType`, the @from@ clauses of any outer queries in which
103− the `Expression` is a correlated subquery expression;
104−* @commons :: @ `FromType`, the `Squeal.PostgreSQL.Query.CommonTableExpression`s
105− that are in scope for the `Expression`;
106−* @grp :: @ `Grouping`, the `Grouping` of the @from@ clause which may limit
107− which columns may be referenced by alias;
108−* @schemas :: @ `SchemasType`, the schemas of your database that are in
109− scope for the `Expression`;
110−* @from :: @ `FromType`, the @from@ clause which the `Expression` may use
111− to reference columns by alias;
112−* @ty :: @ `NullityType`, the type of the `Expression`.
114newtype Expression
246newtype Expression
115 (outer :: FromType)
247 (outer :: FromType)
116− (commons :: FromType)
117 (grp :: Grouping)
248 (grp :: Grouping)
249+ (commons :: FromType)
118 (schemas :: SchemasType)
250 (schemas :: SchemasType)
119 (params :: [NullityType])
251 (params :: [NullityType])
120 (from :: FromType)
252 (from :: FromType)
121 (ty :: NullityType)
253 (ty :: NullityType)
122 = UnsafeExpression { renderExpression :: ByteString }
254 = UnsafeExpression { renderExpression :: ByteString }
123 deriving (GHC.Generic,Show,Eq,Ord,NFData)
255 deriving (GHC.Generic,Show,Eq,Ord,NFData)
124−instance RenderSQL (Expression outer commons grp schemas params from ty) where
257+instance RenderSQL (Expression outer grp commons schemas params from ty) where
125 renderSQL = renderExpression
258 renderSQL = renderExpression
127−-- | An `Expr` is a closed `Expression`.
260+{- | A `HasParameter` constraint is used to indicate a value that is
128−-- It is a F@RankNType@ but don't be scared.
261+supplied externally to a SQL statement.
129−-- Think of it as an expression which sees no
262+`Squeal.PostgreSQL.PQ.manipulateParams`,
130−-- namespaces, so you can't use parameters
263+`Squeal.PostgreSQL.PQ.queryParams` and
131−-- or alias references. It can be used as
264+`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
132−-- a simple piece of more complex `Expression`s.
265+separately from the SQL command string, in which case `param`s are used to
133−type Expr x
266+refer to the out-of-line data values.
134− = forall outer commons grp schemas params from
135− . Expression outer commons grp schemas params from x
136− -- ^ cannot reference aliases
138−-- | A @RankNType@ for binary operators.
139−type Operator x1 x2 y
140− = forall outer commons grp schemas params from
141− . Expression outer commons grp schemas params from x1
143− -> Expression outer commons grp schemas params from x2
145− -> Expression outer commons grp schemas params from y
148−type OperatorDB schemas x1 x2 y
149− = forall outer commons grp params from
150− . Expression outer commons grp schemas params from x1
152− -> Expression outer commons grp schemas params from x2
154− -> Expression outer commons grp schemas params from y
157−-- | A @RankNType@ for functions with a single argument.
158−-- These could be either function calls or unary operators.
159−-- This is a subtype of the usual Haskell function type `Prelude.->`,
160−-- indeed a subcategory as it is closed under the usual
161−-- `Prelude..` and `Prelude.id`.
163− = forall outer commons grp schemas params from
164− . Expression outer commons grp schemas params from x
166− -> Expression outer commons grp schemas params from y
169−type FunctionDB schemas x y
170− = forall outer commons grp params from
171− . Expression outer commons grp schemas params from x
173− -> Expression outer commons grp schemas params from y
176−{- | A @RankNType@ for functions with a fixed-length list of heterogeneous arguments.
177−Use the `*:` operator to end your argument lists, like so.
179−>>> printSQL (unsafeFunctionN "fun" (true :* false :* localTime *: true))
180−fun(TRUE, FALSE, LOCALTIME, TRUE)
183− = forall outer commons grp schemas params from
184− . NP (Expression outer commons grp schemas params from) xs
186− -> Expression outer commons grp schemas params from y
189−type FunctionNDB schemas xs y
190− = forall outer commons grp params from
191− . NP (Expression outer commons grp schemas params from) xs
193− -> Expression outer commons grp schemas params from y
196−{- | A @RankNType@ for functions with a variable-length list of
197−homogeneous arguments and at least 1 more argument.
199−type FunctionVar x0 x1 y
200− = forall outer commons grp schemas params from
201− . [Expression outer commons grp schemas params from x0]
203− -> Expression outer commons grp schemas params from x1
204− -- ^ must have at least 1 input
205− -> Expression outer commons grp schemas params from y
208−{- | >>> printSQL (unsafeFunctionVar "greatest" [true, null_] false)
209−greatest(TRUE, NULL, FALSE)
211−unsafeFunctionVar :: ByteString -> FunctionVar x0 x1 y
268+class KnownNat n => HasParameter
270+ (params :: [NullityType])
272+ | n params -> ty where
273+ -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
275+ -- >>> let expr = parameter @1 int4 :: Expression outer grp '[] schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
276+ -- >>> printSQL expr
279+ :: TypeExpression schemas ty
280+ -> Expression outer grp commons schemas params from ty
212−unsafeFunctionVar fun xs x = UnsafeExpression $ fun <> parenthesized
281+ parameter ty = UnsafeExpression $ parenthesized $
213− (commaSeparated (renderSQL <$> xs) <> ", " <> renderSQL x)
282+ "$" <> renderNat @n <+> "::"
284+instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
285+instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
286+ => HasParameter n (ty' : params) ty
288+-- | `param` takes a `Nat` using type application and for basic types,
289+-- infers a `TypeExpression`.
291+-- >>> let expr = param @1 :: Expression outer grp commons schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
295+ :: forall n outer commons schemas params from grp ty
296+ . (PGTyped schemas ty, HasParameter n params ty)
297+ => Expression outer grp commons schemas params from ty -- ^ param
298+param = parameter @n (pgtype @schemas)
215instance (HasUnique tab (Join outer from) row, Has col row ty)
300instance (HasUnique tab (Join outer from) row, Has col row ty)
216− => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
301+ => IsLabel col (Expression outer 'Ungrouped commons schemas params from ty) where
217 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
302 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
218instance (HasUnique tab (Join outer from) row, Has col row ty, tys ~ '[ty])
303instance (HasUnique tab (Join outer from) row, Has col row ty, tys ~ '[ty])
219− => IsLabel col (NP (Expression outer commons 'Ungrouped schemas params from) tys) where
304+ => IsLabel col (NP (Expression outer 'Ungrouped commons schemas params from) tys) where
220 fromLabel = fromLabel @col :* Nil
305 fromLabel = fromLabel @col :* Nil
221instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
306instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
222 => IsLabel col
307 => IsLabel col
223− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
308+ (Aliased (Expression outer 'Ungrouped commons schemas params from) column) where
224 fromLabel = fromLabel @col `As` Alias
309 fromLabel = fromLabel @col `As` Alias
225instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
310instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
226 => IsLabel col
311 => IsLabel col
227− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
312+ (NP (Aliased (Expression outer 'Ungrouped commons schemas params from)) columns) where
228 fromLabel = fromLabel @col :* Nil
313 fromLabel = fromLabel @col :* Nil
230instance (Has tab (Join outer from) row, Has col row ty)
315instance (Has tab (Join outer from) row, Has col row ty)
231− => IsQualified tab col (Expression outer commons 'Ungrouped schemas params from ty) where
316+ => IsQualified tab col (Expression outer 'Ungrouped commons schemas params from ty) where
232 tab ! col = UnsafeExpression $
317 tab ! col = UnsafeExpression $
233 renderSQL tab <> "." <> renderSQL col
318 renderSQL tab <> "." <> renderSQL col
234instance (Has tab (Join outer from) row, Has col row ty, tys ~ '[ty])
319instance (Has tab (Join outer from) row, Has col row ty, tys ~ '[ty])
235− => IsQualified tab col (NP (Expression outer commons 'Ungrouped schemas params from) tys) where
320+ => IsQualified tab col (NP (Expression outer 'Ungrouped commons schemas params from) tys) where
236 tab ! col = tab ! col :* Nil
321 tab ! col = tab ! col :* Nil
237instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
322instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
238 => IsQualified tab col
323 => IsQualified tab col
239− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
324+ (Aliased (Expression outer 'Ungrouped commons schemas params from) column) where
240 tab ! col = tab ! col `As` col
325 tab ! col = tab ! col `As` col
241instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
326instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
242 => IsQualified tab col
327 => IsQualified tab col
243− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
328+ (NP (Aliased (Expression outer 'Ungrouped commons schemas params from)) columns) where
244 tab ! col = tab ! col :* Nil
329 tab ! col = tab ! col :* Nil
@@ -248,7 +333,7 @@ instance
248 , Has col row ty
333 , Has col row ty
249 , GroupedBy tab col bys
334 , GroupedBy tab col bys
250 ) => IsLabel col
335 ) => IsLabel col
251− (Expression outer commons ('Grouped bys) schemas params from ty) where
336+ (Expression outer ('Grouped bys) commons schemas params from ty) where
252 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
337 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
254 ( HasUnique tab (Join outer from) row
339 ( HasUnique tab (Join outer from) row
@@ -256,7 +341,7 @@ instance
256 , GroupedBy tab col bys
341 , GroupedBy tab col bys
257 , tys ~ '[ty]
342 , tys ~ '[ty]
258 ) => IsLabel col
343 ) => IsLabel col
259− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
344+ (NP (Expression outer ('Grouped bys) commons schemas params from) tys) where
260 fromLabel = fromLabel @col :* Nil
345 fromLabel = fromLabel @col :* Nil
262 ( HasUnique tab (Join outer from) row
347 ( HasUnique tab (Join outer from) row
@@ -264,7 +349,7 @@ instance
264 , GroupedBy tab col bys
349 , GroupedBy tab col bys
265 , column ~ (col ::: ty)
350 , column ~ (col ::: ty)
266 ) => IsLabel col
351 ) => IsLabel col
267− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
352+ (Aliased (Expression outer ('Grouped bys) commons schemas params from) column) where
268 fromLabel = fromLabel @col `As` Alias
353 fromLabel = fromLabel @col `As` Alias
270 ( HasUnique tab (Join outer from) row
355 ( HasUnique tab (Join outer from) row
@@ -272,7 +357,7 @@ instance
272 , GroupedBy tab col bys
357 , GroupedBy tab col bys
273 , columns ~ '[col ::: ty]
358 , columns ~ '[col ::: ty]
274 ) => IsLabel col
359 ) => IsLabel col
275− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
360+ (NP (Aliased (Expression outer ('Grouped bys) commons schemas params from)) columns) where
276 fromLabel = fromLabel @col :* Nil
361 fromLabel = fromLabel @col :* Nil
@@ -280,7 +365,7 @@ instance
280 , Has col row ty
365 , Has col row ty
281 , GroupedBy tab col bys
366 , GroupedBy tab col bys
282 ) => IsQualified tab col
367 ) => IsQualified tab col
283− (Expression outer commons ('Grouped bys) schemas params from ty) where
368+ (Expression outer ('Grouped bys) commons schemas params from ty) where
284 tab ! col = UnsafeExpression $
369 tab ! col = UnsafeExpression $
285 renderSQL tab <> "." <> renderSQL col
370 renderSQL tab <> "." <> renderSQL col
@@ -289,7 +374,7 @@ instance
289 , GroupedBy tab col bys
374 , GroupedBy tab col bys
290 , tys ~ '[ty]
375 , tys ~ '[ty]
291 ) => IsQualified tab col
376 ) => IsQualified tab col
292− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
377+ (NP (Expression outer ('Grouped bys) commons schemas params from) tys) where
293 tab ! col = tab ! col :* Nil
378 tab ! col = tab ! col :* Nil
295 ( Has tab (Join outer from) row
380 ( Has tab (Join outer from) row
@@ -297,7 +382,7 @@ instance
297 , GroupedBy tab col bys
382 , GroupedBy tab col bys
298 , column ~ (col ::: ty)
383 , column ~ (col ::: ty)
299 ) => IsQualified tab col
384 ) => IsQualified tab col
300− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
385+ (Aliased (Expression outer ('Grouped bys) commons schemas params from) column) where
301 tab ! col = tab ! col `As` col
386 tab ! col = tab ! col `As` col
303 ( Has tab (Join outer from) row
388 ( Has tab (Join outer from) row
@@ -305,78 +390,244 @@ instance
305 , GroupedBy tab col bys
390 , GroupedBy tab col bys
306 , columns ~ '[col ::: ty]
391 , columns ~ '[col ::: ty]
307 ) => IsQualified tab col
392 ) => IsQualified tab col
308− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
393+ (NP (Aliased (Expression outer ('Grouped bys) commons schemas params from)) columns) where
309 tab ! col = tab ! col :* Nil
394 tab ! col = tab ! col :* Nil
396+-- | analagous to `Nothing`
398+-- >>> printSQL null_
400+null_ :: Expression outer grp commons schemas params from ('Null ty)
401+null_ = UnsafeExpression "NULL"
403+-- | analagous to `Just`
405+-- >>> printSQL $ notNull true
408+ :: Expression outer grp commons schemas params from ('NotNull ty)
409+ -> Expression outer grp commons schemas params from ('Null ty)
410+notNull = UnsafeExpression . renderSQL
412+-- | return the leftmost value which is not NULL
414+-- >>> printSQL $ coalesce [null_, true] false
415+-- COALESCE(NULL, TRUE, FALSE)
417+ :: [Expression outer grp commons schemas params from ('Null ty)]
418+ -- ^ @NULL@s may be present
419+ -> Expression outer grp commons schemas params from ('NotNull ty)
420+ -- ^ @NULL@ is absent
421+ -> Expression outer grp commons schemas params from ('NotNull ty)
422+coalesce nullxs notNullx = UnsafeExpression $
423+ "COALESCE" <> parenthesized (commaSeparated
424+ ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
426+-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
428+-- >>> printSQL $ fromNull true null_
429+-- COALESCE(NULL, TRUE)
431+ :: Expression outer grp commons schemas params from ('NotNull ty)
432+ -- ^ what to convert @NULL@ to
433+ -> Expression outer grp commons schemas params from ('Null ty)
434+ -> Expression outer grp commons schemas params from ('NotNull ty)
435+fromNull notNullx nullx = coalesce [nullx] notNullx
437+-- | >>> printSQL $ null_ & isNull
440+ :: Expression outer grp commons schemas params from ('Null ty)
441+ -- ^ possibly @NULL@
442+ -> Condition outer grp commons schemas params from
443+isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
445+-- | >>> printSQL $ null_ & isNotNull
448+ :: Expression outer grp commons schemas params from ('Null ty)
449+ -- ^ possibly @NULL@
450+ -> Condition outer grp commons schemas params from
451+isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
453+-- | analagous to `maybe` using @IS NULL@
455+-- >>> printSQL $ matchNull true not_ null_
456+-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
458+ :: Expression outer grp commons schemas params from (nullty)
459+ -- ^ what to convert @NULL@ to
460+ -> ( Expression outer grp commons schemas params from ('NotNull ty)
461+ -> Expression outer grp commons schemas params from (nullty) )
462+ -- ^ function to perform when @NULL@ is absent
463+ -> Expression outer grp commons schemas params from ('Null ty)
464+ -> Expression outer grp commons schemas params from (nullty)
465+matchNull y f x = ifThenElse (isNull x) y
466+ (f (UnsafeExpression (renderSQL x)))
468+{-| right inverse to `fromNull`, if its arguments are equal then
469+`nullIf` gives @NULL@.
471+>>> :set -XTypeApplications -XDataKinds
472+>>> let expr = nullIf false (param @1) :: Expression outer grp commons schemas '[ 'NotNull 'PGbool] from ('Null 'PGbool)
474+NULL IF (FALSE, ($1 :: bool))
477+ :: Expression outer grp commons schemas params from ('NotNull ty)
478+ -- ^ @NULL@ is absent
479+ -> Expression outer grp commons schemas params from ('NotNull ty)
480+ -- ^ @NULL@ is absent
481+ -> Expression outer grp commons schemas params from ('Null ty)
482+nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
483+ (renderSQL x <> ", " <> renderSQL y)
485+-- | >>> printSQL $ array [null_, false, true]
486+-- ARRAY[NULL, FALSE, TRUE]
488+ :: [Expression outer grp commons schemas params from ty]
490+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ty))
491+array xs = UnsafeExpression $
492+ "ARRAY[" <> commaSeparated (renderSQL <$> xs) <> "]"
494+-- | >>> printSQL $ cardinality (array [null_, false, true])
495+-- cardinality(ARRAY[NULL, FALSE, TRUE])
497+ :: Expression outer grp commons schemas params from (nullity ('PGvararray ty))
498+ -> Expression outer grp commons schemas params from (nullity 'PGint8)
499+cardinality = unsafeFunction "cardinality"
501+-- | >>> printSQL $ array [null_, false, true] & index 2
502+-- (ARRAY[NULL, FALSE, TRUE])[2]
504+ :: Word64 -- ^ index
505+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ty)) -- ^ array
506+ -> Expression outer grp commons schemas params from (NullifyType ty)
507+index n expr = UnsafeExpression $
508+ parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
510instance (KnownSymbol label, label `In` labels) => IsPGlabel label
312− (Expression outer commons grp schemas params from (null ('PGenum labels))) where
511+ (Expression outer grp commons schemas params from (nullity ('PGenum labels))) where
313 label = UnsafeExpression $ renderSQL (PGlabel @label)
512 label = UnsafeExpression $ renderSQL (PGlabel @label)
514+-- | A row constructor is an expression that builds a row value
515+-- (also called a composite value) using values for its member fields.
518+-- type Complex = 'PGcomposite
519+-- '[ "real" ::: 'NotNull 'PGfloat8
520+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
523+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer grp commons schemas params from ('NotNull Complex)
528+ => NP (Aliased (Expression outer grp commons schemas params from)) row
529+ -- ^ zero or more expressions for the row field values
530+ -> Expression outer grp commons schemas params from (nullity ('PGcomposite row))
531+row exprs = UnsafeExpression $ "ROW" <> parenthesized
532+ (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
535+-- type Complex = 'PGcomposite
536+-- '[ "real" ::: 'NotNull 'PGfloat8
537+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
538+-- type Schema = '["complex" ::: 'Typedef Complex]
541+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer grp '[] (Public Schema) from params ('NotNull Complex)
542+-- >>> printSQL $ i & field #complex #imaginary
543+-- (ROW(0, 1)::"complex")."imaginary"
545+ :: ( Has sch schemas schema
546+ , Has tydef schema ('Typedef ('PGcomposite row))
548+ => QualifiedAlias sch tydef -- ^ row type
549+ -> Alias field -- ^ field name
550+ -> Expression outer grp commons schemas params from ('NotNull ('PGcomposite row))
551+ -> Expression outer grp commons schemas params from ty
552+field td fld expr = UnsafeExpression $
553+ parenthesized (renderSQL expr <> "::" <> renderSQL td)
554+ <> "." <> renderSQL fld
557+ (Expression outer grp commons schemas params from (nullity ('PGvararray ty))) where
558+ (<>) = unsafeBinaryOp "||"
561+ (Expression outer grp commons schemas params from (nullity ('PGvararray ty))) where
565+-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression outer grp commons schemas '[ 'NotNull 'PGtimestamptz] from ('NotNull 'PGtimestamptz)
567+-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
569+ :: Expression outer grp commons schemas params from (nullty)
570+ -- ^ needs at least 1 argument
571+ -> [Expression outer grp commons schemas params from (nullty)]
573+ -> Expression outer grp commons schemas params from (nullty)
574+greatest x xs = UnsafeExpression $ "GREATEST("
575+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
577+-- | >>> printSQL $ least currentTimestamp [null_]
578+-- LEAST(CURRENT_TIMESTAMP, NULL)
580+ :: Expression outer grp commons schemas params from (nullty)
581+ -- ^ needs at least 1 argument
582+ -> [Expression outer grp commons schemas params from (nullty)]
584+ -> Expression outer grp commons schemas params from (nullty)
585+least x xs = UnsafeExpression $ "LEAST("
586+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
588-- | >>> printSQL $ unsafeBinaryOp "OR" true false
316-- (TRUE OR FALSE)
589-- (TRUE OR FALSE)
317−unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
590+unsafeBinaryOp
593+ -> Expression outer grp commons schemas params from (ty0)
594+ -> Expression outer grp commons schemas params from (ty1)
595+ -> Expression outer grp commons schemas params from (ty2)
318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
596unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
319 renderSQL x <+> op <+> renderSQL y
597 renderSQL x <+> op <+> renderSQL y
322− :: forall op sch schemas schema x y z.
323− ( Has sch schemas schema
324− , Has op schema ('Operator ('BinaryOp x y z)) )
325− => OperatorDB schemas x y z
326−binaryOp = unsafeBinaryOp $ renderSymbol @op
328−-- | >>> printSQL $ unsafeLeftOp "NOT" true
599+-- | >>> printSQL $ unsafeUnaryOp "NOT" true
329-- (NOT TRUE)
600-- (NOT TRUE)
330−unsafeLeftOp :: ByteString -> x --> y
602+ :: ByteString
331−unsafeLeftOp op x = UnsafeExpression $ parenthesized $ op <+> renderSQL x
603+ -- ^ operator
332−
604+ -> Expression outer grp commons schemas params from (ty0)
333−leftOp
605+ -> Expression outer grp commons schemas params from (ty1)
334− :: forall op sch schemas schema x y.
335− ( Has sch schemas schema
336− , Has op schema ('Operator ('LeftOp x y)) )
337− => FunctionDB schemas x y
338−leftOp = unsafeLeftOp $ renderSymbol @op
340−-- | >>> printSQL $ true & unsafeRightOp "IS NOT TRUE"
341−-- (TRUE IS NOT TRUE)
342−unsafeRightOp :: ByteString -> x --> y
343−unsafeRightOp op x = UnsafeExpression $ parenthesized $ renderSQL x <+> op
606+unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
344−
607+ op <+> renderSQL x
346− :: forall op sch schemas schema x y.
347− ( Has sch schemas schema
348− , Has op schema ('Operator ('RightOp x y)) )
349− => FunctionDB schemas x y
350−rightOp = unsafeRightOp $ renderSymbol @op
352-- | >>> printSQL $ unsafeFunction "f" true
609-- | >>> printSQL $ unsafeFunction "f" true
353-- f(TRUE)
610-- f(TRUE)
354−unsafeFunction :: ByteString -> x --> y
611+unsafeFunction
614+ -> Expression outer grp commons schemas params from (xty)
615+ -> Expression outer grp commons schemas params from (yty)
355unsafeFunction fun x = UnsafeExpression $
616unsafeFunction fun x = UnsafeExpression $
356 fun <> parenthesized (renderSQL x)
617 fun <> parenthesized (renderSQL x)
358−function
619+-- | Helper for defining variadic functions.
359− :: (Has sch schemas schema, Has fun schema ('Function ('[x] :=> 'Returns y)))
620+unsafeVariadicFunction
360− => QualifiedAlias sch fun
621+ :: SListI elems
361− -> FunctionDB schemas x y
362−function = unsafeFunction . renderSQL
364−-- | >>> printSQL $ unsafeFunctionN "f" (currentTime :* localTimestamp :* false *: literal 'a')
365−-- f(CURRENT_TIME, LOCALTIMESTAMP, FALSE, E'a')
366−unsafeFunctionN :: SListI xs => ByteString -> xs ---> y
622+ => ByteString
624+ -> NP (Expression outer grp commons schemas params from) elems
625+ -> Expression outer grp commons schemas params from ret
367−unsafeFunctionN fun xs = UnsafeExpression $
626+unsafeVariadicFunction fun x = UnsafeExpression $
368− fun <> parenthesized (renderCommaSeparated renderSQL xs)
627+ fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderSQL) x)))
371− :: ( Has sch schemas schema
372− , Has fun schema ('Function (xs :=> 'Returns y))
374− => QualifiedAlias sch fun
375− -> FunctionNDB schemas xs y
376−functionN = unsafeFunctionN . renderSQL
378instance ty `In` PGNum
629instance ty `In` PGNum
379− => Num (Expression outer commons grp schemas params from (null ty)) where
630+ => Num (Expression outer grp commons schemas params from (nullity ty)) where
380 (+) = unsafeBinaryOp "+"
631 (+) = unsafeBinaryOp "+"
381 (-) = unsafeBinaryOp "-"
632 (-) = unsafeBinaryOp "-"
382 (*) = unsafeBinaryOp "*"
633 (*) = unsafeBinaryOp "*"
@@ -388,7 +639,7 @@ instance ty `In` PGNum
390instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
641instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
391− (Expression outer commons grp schemas params from (null ty)) where
642+ (Expression outer grp commons schemas params from (nullity ty)) where
392 (/) = unsafeBinaryOp "/"
643 (/) = unsafeBinaryOp "/"
393 fromRational
644 fromRational
394 = UnsafeExpression
645 = UnsafeExpression
@@ -398,7 +649,7 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
398 . fromRat @Double
649 . fromRat @Double
400instance (ty `In` PGNum, ty `In` PGFloating) => Floating
651instance (ty `In` PGNum, ty `In` PGFloating) => Floating
401− (Expression outer commons grp schemas params from (null ty)) where
652+ (Expression outer grp commons schemas params from (nullity ty)) where
402 pi = UnsafeExpression "pi()"
653 pi = UnsafeExpression "pi()"
403 exp = unsafeFunction "exp"
654 exp = unsafeFunction "exp"
404 log = unsafeFunction "ln"
655 log = unsafeFunction "ln"
@@ -419,54 +670,1748 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
419 acosh x = log (x + sqrt (x*x - 1))
670 acosh x = log (x + sqrt (x*x - 1))
420 atanh x = log ((1 + x) / (1 - x)) / 2
671 atanh x = log ((1 + x) / (1 - x)) / 2
422−-- | Contained by operators
673+-- | >>> :{
423−class PGSubset ty where
674+-- let
424− (@>) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
675+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
425− (@>) = unsafeBinaryOp "@>"
676+-- expression = atan2_ pi 2
426− (<@) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
677+-- in printSQL expression
427− (<@) = unsafeBinaryOp "<@"
678+-- :}
428−instance PGSubset 'PGjsonb
679+-- atan2(pi(), 2)
429−instance PGSubset 'PGtsquery
680+atan2_
430−instance PGSubset ('PGvararray ty)
681+ :: float `In` PGFloating
431−instance PGSubset ('PGrange ty)
682+ => Expression outer grp commons schemas params from (nullity float)
433−class PGIntersect ty where
684+ -> Expression outer grp commons schemas params from (nullity float)
434− (@&&) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
685+ -- ^ denominator
435− (@&&) = unsafeBinaryOp "&&"
686+ -> Expression outer grp commons schemas params from (nullity float)
436−instance PGIntersect ('PGvararray ty)
687+atan2_ y x = UnsafeExpression $
437−instance PGIntersect ('PGrange ty)
688+ "atan2(" <> renderSQL y <> ", " <> renderSQL x <> ")"
690+-- When a `cast` is applied to an `Expression` of a known type, it
691+-- represents a run-time type conversion. The cast will succeed only if a
692+-- suitable type conversion operation has been defined.
694+-- | >>> printSQL $ true & cast int4
697+ :: TypeExpression schemas ty1
698+ -- ^ type to cast as
699+ -> Expression outer grp commons schemas params from ty0
700+ -- ^ value to convert
701+ -> Expression outer grp commons schemas params from ty1
702+cast ty x = UnsafeExpression $ parenthesized $
703+ renderSQL x <+> "::" <+> renderSQL ty
705+-- | integer division, truncates the result
709+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
710+-- expression = 5 `quot_` 2
711+-- in printSQL expression
715+ :: int `In` PGIntegral
716+ => Expression outer grp commons schemas params from (nullity int)
718+ -> Expression outer grp commons schemas params from (nullity int)
720+ -> Expression outer grp commons schemas params from (nullity int)
721+quot_ = unsafeBinaryOp "/"
723+-- | remainder upon integer division
727+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
728+-- expression = 5 `rem_` 2
729+-- in printSQL expression
733+ :: int `In` PGIntegral
734+ => Expression outer grp commons schemas params from (nullity int)
736+ -> Expression outer grp commons schemas params from (nullity int)
738+ -> Expression outer grp commons schemas params from (nullity int)
739+rem_ = unsafeBinaryOp "%"
743+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
744+-- expression = trunc pi
745+-- in printSQL expression
749+ :: frac `In` PGFloating
750+ => Expression outer grp commons schemas params from (nullity frac)
751+ -- ^ fractional number
752+ -> Expression outer grp commons schemas params from (nullity frac)
753+trunc = unsafeFunction "trunc"
757+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
758+-- expression = round_ pi
759+-- in printSQL expression
763+ :: frac `In` PGFloating
764+ => Expression outer grp commons schemas params from (nullity frac)
765+ -- ^ fractional number
766+ -> Expression outer grp commons schemas params from (nullity frac)
767+round_ = unsafeFunction "round"
771+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
772+-- expression = ceiling_ pi
773+-- in printSQL expression
777+ :: frac `In` PGFloating
778+ => Expression outer grp commons schemas params from (nullity frac)
779+ -- ^ fractional number
780+ -> Expression outer grp commons schemas params from (nullity frac)
781+ceiling_ = unsafeFunction "ceiling"
783+-- | A `Condition` is an `Expression`, which can evaluate
784+-- to `true`, `false` or `null_`. This is because SQL uses
785+-- a three valued logic.
786+type Condition outer grp commons schemas params from =
787+ Expression outer grp commons schemas params from ('Null 'PGbool)
789+-- | >>> printSQL true
791+true :: Expression outer grp commons schemas params from (nullity 'PGbool)
792+true = UnsafeExpression "TRUE"
794+-- | >>> printSQL false
796+false :: Expression outer grp commons schemas params from (nullity 'PGbool)
797+false = UnsafeExpression "FALSE"
799+-- | >>> printSQL $ not_ true
802+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
803+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
804+not_ = unsafeUnaryOp "NOT"
806+-- | >>> printSQL $ true .&& false
809+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
810+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
811+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
813+(.&&) = unsafeBinaryOp "AND"
815+-- | >>> printSQL $ true .|| false
818+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
819+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
820+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
822+(.||) = unsafeBinaryOp "OR"
826+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
827+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
828+-- in printSQL expression
830+-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
832+ :: [ ( Condition outer grp commons schemas params from
833+ , Expression outer grp commons schemas params from ty
835+ -- ^ whens and thens
836+ -> Expression outer grp commons schemas params from ty
838+ -> Expression outer grp commons schemas params from ty
839+caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
843+ [ " WHEN ", renderSQL when_
844+ , " THEN ", renderSQL then_
846+ | (when_,then_) <- whenThens
848+ , " ELSE ", renderSQL else_
854+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
855+-- expression = ifThenElse true 1 0
856+-- in printSQL expression
858+-- CASE WHEN TRUE THEN 1 ELSE 0 END
860+ :: Condition outer grp commons schemas params from
861+ -> Expression outer grp commons schemas params from ty -- ^ then
862+ -> Expression outer grp commons schemas params from ty -- ^ else
863+ -> Expression outer grp commons schemas params from ty
864+ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
866+-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
867+-- will produce @NULL@s if one of their arguments is @NULL@.
869+-- >>> printSQL $ true .== null_
872+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
873+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
874+ -> Condition outer grp commons schemas params from
875+(.==) = unsafeBinaryOp "="
878+-- | >>> printSQL $ true ./= null_
881+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
882+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
883+ -> Condition outer grp commons schemas params from
884+(./=) = unsafeBinaryOp "<>"
887+-- | >>> printSQL $ true .>= null_
890+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
891+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
892+ -> Condition outer grp commons schemas params from
893+(.>=) = unsafeBinaryOp ">="
896+-- | >>> printSQL $ true .< null_
899+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
900+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
901+ -> Condition outer grp commons schemas params from
902+(.<) = unsafeBinaryOp "<"
905+-- | >>> printSQL $ true .<= null_
908+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
909+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
910+ -> Condition outer grp commons schemas params from
911+(.<=) = unsafeBinaryOp "<="
914+-- | >>> printSQL $ true .> null_
917+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
918+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
919+ -> Condition outer grp commons schemas params from
920+(.>) = unsafeBinaryOp ">"
923+-- | >>> printSQL currentDate
926+ :: Expression outer grp commons schemas params from (nullity 'PGdate)
927+currentDate = UnsafeExpression "CURRENT_DATE"
929+-- | >>> printSQL currentTime
932+ :: Expression outer grp commons schemas params from (nullity 'PGtimetz)
933+currentTime = UnsafeExpression "CURRENT_TIME"
935+-- | >>> printSQL currentTimestamp
938+ :: Expression outer grp commons schemas params from (nullity 'PGtimestamptz)
939+currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
941+-- | >>> printSQL localTime
944+ :: Expression outer grp commons schemas params from (nullity 'PGtime)
945+localTime = UnsafeExpression "LOCALTIME"
947+-- | >>> printSQL localTimestamp
950+ :: Expression outer grp commons schemas params from (nullity 'PGtimestamp)
951+localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
953+{-----------------------------------------
955+-----------------------------------------}
439instance IsString
957instance IsString
440− (Expression outer commons grp schemas params from (null 'PGtext)) where
958+ (Expression outer grp commons schemas params from (nullity 'PGtext)) where
441 fromString str = UnsafeExpression $
959 fromString str = UnsafeExpression $
442 "E\'" <> fromString (escape =<< str) <> "\'"
960 "E\'" <> fromString (escape =<< str) <> "\'"
443−instance IsString
961+ where
444− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
962+ escape = \case
445− fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
963+ '\NUL' -> "\\0"
446− "E\'" <> fromString (escape =<< str) <> "\'"
964+ '\'' -> "''"
447−instance IsString
965+ '"' -> "\\\""
448− (Expression outer commons grp schemas params from (null 'PGtsquery)) where
966+ '\b' -> "\\b"
449− fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
967+ '\n' -> "\\n"
450− "E\'" <> fromString (escape =<< str) <> "\'"
968+ '\r' -> "\\r"
452instance Semigroup
973instance Semigroup
453− (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
454− (<>) = unsafeBinaryOp "||"
456− (Expression outer commons grp schemas params from (null 'PGjsonb)) where
457− (<>) = unsafeBinaryOp "||"
459− (Expression outer commons grp schemas params from (null 'PGtext)) where
974+ (Expression outer grp commons schemas params from (nullity 'PGtext)) where
460− (<>) = unsafeBinaryOp "||"
462− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
463 (<>) = unsafeBinaryOp "||"
975 (<>) = unsafeBinaryOp "||"
465instance Monoid
977instance Monoid
466− (Expression outer commons grp schemas params from (null 'PGtext)) where
978+ (Expression outer grp commons schemas params from (nullity 'PGtext)) where
467− mempty = fromString ""
470− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
471 mempty = fromString ""
979 mempty = fromString ""
472 mappend = (<>)
980 mappend = (<>)
982+-- | >>> printSQL $ lower "ARRRGGG"
985+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
986+ -- ^ string to lower case
987+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
988+lower = unsafeFunction "lower"
990+-- | >>> printSQL $ upper "eeee"
993+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
994+ -- ^ string to upper case
995+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
996+upper = unsafeFunction "upper"
998+-- | >>> printSQL $ charLength "four"
999+-- char_length(E'four')
1001+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1002+ -- ^ string to measure
1003+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1004+charLength = unsafeFunction "char_length"
1006+-- | The `like` expression returns true if the @string@ matches
1007+-- the supplied @pattern@. If @pattern@ does not contain percent signs
1008+-- or underscores, then the pattern only represents the string itself;
1009+-- in that case `like` acts like the equals operator. An underscore (_)
1010+-- in pattern stands for (matches) any single character; a percent sign (%)
1011+-- matches any sequence of zero or more characters.
1013+-- >>> printSQL $ "abc" `like` "a%"
1014+-- (E'abc' LIKE E'a%')
1016+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1018+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1020+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
1021+like = unsafeBinaryOp "LIKE"
1023+-- | The key word ILIKE can be used instead of LIKE to make the
1024+-- match case-insensitive according to the active locale.
1026+-- >>> printSQL $ "abc" `ilike` "a%"
1027+-- (E'abc' ILIKE E'a%')
1029+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1031+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1033+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
1034+ilike = unsafeBinaryOp "ILIKE"
1036+{-----------------------------------------
1037+ -- json and jsonb support
1039+See https://www.postgresql.org/docs/10/static/functions-json.html -- most
1040+comments lifted directly from this page.
1042+Table 9.44: json and jsonb operators
1043+-----------------------------------------}
1045+-- | Get JSON value (object field or array element) at a key.
1047+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1048+ => Expression outer grp commons schemas params from (nullity json)
1049+ -> Expression outer grp commons schemas params from (nullity key)
1050+ -> Expression outer grp commons schemas params from ('Null json)
1052+(.->) = unsafeBinaryOp "->"
1054+-- | Get JSON value (object field or array element) at a key, as text.
1056+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1057+ => Expression outer grp commons schemas params from (nullity json)
1058+ -> Expression outer grp commons schemas params from (nullity key)
1059+ -> Expression outer grp commons schemas params from ('Null 'PGtext)
1061+(.->>) = unsafeBinaryOp "->>"
1063+-- | Get JSON value at a specified path.
1065+ :: (json `In` PGJsonType, PGTextArray "(.#>)" path)
1066+ => Expression outer grp commons schemas params from (nullity json)
1067+ -> Expression outer grp commons schemas params from (nullity path)
1068+ -> Expression outer grp commons schemas params from ('Null json)
1070+(.#>) = unsafeBinaryOp "#>"
1072+-- | Get JSON value at a specified path as text.
1074+ :: (json `In` PGJsonType, PGTextArray "(.#>>)" path)
1075+ => Expression outer grp commons schemas params from (nullity json)
1076+ -> Expression outer grp commons schemas params from (nullity path)
1077+ -> Expression outer grp commons schemas params from ('Null 'PGtext)
1079+(.#>>) = unsafeBinaryOp "#>>"
1081+-- Additional jsonb operators
1083+-- | Does the left JSON value contain the right JSON path/value entries at the
1086+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1087+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1088+ -> Condition outer grp commons schemas params from
1090+(.@>) = unsafeBinaryOp "@>"
1092+-- | Are the left JSON path/value entries contained at the top level within the
1093+-- right JSON value?
1095+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1096+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1097+ -> Condition outer grp commons schemas params from
1099+(.<@) = unsafeBinaryOp "<@"
1101+-- | Does the string exist as a top-level key within the JSON value?
1103+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1104+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1105+ -> Condition outer grp commons schemas params from
1107+(.?) = unsafeBinaryOp "?"
1109+-- | Do any of these array strings exist as top-level keys?
1111+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1112+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1113+ -> Condition outer grp commons schemas params from
1115+(.?|) = unsafeBinaryOp "?|"
1117+-- | Do all of these array strings exist as top-level keys?
1119+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1120+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1121+ -> Condition outer grp commons schemas params from
1123+(.?&) = unsafeBinaryOp "?&"
1125+-- | Concatenate two jsonb values into a new jsonb value.
1127+ (Expression outer grp commons schemas params from (nullity 'PGjsonb)) where
1128+ (<>) = unsafeBinaryOp "||"
1130+-- | Delete a key or keys from a JSON object, or remove an array element.
1132+-- If the right operand is..
1134+-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1135+-- are matched based on their key value.
1137+-- @ text[] @: Delete multiple key/value pairs or string elements
1138+-- from left operand. Key/value pairs are matched based on their key value.
1140+-- @ integer @: Delete the array element with specified index (Negative integers
1141+-- count from the end). Throws an error if top level container is not an array.
1143+ :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1144+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1145+ -> Expression outer grp commons schemas params from (nullity key)
1146+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1148+(.-.) = unsafeBinaryOp "-"
1150+-- | Delete the field or element with specified path (for JSON arrays, negative
1151+-- integers count from the end)
1153+ :: PGTextArray "(#-.)" arrayty
1154+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1155+ -> Expression outer grp commons schemas params from (nullity arrayty)
1156+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1158+(#-.) = unsafeBinaryOp "#-"
1160+{-----------------------------------------
1161+Table 9.45: JSON creation functions
1162+-----------------------------------------}
1164+-- | Literal binary JSON
1167+ => x -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1168+jsonbLit = cast jsonb . UnsafeExpression
1169+ . singleQuotedUtf8 . toStrict . JSON.encode
1174+ => x -> Expression outer grp commons schemas params from (nullity 'PGjson)
1175+jsonLit = cast json . UnsafeExpression
1176+ . singleQuotedUtf8 . toStrict . JSON.encode
1178+-- | Returns the value as json. Arrays and composites are converted
1179+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1180+-- type to json, the cast function will be used to perform the conversion;
1181+-- otherwise, a scalar value is produced. For any scalar type other than a
1182+-- number, a Boolean, or a null value, the text representation will be used, in
1183+-- such a fashion that it is a valid json value.
1185+ :: Expression outer grp commons schemas params from (nullity ty)
1186+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1187+toJson = unsafeFunction "to_json"
1189+-- | Returns the value as jsonb. Arrays and composites are converted
1190+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1191+-- type to json, the cast function will be used to perform the conversion;
1192+-- otherwise, a scalar value is produced. For any scalar type other than a
1193+-- number, a Boolean, or a null value, the text representation will be used, in
1194+-- such a fashion that it is a valid jsonb value.
1196+ :: Expression outer grp commons schemas params from (nullity ty)
1197+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1198+toJsonb = unsafeFunction "to_jsonb"
1200+-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1201+-- becomes a JSON array of arrays.
1203+ :: PGArray "arrayToJson" arr
1204+ => Expression outer grp commons schemas params from (nullity arr)
1205+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1206+arrayToJson = unsafeFunction "array_to_json"
1208+-- | Returns the row as a JSON object.
1210+ :: Expression outer grp commons schemas params from (nullity ('PGcomposite ty))
1211+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1212+rowToJson = unsafeFunction "row_to_json"
1214+-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1218+ => NP (Expression outer grp commons schemas params from) elems
1219+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1220+jsonBuildArray = unsafeVariadicFunction "json_build_array"
1222+-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1223+-- variadic argument list.
1226+ => NP (Expression outer grp commons schemas params from) elems
1227+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1228+jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1231+ :: SOP.SListI elems
1232+ => NP (Aliased (Expression outer grp commons schemas params from)) elems
1235+ (`appEndo` []) . hcfoldMap (Proxy :: SOP.Proxy SOP.Top)
1236+ (\(col `As` name) -> Endo $ \xs ->
1237+ renderAliasString name : renderSQL col : xs)
1239+ renderAliasString :: KnownSymbol alias => Alias alias -> ByteString
1240+ renderAliasString = singleQuotedText . fromString . symbolVal
1242+-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1243+-- argument list. The elements of the argument list must alternate between text
1246+ :: SOP.SListI elems
1247+ => NP (Aliased (Expression outer grp commons schemas params from)) elems
1248+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1250+ = unsafeFunction "json_build_object"
1253+ . unsafeRowFunction
1255+-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1256+-- variadic argument list. The elements of the argument list must alternate
1257+-- between text and values.
1259+ :: SOP.SListI elems
1260+ => NP (Aliased (Expression outer grp commons schemas params from)) elems
1261+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1263+ = unsafeFunction "jsonb_build_object"
1266+ . unsafeRowFunction
1268+-- | Builds a JSON object out of a text array. The array must have either
1269+-- exactly one dimension with an even number of members, in which case they are
1270+-- taken as alternating key/value pairs, or two dimensions such that each inner
1271+-- array has exactly two elements, which are taken as a key/value pair.
1273+ :: PGArrayOf "jsonObject" arr ('NotNull 'PGtext)
1274+ => Expression outer grp commons schemas params from (nullity arr)
1275+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1276+jsonObject = unsafeFunction "json_object"
1278+-- | Builds a binary JSON object out of a text array. The array must have either
1279+-- exactly one dimension with an even number of members, in which case they are
1280+-- taken as alternating key/value pairs, or two dimensions such that each inner
1281+-- array has exactly two elements, which are taken as a key/value pair.
1283+ :: PGArrayOf "jsonbObject" arr ('NotNull 'PGtext)
1284+ => Expression outer grp commons schemas params from (nullity arr)
1285+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1286+jsonbObject = unsafeFunction "jsonb_object"
1288+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1289+-- keys and one for values, that are zipped pairwise to create a JSON object.
1291+ :: ( PGArrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1292+ , PGArrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
1293+ => Expression outer grp commons schemas params from (nullity keysArray)
1294+ -> Expression outer grp commons schemas params from (nullity valuesArray)
1295+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1296+jsonZipObject ks vs =
1297+ unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1299+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1300+-- keys and one for values, that are zipped pairwise to create a binary JSON
1303+ :: ( PGArrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1304+ , PGArrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
1305+ => Expression outer grp commons schemas params from (nullity keysArray)
1306+ -> Expression outer grp commons schemas params from (nullity valuesArray)
1307+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1308+jsonbZipObject ks vs =
1309+ unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1311+{-----------------------------------------
1312+Table 9.46: JSON processing functions
1313+-----------------------------------------}
1315+-- | Returns the number of elements in the outermost JSON array.
1317+ :: Expression outer grp commons schemas params from (nullity 'PGjson)
1318+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1319+jsonArrayLength = unsafeFunction "json_array_length"
1321+-- | Returns the number of elements in the outermost binary JSON array.
1323+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1324+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1325+jsonbArrayLength = unsafeFunction "jsonb_array_length"
1327+-- | Returns JSON value pointed to by the given path (equivalent to #>
1331+ => Expression outer grp commons schemas params from (nullity 'PGjson)
1332+ -> NP (Expression outer grp commons schemas params from) elems
1333+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1334+jsonExtractPath x xs =
1335+ unsafeVariadicFunction "json_extract_path" (x :* xs)
1337+-- | Returns JSON value pointed to by the given path (equivalent to #>
1341+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1342+ -> NP (Expression outer grp commons schemas params from) elems
1343+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1344+jsonbExtractPath x xs =
1345+ unsafeVariadicFunction "jsonb_extract_path" (x :* xs)
1347+-- | Returns JSON value pointed to by the given path (equivalent to #>
1348+-- operator), as text.
1349+jsonExtractPathAsText
1351+ => Expression outer grp commons schemas params from (nullity 'PGjson)
1352+ -> NP (Expression outer grp commons schemas params from) elems
1353+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1354+jsonExtractPathAsText x xs =
1355+ unsafeVariadicFunction "json_extract_path_text" (x :* xs)
1357+-- | Returns JSON value pointed to by the given path (equivalent to #>
1358+-- operator), as text.
1359+jsonbExtractPathAsText
1361+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1362+ -> NP (Expression outer grp commons schemas params from) elems
1363+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1364+jsonbExtractPathAsText x xs =
1365+ unsafeVariadicFunction "jsonb_extract_path_text" (x :* xs)
1367+-- | Returns the type of the outermost JSON value as a text string. Possible
1368+-- types are object, array, string, number, boolean, and null.
1370+ :: Expression outer grp commons schemas params from (nullity 'PGjson)
1371+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1372+jsonTypeof = unsafeFunction "json_typeof"
1374+-- | Returns the type of the outermost binary JSON value as a text string.
1375+-- Possible types are object, array, string, number, boolean, and null.
1377+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1378+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1379+jsonbTypeof = unsafeFunction "jsonb_typeof"
1381+-- | Returns its argument with all object fields that have null values omitted.
1382+-- Other null values are untouched.
1384+ :: Expression outer grp commons schemas params from (nullity 'PGjson)
1385+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1386+jsonStripNulls = unsafeFunction "json_strip_nulls"
1388+-- | Returns its argument with all object fields that have null values omitted.
1389+-- Other null values are untouched.
1391+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1392+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1393+jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1395+-- | @ jsonbSet target path new_value create_missing @
1397+-- Returns target with the section designated by path replaced by new_value,
1398+-- or with new_value added if create_missing is true ( default is true) and the
1399+-- item designated by path does not exist. As with the path orientated
1400+-- operators, negative integers that appear in path count from the end of JSON
1403+ :: PGTextArray "jsonbSet" arr
1404+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1405+ -> Expression outer grp commons schemas params from (nullity arr)
1406+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1407+ -> Maybe (Expression outer grp commons schemas params from (nullity 'PGbool))
1408+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1409+jsonbSet tgt path val createMissing = case createMissing of
1410+ Just m -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* m :* Nil)
1411+ Nothing -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* Nil)
1413+-- | @ jsonbInsert target path new_value insert_after @
1415+-- Returns target with new_value inserted. If target section designated by
1416+-- path is in a JSONB array, new_value will be inserted before target or after
1417+-- if insert_after is true (default is false). If target section designated by
1418+-- path is in JSONB object, new_value will be inserted only if target does not
1419+-- exist. As with the path orientated operators, negative integers that appear
1420+-- in path count from the end of JSON arrays.
1422+ :: PGTextArray "jsonbInsert" arr
1423+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1424+ -> Expression outer grp commons schemas params from (nullity arr)
1425+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1426+ -> Maybe (Expression outer grp commons schemas params from (nullity 'PGbool))
1427+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1428+jsonbInsert tgt path val insertAfter = case insertAfter of
1429+ Just i -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1430+ Nothing -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* Nil)
1432+-- | Returns its argument as indented JSON text.
1434+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1435+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1436+jsonbPretty = unsafeFunction "jsonb_pretty"
1438+{-----------------------------------------
1440+-----------------------------------------}
1443+`Aggregate` functions compute a single result from a set of input values.
1444+`Aggregate` functions can be used as `GroupedBy` `Expression`s as well
1445+as `WindowFunction`s.
1447+class Aggregate expr1 expr2 aggr
1448+ | aggr -> expr1, aggr -> expr2 where
1450+ -- | A special aggregation that does not require an input
1454+ -- expression :: Expression '[] ('Grouped bys) commons schemas params from ('NotNull 'PGint8)
1455+ -- expression = countStar
1456+ -- in printSQL expression
1459+ countStar :: aggr ('NotNull 'PGint8)
1463+ -- expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1464+ -- expression = count (All #col)
1465+ -- in printSQL expression
1467+ -- count(ALL "col")
1471+ -> aggr ('NotNull 'PGint8)
1475+ -- expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('NotNull 'PGnumeric)
1476+ -- expression = sum_ (Distinct #col)
1477+ -- in printSQL expression
1479+ -- sum(DISTINCT "col")
1482+ => expr1 (nullity ty)
1483+ -> aggr ('NotNull ty)
1485+ -- | input values, including nulls, concatenated into an array
1488+ -> aggr ('Null ('PGvararray ty))
1490+ -- | aggregates values as a JSON array
1493+ -> aggr ('Null 'PGjson)
1495+ -- | aggregates values as a JSON array
1498+ -> aggr ('Null 'PGjsonb)
1501+ the bitwise AND of all non-null input values, or null if none
1504+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] ('Null 'PGint4)
1505+ expression = bitAnd (Distinct #col)
1506+ in printSQL expression
1508+ bit_and(DISTINCT "col")
1511+ :: int `In` PGIntegral
1512+ => expr1 (nullity int)
1513+ -- ^ what to aggregate
1514+ -> aggr ('Null int)
1517+ the bitwise OR of all non-null input values, or null if none
1521+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] ('Null 'PGint4)
1522+ expression = bitOr (All #col)
1523+ in printSQL expression
1528+ :: int `In` PGIntegral
1529+ => expr1 (nullity int)
1530+ -- ^ what to aggregate
1531+ -> aggr ('Null int)
1534+ true if all input values are true, otherwise false
1538+ winFun :: WindowFunction '[] 'Ungrouped commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] ('Null 'PGbool)
1539+ winFun = boolAnd #col
1545+ :: expr1 (nullity 'PGbool)
1546+ -- ^ what to aggregate
1547+ -> aggr ('Null 'PGbool)
1550+ true if at least one input value is true, otherwise false
1554+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] ('Null 'PGbool)
1555+ expression = boolOr (All #col)
1556+ in printSQL expression
1561+ :: expr1(nullity 'PGbool)
1562+ -- ^ what to aggregate
1563+ -> aggr ('Null 'PGbool)
1566+ equivalent to `boolAnd`
1570+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] ('Null 'PGbool)
1571+ expression = every (Distinct #col)
1572+ in printSQL expression
1574+ every(DISTINCT "col")
1577+ :: expr1 (nullity 'PGbool)
1578+ -- ^ what to aggregate
1579+ -> aggr ('Null 'PGbool)
1581+ {- |maximum value of expression across all input values-}
1583+ :: expr1 (nullity ty)
1584+ -- ^ what to maximize
1587+ -- | minimum value of expression across all input values
1589+ :: expr1 (nullity ty)
1590+ -- ^ what to minimize
1593+ -- | the average (arithmetic mean) of all input values
1595+ :: expr1 (nullity ty)
1596+ -- ^ what to average
1597+ -> aggr ('Null (PGAvg ty))
1599+ {- | correlation coefficient
1602+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1603+ expression = corr (All (#y :*: #x))
1604+ in printSQL expression
1609+ :: expr2 (nullity 'PGfloat8)
1610+ -> aggr ('Null 'PGfloat8)
1612+ {- | population covariance
1615+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1616+ expression = covarPop (All (#y :*: #x))
1617+ in printSQL expression
1619+ covar_pop(ALL "y", "x")
1622+ :: expr2 (nullity 'PGfloat8)
1623+ -> aggr ('Null 'PGfloat8)
1625+ {- | sample covariance
1628+ winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1629+ winFun = covarSamp (#y :*: #x)
1632+ covar_samp("y", "x")
1635+ :: expr2 (nullity 'PGfloat8)
1636+ -> aggr ('Null 'PGfloat8)
1638+ {- | average of the independent variable (sum(X)/N)
1641+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1642+ expression = regrAvgX (All (#y :*: #x))
1643+ in printSQL expression
1645+ regr_avgx(ALL "y", "x")
1648+ :: expr2 (nullity 'PGfloat8)
1649+ -> aggr ('Null 'PGfloat8)
1651+ {- | average of the dependent variable (sum(Y)/N)
1654+ winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1655+ winFun = regrAvgY (#y :*: #x)
1658+ regr_avgy("y", "x")
1661+ :: expr2 (nullity 'PGfloat8)
1662+ -> aggr ('Null 'PGfloat8)
1664+ {- | number of input rows in which both expressions are nonnull
1667+ winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGint8)
1668+ winFun = regrCount (#y :*: #x)
1671+ regr_count("y", "x")
1674+ :: expr2 (nullity 'PGfloat8)
1675+ -> aggr ('Null 'PGint8)
1677+ {- | y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs
1680+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1681+ expression = regrIntercept (All (#y :*: #x))
1682+ in printSQL expression
1684+ regr_intercept(ALL "y", "x")
1687+ :: expr2 (nullity 'PGfloat8)
1688+ -> aggr ('Null 'PGfloat8)
1690+ -- | @regr_r2(Y, X)@, square of the correlation coefficient
1692+ :: expr2 (nullity 'PGfloat8)
1693+ -> aggr ('Null 'PGfloat8)
1695+ -- | @regr_slope(Y, X)@, slope of the least-squares-fit linear equation
1696+ -- determined by the (X, Y) pairs
1698+ :: expr2 (nullity 'PGfloat8)
1699+ -> aggr ('Null 'PGfloat8)
1701+ -- | @regr_sxx(Y, X)@, sum(X^2) - sum(X)^2/N
1702+ -- (“sum of squares” of the independent variable)
1704+ :: expr2 (nullity 'PGfloat8)
1705+ -> aggr ('Null 'PGfloat8)
1707+ -- | @regr_sxy(Y, X)@, sum(X*Y) - sum(X) * sum(Y)/N
1708+ -- (“sum of products” of independent times dependent variable)
1710+ :: expr2 (nullity 'PGfloat8)
1711+ -> aggr ('Null 'PGfloat8)
1713+ -- | @regr_syy(Y, X)@, sum(Y^2) - sum(Y)^2/N
1714+ -- (“sum of squares” of the dependent variable)
1716+ :: expr2 (nullity 'PGfloat8)
1717+ -> aggr ('Null 'PGfloat8)
1719+ -- | historical alias for `stddevSamp`
1721+ :: expr1 (nullity ty)
1722+ -> aggr ('Null (PGAvg ty))
1724+ -- | population standard deviation of the input values
1726+ :: expr1 (nullity ty)
1727+ -> aggr ('Null (PGAvg ty))
1729+ -- | sample standard deviation of the input values
1731+ :: expr1 (nullity ty)
1732+ -> aggr ('Null (PGAvg ty))
1734+ -- | historical alias for `varSamp`
1736+ :: expr1 (nullity ty)
1737+ -> aggr ('Null (PGAvg ty))
1739+ -- | population variance of the input values
1740+ -- (square of the population standard deviation)
1742+ :: expr1 (nullity ty)
1743+ -> aggr ('Null (PGAvg ty))
1745+ -- | sample variance of the input values
1746+ -- (square of the sample standard deviation)
1748+ :: expr1 (nullity ty)
1749+ -> aggr ('Null (PGAvg ty))
1752+`Distinction`s are used for the input of `Aggregate` `Expression`s.
1753+`All` invokes the aggregate once for each input row.
1754+`Distinct` invokes the aggregate once for each distinct value of the expression
1755+(or distinct set of values, for multiple expressions) found in the input
1757+data Distinction expr ty
1759+ | Distinct (expr ty)
1760+ deriving (GHC.Generic,Show,Eq,Ord)
1761+instance NFData (Distinction (Expression outer grp commons schemas params from) ty)
1762+instance RenderSQL (Distinction (Expression outer grp commons schemas params from) ty) where
1764+ All x -> "ALL" <+> renderSQL x
1765+ Distinct x -> "DISTINCT" <+> renderSQL x
1768+ ( Expression outer grp commons schemas params from
1770+ Expression outer grp commons schemas params from) xty ) where
1773+ "ALL" <+> renderSQL x <> ", " <> renderSQL x'
1774+ Distinct (x :*: x') ->
1775+ "DISTINCT" <+> renderSQL x <> ", " <> renderSQL x'
1778+ (Distinction (Expression outer 'Ungrouped commons schemas params from))
1779+ (Distinction (Expression outer 'Ungrouped commons schemas params from :*: Expression outer 'Ungrouped commons schemas params from))
1780+ (Expression outer ('Grouped bys) commons schemas params from) where
1781+ countStar = UnsafeExpression "count(*)"
1782+ count = unsafeAggregate1 "count"
1783+ sum_ = unsafeAggregate1 "sum"
1784+ arrayAgg = unsafeAggregate1 "array_agg"
1785+ jsonAgg = unsafeAggregate1 "json_agg"
1786+ jsonbAgg = unsafeAggregate1 "jsonb_agg"
1787+ bitAnd = unsafeAggregate1 "bit_and"
1788+ bitOr = unsafeAggregate1 "bit_or"
1789+ boolAnd = unsafeAggregate1 "bool_and"
1790+ boolOr = unsafeAggregate1 "bool_or"
1791+ every = unsafeAggregate1 "every"
1792+ max_ = unsafeAggregate1 "max"
1793+ min_ = unsafeAggregate1 "min"
1794+ avg = unsafeAggregate1 "avg"
1795+ corr = unsafeAggregate2 "corr"
1796+ covarPop = unsafeAggregate2 "covar_pop"
1797+ covarSamp = unsafeAggregate2 "covar_samp"
1798+ regrAvgX = unsafeAggregate2 "regr_avgx"
1799+ regrAvgY = unsafeAggregate2 "regr_avgy"
1800+ regrCount = unsafeAggregate2 "regr_count"
1801+ regrIntercept = unsafeAggregate2 "regr_intercept"
1802+ regrR2 = unsafeAggregate2 "regr_r2"
1803+ regrSlope = unsafeAggregate2 "regr_slope"
1804+ regrSxx = unsafeAggregate2 "regr_sxx"
1805+ regrSxy = unsafeAggregate2 "regr_sxy"
1806+ regrSyy = unsafeAggregate2 "regr_syy"
1807+ stddev = unsafeAggregate1 "stddev"
1808+ stddevPop = unsafeAggregate1 "stddev_pop"
1809+ stddevSamp = unsafeAggregate1 "stddev_samp"
1810+ variance = unsafeAggregate1 "variance"
1811+ varPop = unsafeAggregate1 "var_pop"
1812+ varSamp = unsafeAggregate1 "var_samp"
1814+ (Expression outer grp commons schemas params from)
1815+ (Expression outer grp commons schemas params from :*: Expression outer grp commons schemas params from)
1816+ (WindowFunction outer grp commons schemas params from) where
1817+ countStar = UnsafeWindowFunction "count(*)"
1818+ count = unsafeWindowFunction1 "count"
1819+ sum_ = unsafeWindowFunction1 "sum"
1820+ arrayAgg = unsafeWindowFunction1 "array_agg"
1821+ jsonAgg = unsafeWindowFunction1 "json_agg"
1822+ jsonbAgg = unsafeWindowFunction1 "jsonb_agg"
1823+ bitAnd = unsafeWindowFunction1 "bit_and"
1824+ bitOr = unsafeWindowFunction1 "bit_or"
1825+ boolAnd = unsafeWindowFunction1 "bool_and"
1826+ boolOr = unsafeWindowFunction1 "bool_or"
1827+ every = unsafeWindowFunction1 "every"
1828+ max_ = unsafeWindowFunction1 "max"
1829+ min_ = unsafeWindowFunction1 "min"
1830+ avg = unsafeWindowFunction1 "avg"
1831+ corr = unsafeWindowFunction2 "corr"
1832+ covarPop = unsafeWindowFunction2 "covar_pop"
1833+ covarSamp = unsafeWindowFunction2 "covar_samp"
1834+ regrAvgX = unsafeWindowFunction2 "regr_avgx"
1835+ regrAvgY = unsafeWindowFunction2 "regr_avgy"
1836+ regrCount = unsafeWindowFunction2 "regr_count"
1837+ regrIntercept = unsafeWindowFunction2 "regr_intercept"
1838+ regrR2 = unsafeWindowFunction2 "regr_r2"
1839+ regrSlope = unsafeWindowFunction2 "regr_slope"
1840+ regrSxx = unsafeWindowFunction2 "regr_sxx"
1841+ regrSxy = unsafeWindowFunction2 "regr_sxy"
1842+ regrSyy = unsafeWindowFunction2 "regr_syy"
1843+ stddev = unsafeWindowFunction1 "stddev"
1844+ stddevPop = unsafeWindowFunction1 "stddev_pop"
1845+ stddevSamp = unsafeWindowFunction1 "stddev_samp"
1846+ variance = unsafeWindowFunction1 "variance"
1847+ varPop = unsafeWindowFunction1 "var_pop"
1848+ varSamp = unsafeWindowFunction1 "var_samp"
1850+-- | escape hatch to define aggregate functions
1852+ :: ByteString -- ^ aggregate function
1853+ -> Distinction (Expression outer 'Ungrouped commons schemas params from) xty
1854+ -> Expression outer ('Grouped bys) commons schemas params from yty
1855+unsafeAggregate1 fun x = UnsafeExpression $ mconcat
1856+ [fun, "(", renderSQL x, ")"]
1858+-- | escape hatch to define aggregate binary functions
1860+ :: ByteString -- ^ aggregate function
1861+ -> Distinction (Expression outer 'Ungrouped commons schemas params from :*: Expression outer 'Ungrouped commons schemas params from) xty
1862+ -> Expression outer ('Grouped bys) commons schemas params from yty
1863+unsafeAggregate2 fun xx = UnsafeExpression $ mconcat
1864+ [fun, "(", renderSQL xx, ")"]
1866+-- | A type family that calculates `PGAvg` type of a `PGType`.
1867+type family PGAvg ty where
1868+ PGAvg 'PGint2 = 'PGnumeric
1869+ PGAvg 'PGint4 = 'PGnumeric
1870+ PGAvg 'PGint8 = 'PGnumeric
1871+ PGAvg 'PGnumeric = 'PGnumeric
1872+ PGAvg 'PGfloat4 = 'PGfloat8
1873+ PGAvg 'PGfloat8 = 'PGfloat8
1874+ PGAvg 'PGinterval = 'PGinterval
1875+ PGAvg pg = TypeError
1876+ ('Text "Squeal type error: No average for " ':<>: 'ShowType pg)
1878+{-----------------------------------------
1880+-----------------------------------------}
1882+-- | `TypeExpression`s are used in `cast`s and
1883+-- `Squeal.PostgreSQL.Definition.createTable` commands.
1884+newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
1885+ = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1886+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
1887+instance RenderSQL (TypeExpression schemas ty) where
1888+ renderSQL = renderTypeExpression
1890+-- | The enum or composite type in a `Typedef` can be expressed by its alias.
1892+ :: (Has sch schemas schema, Has td schema ('Typedef ty))
1893+ => QualifiedAlias sch td
1894+ -> TypeExpression schemas (nullity ty)
1895+typedef = UnsafeTypeExpression . renderSQL
1897+-- | The composite type corresponding to a `Table` definition can be expressed
1900+ :: (Has sch schemas schema, Has tab schema ('Table table))
1901+ => QualifiedAlias sch tab
1902+ -> TypeExpression schemas (nullity ('PGcomposite (TableToRow table)))
1903+typetable = UnsafeTypeExpression . renderSQL
1905+-- | The composite type corresponding to a `View` definition can be expressed
1908+ :: (Has sch schemas schema, Has vw schema ('View view))
1909+ => QualifiedAlias sch vw
1910+ -> TypeExpression schemas (nullity ('PGcomposite view))
1911+typeview = UnsafeTypeExpression . renderSQL
1913+-- | logical Boolean (true/false)
1914+bool :: TypeExpression schemas (nullity 'PGbool)
1915+bool = UnsafeTypeExpression "bool"
1916+-- | signed two-byte integer
1917+int2, smallint :: TypeExpression schemas (nullity 'PGint2)
1918+int2 = UnsafeTypeExpression "int2"
1919+smallint = UnsafeTypeExpression "smallint"
1920+-- | signed four-byte integer
1921+int4, int, integer :: TypeExpression schemas (nullity 'PGint4)
1922+int4 = UnsafeTypeExpression "int4"
1923+int = UnsafeTypeExpression "int"
1924+integer = UnsafeTypeExpression "integer"
1925+-- | signed eight-byte integer
1926+int8, bigint :: TypeExpression schemas (nullity 'PGint8)
1927+int8 = UnsafeTypeExpression "int8"
1928+bigint = UnsafeTypeExpression "bigint"
1929+-- | arbitrary precision numeric type
1930+numeric :: TypeExpression schemas (nullity 'PGnumeric)
1931+numeric = UnsafeTypeExpression "numeric"
1932+-- | single precision floating-point number (4 bytes)
1933+float4, real :: TypeExpression schemas (nullity 'PGfloat4)
1934+float4 = UnsafeTypeExpression "float4"
1935+real = UnsafeTypeExpression "real"
1936+-- | double precision floating-point number (8 bytes)
1937+float8, doublePrecision :: TypeExpression schemas (nullity 'PGfloat8)
1938+float8 = UnsafeTypeExpression "float8"
1939+doublePrecision = UnsafeTypeExpression "double precision"
1940+-- | currency amount
1941+money :: TypeExpression schema (nullity 'PGmoney)
1942+money = UnsafeTypeExpression "money"
1943+-- | variable-length character string
1944+text :: TypeExpression schemas (nullity 'PGtext)
1945+text = UnsafeTypeExpression "text"
1946+-- | fixed-length character string
1948+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
1949+ => TypeExpression schemas (nullity ('PGchar n))
1950+char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
1951+character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
1952+-- | variable-length character string
1953+varchar, characterVarying
1954+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
1955+ => TypeExpression schemas (nullity ('PGvarchar n))
1956+varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
1957+characterVarying = UnsafeTypeExpression $
1958+ "character varying(" <> renderNat @n <> ")"
1959+-- | binary data ("byte array")
1960+bytea :: TypeExpression schemas (nullity 'PGbytea)
1961+bytea = UnsafeTypeExpression "bytea"
1962+-- | date and time (no time zone)
1963+timestamp :: TypeExpression schemas (nullity 'PGtimestamp)
1964+timestamp = UnsafeTypeExpression "timestamp"
1965+-- | date and time, including time zone
1966+timestampWithTimeZone :: TypeExpression schemas (nullity 'PGtimestamptz)
1967+timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1968+-- | calendar date (year, month, day)
1969+date :: TypeExpression schemas (nullity 'PGdate)
1970+date = UnsafeTypeExpression "date"
1971+-- | time of day (no time zone)
1972+time :: TypeExpression schemas (nullity 'PGtime)
1973+time = UnsafeTypeExpression "time"
1974+-- | time of day, including time zone
1975+timeWithTimeZone :: TypeExpression schemas (nullity 'PGtimetz)
1976+timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1978+interval :: TypeExpression schemas (nullity 'PGinterval)
1979+interval = UnsafeTypeExpression "interval"
1980+-- | universally unique identifier
1981+uuid :: TypeExpression schemas (nullity 'PGuuid)
1982+uuid = UnsafeTypeExpression "uuid"
1983+-- | IPv4 or IPv6 host address
1984+inet :: TypeExpression schemas (nullity 'PGinet)
1985+inet = UnsafeTypeExpression "inet"
1986+-- | textual JSON data
1987+json :: TypeExpression schemas (nullity 'PGjson)
1988+json = UnsafeTypeExpression "json"
1989+-- | binary JSON data, decomposed
1990+jsonb :: TypeExpression schemas (nullity 'PGjsonb)
1991+jsonb = UnsafeTypeExpression "jsonb"
1992+-- | variable length array
1994+ :: TypeExpression schemas pg
1995+ -> TypeExpression schemas (nullity ('PGvararray pg))
1996+vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
1997+-- | fixed length array
1999+-- >>> renderSQL (fixarray @'[2] json)
2002+ :: forall dims schemas nullity pg. SOP.All KnownNat dims
2003+ => TypeExpression schemas pg
2004+ -> TypeExpression schemas (nullity ('PGfixarray dims pg))
2005+fixarray ty = UnsafeTypeExpression $
2006+ renderSQL ty <> renderDims @dims
2008+ renderDims :: forall ns. SOP.All KnownNat ns => ByteString
2012+ . ByteString.intercalate "]["
2014+ $ hcmap (SOP.Proxy @KnownNat)
2015+ (K . fromString . show . natVal)
2016+ (hpure SOP.Proxy :: NP SOP.Proxy ns)
2018+-- | `pgtype` is a demoted version of a `PGType`
2019+class PGTyped schemas (ty :: NullityType) where
2020+ pgtype :: TypeExpression schemas ty
2021+instance PGTyped schemas (nullity 'PGbool) where pgtype = bool
2022+instance PGTyped schemas (nullity 'PGint2) where pgtype = int2
2023+instance PGTyped schemas (nullity 'PGint4) where pgtype = int4
2024+instance PGTyped schemas (nullity 'PGint8) where pgtype = int8
2025+instance PGTyped schemas (nullity 'PGnumeric) where pgtype = numeric
2026+instance PGTyped schemas (nullity 'PGfloat4) where pgtype = float4
2027+instance PGTyped schemas (nullity 'PGfloat8) where pgtype = float8
2028+instance PGTyped schemas (nullity 'PGtext) where pgtype = text
2029+instance (KnownNat n, 1 <= n)
2030+ => PGTyped schemas (nullity ('PGchar n)) where pgtype = char @n
2031+instance (KnownNat n, 1 <= n)
2032+ => PGTyped schemas (nullity ('PGvarchar n)) where pgtype = varchar @n
2033+instance PGTyped schemas (nullity 'PGbytea) where pgtype = bytea
2034+instance PGTyped schemas (nullity 'PGtimestamp) where pgtype = timestamp
2035+instance PGTyped schemas (nullity 'PGtimestamptz) where pgtype = timestampWithTimeZone
2036+instance PGTyped schemas (nullity 'PGdate) where pgtype = date
2037+instance PGTyped schemas (nullity 'PGtime) where pgtype = time
2038+instance PGTyped schemas (nullity 'PGtimetz) where pgtype = timeWithTimeZone
2039+instance PGTyped schemas (nullity 'PGinterval) where pgtype = interval
2040+instance PGTyped schemas (nullity 'PGuuid) where pgtype = uuid
2041+instance PGTyped schemas (nullity 'PGjson) where pgtype = json
2042+instance PGTyped schemas (nullity 'PGjsonb) where pgtype = jsonb
2043+instance PGTyped schemas ty
2044+ => PGTyped schemas (nullity ('PGvararray ty)) where
2045+ pgtype = vararray (pgtype @schemas @ty)
2046+instance (SOP.All KnownNat dims, PGTyped schemas ty)
2047+ => PGTyped schemas (nullity ('PGfixarray dims ty)) where
2048+ pgtype = fixarray @dims (pgtype @schemas @ty)
2050+{-----------------------------------------
2052+-----------------------------------------}
2054+-- | `SortExpression`s are used by `orderBy` to optionally sort the results
2055+-- of a `Squeal.PostgreSQL.Query.Query`. `Asc` or `Desc`
2056+-- set the sort direction of a `NotNull` result
2057+-- column to ascending or descending. Ascending order puts smaller values
2058+-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
2059+-- descending order is determined with the `.>` operator. `AscNullsFirst`,
2060+-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
2061+-- determine whether nulls appear before or after non-null values in the sort
2062+-- ordering of a `Null` result column.
2063+data SortExpression outer grp commons schemas params from where
2065+ :: Expression outer grp commons schemas params from ('NotNull ty)
2066+ -> SortExpression outer grp commons schemas params from
2068+ :: Expression outer grp commons schemas params from ('NotNull ty)
2069+ -> SortExpression outer grp commons schemas params from
2071+ :: Expression outer grp commons schemas params from ('Null ty)
2072+ -> SortExpression outer grp commons schemas params from
2074+ :: Expression outer grp commons schemas params from ('Null ty)
2075+ -> SortExpression outer grp commons schemas params from
2077+ :: Expression outer grp commons schemas params from ('Null ty)
2078+ -> SortExpression outer grp commons schemas params from
2080+ :: Expression outer grp commons schemas params from ('Null ty)
2081+ -> SortExpression outer grp commons schemas params from
2082+deriving instance Show (SortExpression outer grp commons schemas params from)
2085+The `orderBy` clause causes the result rows of a `Squeal.PostgreSQL.Query.TableExpression`
2086+to be sorted according to the specified `SortExpression`(s).
2087+If two rows are equal according to the leftmost expression,
2088+they are compared according to the next expression and so on.
2089+If they are equal according to all specified expressions,
2090+they are returned in an implementation-dependent order.
2092+You can also control the order in which rows are processed by window functions
2093+using `orderBy` within `Squeal.PostgreSQL.Query.Over`.
2095+class OrderBy expr where
2097+ :: [SortExpression outer grp commons schemas params from]
2098+ -> expr outer grp commons schemas params from
2099+ -> expr outer grp commons schemas params from
2101+-- | Render a `SortExpression`.
2102+instance RenderSQL (SortExpression outer grp commons schemas params from) where
2104+ Asc expression -> renderSQL expression <+> "ASC"
2105+ Desc expression -> renderSQL expression <+> "DESC"
2106+ AscNullsFirst expression -> renderSQL expression
2107+ <+> "ASC NULLS FIRST"
2108+ DescNullsFirst expression -> renderSQL expression
2109+ <+> "DESC NULLS FIRST"
2110+ AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
2111+ DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
2113+-- | A `WindowDefinition` is a set of table rows that are somehow related
2114+-- to the current row
2115+data WindowDefinition outer grp commons schemas params from where
2118+ => NP (Expression outer grp commons schemas params from) bys
2119+ -> [SortExpression outer grp commons schemas params from]
2120+ -> WindowDefinition outer grp commons schemas params from
2122+instance OrderBy WindowDefinition where
2123+ orderBy sortsR (WindowDefinition parts sortsL)
2124+ = WindowDefinition parts (sortsL ++ sortsR)
2126+instance RenderSQL (WindowDefinition outer commons schemas from grp params) where
2127+ renderSQL (WindowDefinition part ord) =
2128+ renderPartitionByClause part <> renderOrderByClause ord
2130+ renderPartitionByClause = \case
2132+ parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
2133+ renderOrderByClause = \case
2135+ srts -> " ORDER" <+> "BY"
2136+ <+> commaSeparated (renderSQL <$> srts)
2139+The `partitionBy` clause within `Squeal.PostgreSQL.Query.Over` divides the rows into groups,
2140+or partitions, that share the same values of the `partitionBy` `Expression`(s).
2141+For each row, the window function is computed across the rows that fall into
2142+the same partition as the current row.
2146+ => NP (Expression outer grp commons schemas params from) bys
2147+ -> WindowDefinition outer grp commons schemas params from
2148+partitionBy bys = WindowDefinition bys []
2151+A window function performs a calculation across a set of table rows
2152+that are somehow related to the current row. This is comparable to the type
2153+of calculation that can be done with an aggregate function.
2154+However, window functions do not cause rows to become grouped into a single
2155+output row like non-window aggregate calls would.
2156+Instead, the rows retain their separate identities.
2157+Behind the scenes, the window function is able to access more than
2158+just the current row of the query result.
2160+newtype WindowFunction
2161+ (outer :: FromType)
2163+ (commons :: FromType)
2164+ (schemas :: SchemasType)
2165+ (params :: [NullityType])
2167+ (ty :: NullityType)
2168+ = UnsafeWindowFunction { renderWindowFunction :: ByteString }
2169+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
2171+instance RenderSQL (WindowFunction outer grp commons schemas params from ty) where
2172+ renderSQL = renderWindowFunction
2174+unsafeWindowFunction1
2176+ -> Expression outer grp commons schemas params from ty0
2177+ -> WindowFunction outer grp commons schemas params from ty1
2178+unsafeWindowFunction1 fun x
2179+ = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x)
2181+unsafeWindowFunction2
2183+ -> (Expression outer grp commons schemas params from :*: Expression outer grp commons schemas params from) ty0
2184+ -> WindowFunction outer grp commons schemas params from ty1
2185+unsafeWindowFunction2 fun (x :*: x')
2186+ = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x <> ", " <> renderSQL x')
2188+{- | rank of the current row with gaps; same as `rowNumber` of its first peer
2192+rank :: WindowFunction outer grp commons schemas params from ('NotNull 'PGint8)
2193+rank = UnsafeWindowFunction "rank()"
2195+{- | number of the current row within its partition, counting from 1
2196+>>> printSQL rowNumber
2199+rowNumber :: WindowFunction outer grp commons schemas params from ('NotNull 'PGint8)
2200+rowNumber = UnsafeWindowFunction "row_number()"
2202+{- | rank of the current row without gaps; this function counts peer groups
2203+>>> printSQL denseRank
2206+denseRank :: WindowFunction outer grp commons schemas params from ('NotNull 'PGint8)
2207+denseRank = UnsafeWindowFunction "dense_rank()"
2209+{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
2210+>>> printSQL percentRank
2213+percentRank :: WindowFunction outer grp commons schemas params from ('NotNull 'PGfloat8)
2214+percentRank = UnsafeWindowFunction "percent_rank()"
2216+{- | cumulative distribution: (number of partition rows
2217+preceding or peer with current row) / total partition rows
2218+>>> printSQL cumeDist
2221+cumeDist :: WindowFunction outer grp commons schemas params from ('NotNull 'PGfloat8)
2222+cumeDist = UnsafeWindowFunction "cume_dist()"
2224+{- | integer ranging from 1 to the argument value,
2225+dividing the partition as equally as possible
2228+ :: Expression outer grp commons schemas params from ('NotNull 'PGint4)
2230+ -> WindowFunction outer grp commons schemas params from ('NotNull 'PGint4)
2231+ntile = unsafeWindowFunction1 "ntile"
2233+{- | returns value evaluated at the row that is offset rows before the current
2234+row within the partition; if there is no such row, instead return default
2235+(which must be of the same type as value). Both offset and default are
2236+evaluated with respect to the current row.
2239+ :: Expression outer grp commons schemas params from ty
2241+ -> Expression outer grp commons schemas params from ('NotNull 'PGint4)
2243+ -> Expression outer grp commons schemas params from ty
2245+ -> WindowFunction outer grp commons schemas params from ty
2246+lag value offset def = UnsafeWindowFunction $ "lag"
2248+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
2250+{- | returns value evaluated at the row that is offset rows after the current
2251+row within the partition; if there is no such row, instead return default
2252+(which must be of the same type as value). Both offset and default are
2253+evaluated with respect to the current row.
2256+ :: Expression outer grp commons schemas params from ty
2258+ -> Expression outer grp commons schemas params from ('NotNull 'PGint4)
2260+ -> Expression outer grp commons schemas params from ty
2262+ -> WindowFunction outer grp commons schemas params from ty
2263+lead value offset def = UnsafeWindowFunction $ "lag"
2265+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
2267+{- | returns value evaluated at the row that is the
2268+first row of the window frame
2271+ :: Expression outer grp commons schemas params from ty
2273+ -> WindowFunction outer grp commons schemas params from ty
2274+firstValue = unsafeWindowFunction1 "first_value"
2276+{- | returns value evaluated at the row that is the
2277+last row of the window frame
2280+ :: Expression outer grp commons schemas params from ty
2282+ -> WindowFunction outer grp commons schemas params from ty
2283+lastValue = unsafeWindowFunction1 "last_value"
2285+{- | returns value evaluated at the row that is the nth
2286+row of the window frame (counting from 1); null if no such row
2289+ :: Expression outer grp commons schemas params from (nullity ty)
2291+ -> Expression outer grp commons schemas params from ('NotNull 'PGint4)
2293+ -> WindowFunction outer grp commons schemas params from ('Null ty)
2294+nthValue value nth = UnsafeWindowFunction $ "nth_value"
2295+ <> parenthesized (commaSeparated [renderSQL value, renderSQL nth])
2298+Create date from year, month and day fields
2300+>>> printSQL (makeDate 1984 7 3)
2301+make_date(1984, 7, 3)
2304+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2306+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2308+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2310+ -> Expression outer grp commons schemas params from (nullity 'PGdate)
2311+makeDate y m d = UnsafeExpression $ "make_date" <>
2312+ parenthesized (renderCommaSeparated renderSQL (y :* m :* d :* Nil))
2315+Create time from hour, minute and seconds fields
2317+>>> printSQL (makeTime 8 15 23.5)
2318+make_time(8, 15, 23.5)
2321+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2323+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2325+ -> Expression outer grp commons schemas params from (nullity 'PGfloat8)
2327+ -> Expression outer grp commons schemas params from (nullity 'PGtime)
2328+makeTime h m s = UnsafeExpression $ "make_time" <>
2329+ parenthesized (renderCommaSeparated renderSQL (h :* m :* s :* Nil))
2332+Create timestamp from year, month, day, hour, minute and seconds fields
2334+>>> printSQL (makeTimestamp 2013 7 15 8 15 23.5)
2335+make_timestamp(2013, 7, 15, 8, 15, 23.5)
2338+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2340+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2342+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2344+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2346+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2348+ -> Expression outer grp commons schemas params from (nullity 'PGfloat8)
2350+ -> Expression outer grp commons schemas params from (nullity 'PGtimestamp)
2351+makeTimestamp y mon d h m s =
2352+ UnsafeExpression $ "make_timestamp" <> parenthesized
2353+ (renderCommaSeparated renderSQL (y :* mon :* d :* h :* m :* s :* Nil))
2356+Create timestamp with time zone from
2357+year, month, day, hour, minute and seconds fields;
2358+the current time zone is used
2360+>>> printSQL (makeTimestamptz 2013 7 15 8 15 23.5)
2361+make_timestamptz(2013, 7, 15, 8, 15, 23.5)
2364+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2366+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2368+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2370+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2372+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2374+ -> Expression outer grp commons schemas params from (nullity 'PGfloat8)
2376+ -> Expression outer grp commons schemas params from (nullity 'PGtimestamptz)
2377+makeTimestamptz y mon d h m s =
2378+ UnsafeExpression $ "make_timestamptz" <> parenthesized
2379+ (renderCommaSeparated renderSQL (y :* mon :* d :* h :* m :* s :* Nil))
2382+Affine space operations on time types.
2384+class TimeOp time diff | time -> diff where
2386+ >>> printSQL (makeDate 1984 7 3 !+ 365)
2387+ (make_date(1984, 7, 3) + 365)
2390+ :: Expression outer grp commons schemas params from (nullity time)
2391+ -> Expression outer grp commons schemas params from (nullity diff)
2392+ -> Expression outer grp commons schemas params from (nullity time)
2393+ (!+) = unsafeBinaryOp "+"
2395+ >>> printSQL (365 +! makeDate 1984 7 3)
2396+ (365 + make_date(1984, 7, 3))
2399+ :: Expression outer grp commons schemas params from (nullity diff)
2400+ -> Expression outer grp commons schemas params from (nullity time)
2401+ -> Expression outer grp commons schemas params from (nullity time)
2402+ (+!) = unsafeBinaryOp "+"
2404+ >>> printSQL (makeDate 1984 7 3 !-! currentDate)
2405+ (make_date(1984, 7, 3) - CURRENT_DATE)
2408+ :: Expression outer grp commons schemas params from (nullity time)
2409+ -> Expression outer grp commons schemas params from (nullity time)
2410+ -> Expression outer grp commons schemas params from (nullity diff)
2411+ (!-!) = unsafeBinaryOp "-"
2412+instance TimeOp 'PGtimestamp 'PGinterval
2413+instance TimeOp 'PGtimestamptz 'PGinterval
2414+instance TimeOp 'PGtime 'PGinterval
2415+instance TimeOp 'PGtimetz 'PGinterval
2416+instance TimeOp 'PGinterval 'PGinterval
2417+instance TimeOp 'PGdate 'PGint4