@@ -1,13 +1,14 @@
11{-|
2−Module: Squeal.PostgreSQL.Expression
2+Module: Squeal.PostgreSQL.Query
33Description: Squeal expressions
4−Copyright: (c) Eitan Chatav, 2019
4+Copyright: (c) Eitan Chatav, 2017
55Maintainer: eitan@morphism.tech
66Stability: experimental
77
88Squeal expressions are the atoms used to build statements.
99-}
1010
11+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
1112{-# LANGUAGE
1213 AllowAmbiguousTypes
1314 , ConstraintKinds
@@ -33,350 +34,565 @@ Squeal expressions are the atoms used to build statements.
3334module Squeal.PostgreSQL.Expression
3435 ( -- * Expression
3536 Expression (..)
36− , Expr
37− , type (-->)
38− , FunctionDB
39− , unsafeFunction
40− , function
41− , unsafeLeftOp
42− , leftOp
43− , unsafeRightOp
44− , rightOp
45− , Operator
46− , OperatorDB
37+ , HasParameter (parameter)
38+ , param
39+ -- ** Null
40+ , null_
41+ , notNull
42+ , coalesce
43+ , fromNull
44+ , isNull
45+ , isNotNull
46+ , matchNull
47+ , nullIf
48+ -- ** Collections
49+ , array
50+ , index
51+ , row
52+ , field
53+ -- ** Functions
4754 , unsafeBinaryOp
48− , binaryOp
49− , FunctionVar
50− , unsafeFunctionVar
51− , type (--->)
52− , FunctionNDB
53− , unsafeFunctionN
54− , functionN
55− , PGSubset (..)
56− , PGIntersect (..)
55+ , unsafeUnaryOp
56+ , unsafeFunction
57+ , unsafeVariadicFunction
58+ , atan2_
59+ , cast
60+ , quot_
61+ , rem_
62+ , trunc
63+ , round_
64+ , ceiling_
65+ , greatest
66+ , least
67+ -- ** Conditions
68+ , true
69+ , false
70+ , not_
71+ , (.&&)
72+ , (.||)
73+ , Condition
74+ , caseWhenThenElse
75+ , ifThenElse
76+ , (.==)
77+ , (./=)
78+ , (.>=)
79+ , (.<)
80+ , (.<=)
81+ , (.>)
82+ -- ** Time
83+ , currentDate
84+ , currentTime
85+ , currentTimestamp
86+ , localTime
87+ , localTimestamp
88+ -- ** Text
89+ , lower
90+ , upper
91+ , charLength
92+ , like
93+ , ilike
94+ -- ** Json
95+ -- *** Json and Jsonb operators
96+ , (.->)
97+ , (.->>)
98+ , (.#>)
99+ , (.#>>)
100+ -- *** Jsonb operators
101+ , (.@>)
102+ , (.<@)
103+ , (.?)
104+ , (.?|)
105+ , (.?&)
106+ , (.-.)
107+ , (#-.)
108+ -- *** Functions
109+ , jsonLit
110+ , jsonbLit
111+ , toJson
112+ , toJsonb
113+ , arrayToJson
114+ , rowToJson
115+ , jsonBuildArray
116+ , jsonbBuildArray
117+ , jsonBuildObject
118+ , jsonbBuildObject
119+ , jsonObject
120+ , jsonbObject
121+ , jsonZipObject
122+ , jsonbZipObject
123+ , jsonArrayLength
124+ , jsonbArrayLength
125+ , jsonExtractPath
126+ , jsonbExtractPath
127+ , jsonExtractPathAsText
128+ , jsonbExtractPathAsText
129+ , jsonTypeof
130+ , jsonbTypeof
131+ , jsonStripNulls
132+ , jsonbStripNulls
133+ , jsonbSet
134+ , jsonbInsert
135+ , jsonbPretty
136+ -- ** Aggregation
137+ , unsafeAggregate, unsafeAggregateDistinct
138+ , sum_, sumDistinct
139+ , PGAvg (avg, avgDistinct)
140+ , bitAnd, bitOr, boolAnd, boolOr
141+ , bitAndDistinct, bitOrDistinct, boolAndDistinct, boolOrDistinct
142+ , countStar
143+ , count, countDistinct
144+ , every, everyDistinct
145+ , max_, maxDistinct, min_, minDistinct
146+ -- * Window Functions
147+ , WindowDefinition (..)
148+ , partitionBy
149+ , WindowFunction (..)
150+ , rank
151+ , rowNumber
152+ , denseRank
153+ , percentRank
154+ , cumeDist
155+ , ntile
156+ , lag
157+ , lead
158+ , firstValue
159+ , lastValue
160+ , nthValue
161+ -- * Sorting
162+ , SortExpression (..)
163+ , OrderBy (..)
164+ -- * Types
165+ , TypeExpression (..)
166+ , PGTyped (..)
167+ , typedef
168+ , typetable
169+ , typeview
170+ , bool
171+ , int2
172+ , smallint
173+ , int4
174+ , int
175+ , integer
176+ , int8
177+ , bigint
178+ , numeric
179+ , float4
180+ , real
181+ , float8
182+ , doublePrecision
183+ , text
184+ , char
185+ , character
186+ , varchar
187+ , characterVarying
188+ , bytea
189+ , timestamp
190+ , timestampWithTimeZone
191+ , date
192+ , time
193+ , timeWithTimeZone
194+ , interval
195+ , uuid
196+ , inet
197+ , json
198+ , jsonb
199+ , vararray
200+ , fixarray
57201 -- * Re-export
58202 , (&)
59− , K (..)
60− , unK
203+ , NP ((:*), Nil)
61204 ) where
62205
63206import Control.Category
64207import Control.DeepSeq
65208import Data.ByteString (ByteString)
209+import Data.ByteString.Lazy (toStrict)
66210import Data.Function ((&))
67211import Data.Semigroup hiding (All)
212+import qualified Data.Aeson as JSON
213+import Data.Ratio
68214import Data.String
69−import Generics.SOP hiding (All, from)
215+import Data.Word
216+import Generics.SOP hiding (from)
70217import GHC.OverloadedLabels
71218import GHC.TypeLits
72−import Numeric
73219import Prelude hiding (id, (.))
74220
221+import qualified Data.ByteString as ByteString
75222import qualified GHC.Generics as GHC
76223
77−import Squeal.PostgreSQL.Alias
78−import Squeal.PostgreSQL.List
79224import Squeal.PostgreSQL.Render
80225import Squeal.PostgreSQL.Schema
81226
82−-- $setup
83−-- >>> import Squeal.PostgreSQL
84−
85227{-----------------------------------------
86228column expressions
87229-----------------------------------------}
88230
89231{- | `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,
232+such as in the target list of the `Squeal.PostgreSQL.Query.select` command,
92233as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
93234`Squeal.PostgreSQL.Manipulation.update`,
94−or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
235+or in search `Condition`s in a number of commands.
95236
96237The expression syntax allows the calculation of
97238values from primitive expression using arithmetic, logical,
98239and other operations.
99−
100−The type parameters of `Expression` are
101−
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`.
113240-}
114241newtype Expression
115− (outer :: FromType)
116− (commons :: FromType)
117242 (grp :: Grouping)
243+ (commons :: FromType)
118244 (schemas :: SchemasType)
119245 (params :: [NullityType])
120246 (from :: FromType)
121247 (ty :: NullityType)
122248 = UnsafeExpression { renderExpression :: ByteString }
123249 deriving (GHC.Generic,Show,Eq,Ord,NFData)
124−instance RenderSQL (Expression outer commons grp schemas params from ty) where
250+
251+instance RenderSQL (Expression grp commons schemas params from ty) where
125252 renderSQL = renderExpression
126253
127−-- | An `Expr` is a closed `Expression`.
128−-- It is a F@RankNType@ but don't be scared.
129−-- Think of it as an expression which sees no
130−-- namespaces, so you can't use parameters
131−-- or alias references. It can be used as
132−-- a simple piece of more complex `Expression`s.
133−type Expr x
134− = forall outer commons grp schemas params from
135− . Expression outer commons grp schemas params from x
136− -- ^ cannot reference aliases
137−
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
142− -- ^ left input
143− -> Expression outer commons grp schemas params from x2
144− -- ^ right input
145− -> Expression outer commons grp schemas params from y
146− -- ^ output
147−
148−type OperatorDB schemas x1 x2 y
149− = forall outer commons grp params from
150− . Expression outer commons grp schemas params from x1
151− -- ^ left input
152− -> Expression outer commons grp schemas params from x2
153− -- ^ right input
154− -> Expression outer commons grp schemas params from y
155− -- ^ output
156−
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`.
162−type (-->) x y
163− = forall outer commons grp schemas params from
164− . Expression outer commons grp schemas params from x
165− -- ^ input
166− -> Expression outer commons grp schemas params from y
167− -- ^ output
168−
169−type FunctionDB schemas x y
170− = forall outer commons grp params from
171− . Expression outer commons grp schemas params from x
172− -- ^ input
173− -> Expression outer commons grp schemas params from y
174− -- ^ output
175−
176−{- | A @RankNType@ for functions with a fixed-length list of heterogeneous arguments.
177−Use the `*:` operator to end your argument lists, like so.
178−
179−>>> printSQL (unsafeFunctionN "fun" (true :* false :* localTime *: true))
180−fun(TRUE, FALSE, LOCALTIME, TRUE)
181−-}
182−type (--->) xs y
183− = forall outer commons grp schemas params from
184− . NP (Expression outer commons grp schemas params from) xs
185− -- ^ inputs
186− -> Expression outer commons grp schemas params from y
187− -- ^ output
188−
189−type FunctionNDB schemas xs y
190− = forall outer commons grp params from
191− . NP (Expression outer commons grp schemas params from) xs
192− -- ^ inputs
193− -> Expression outer commons grp schemas params from y
194− -- ^ output
195−
196−{- | A @RankNType@ for functions with a variable-length list of
197−homogeneous arguments and at least 1 more argument.
254+{- | A `HasParameter` constraint is used to indicate a value that is
255+supplied externally to a SQL statement.
256+`Squeal.PostgreSQL.PQ.manipulateParams`,
257+`Squeal.PostgreSQL.PQ.queryParams` and
258+`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
259+separately from the SQL command string, in which case `param`s are used to
260+refer to the out-of-line data values.
198261-}
199−type FunctionVar x0 x1 y
200− = forall outer commons grp schemas params from
201− . [Expression outer commons grp schemas params from x0]
202− -- ^ inputs
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
206− -- ^ output
207−
208−{- | >>> printSQL (unsafeFunctionVar "greatest" [true, null_] false)
209−greatest(TRUE, NULL, FALSE)
210−-}
211−unsafeFunctionVar :: ByteString -> FunctionVar x0 x1 y
212−unsafeFunctionVar fun xs x = UnsafeExpression $ fun <> parenthesized
213− (commaSeparated (renderSQL <$> xs) <> ", " <> renderSQL x)
262+class KnownNat n => HasParameter
263+ (n :: Nat)
264+ (params :: [NullityType])
265+ (ty :: NullityType)
266+ | n params -> ty where
267+ -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
268+ --
269+ -- >>> let expr = parameter @1 int4 :: Expression '[] schemas '[ 'Null 'PGint4] grp from ('Null 'PGint4)
270+ -- >>> printSQL expr
271+ -- ($1 :: int4)
272+ parameter
273+ :: TypeExpression schemas ty
274+ -> Expression grp commons schemas params from ty
275+ parameter ty = UnsafeExpression $ parenthesized $
276+ "$" <> renderNat @n <+> "::"
277+ <+> renderSQL ty
278+instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
279+instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
280+ => HasParameter n (ty' : params) ty
281+
282+-- | `param` takes a `Nat` using type application and for basic types,
283+-- infers a `TypeExpression`.
284+--
285+-- >>> let expr = param @1 :: Expression commons schemas '[ 'Null 'PGint4] grp from ('Null 'PGint4)
286+-- >>> printSQL expr
287+-- ($1 :: int4)
288+param
289+ :: forall n commons schemas params from grp ty
290+ . (PGTyped schemas ty, HasParameter n params ty)
291+ => Expression grp commons schemas params from ty -- ^ param
292+param = parameter @n (pgtype @schemas)
214293
215−instance (HasUnique tab (Join outer from) row, Has col row ty)
216− => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
294+instance (HasUnique tab from row, Has col row ty)
295+ => IsLabel col (Expression 'Ungrouped commons schemas params from ty) where
217296 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
218−instance (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
220− fromLabel = fromLabel @col :* Nil
221−instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
297+instance (HasUnique tab from row, Has col row ty, column ~ (col ::: ty))
222298 => IsLabel col
223− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
299+ (Aliased (Expression 'Ungrouped commons schemas params from) column) where
224300 fromLabel = fromLabel @col `As` Alias
225−instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
301+instance (HasUnique tab from row, Has col row ty, columns ~ '[col ::: ty])
226302 => IsLabel col
227− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
303+ (NP (Aliased (Expression 'Ungrouped commons schemas params from)) columns) where
228304 fromLabel = fromLabel @col :* Nil
229305
230−instance (Has tab (Join outer from) row, Has col row ty)
231− => IsQualified tab col (Expression outer commons 'Ungrouped schemas params from ty) where
306+instance (Has tab from row, Has col row ty)
307+ => IsQualified tab col (Expression 'Ungrouped commons schemas params from ty) where
232308 tab ! col = UnsafeExpression $
233309 renderSQL tab <> "." <> renderSQL col
234−instance (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
236− tab ! col = tab ! col :* Nil
237−instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
310+instance (Has tab from row, Has col row ty, column ~ (col ::: ty))
238311 => IsQualified tab col
239− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
312+ (Aliased (Expression 'Ungrouped commons schemas params from) column) where
240313 tab ! col = tab ! col `As` col
241−instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
314+instance (Has tab from row, Has col row ty, columns ~ '[col ::: ty])
242315 => IsQualified tab col
243− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
316+ (NP (Aliased (Expression 'Ungrouped commons schemas params from)) columns) where
244317 tab ! col = tab ! col :* Nil
245318
246319instance
247− ( HasUnique tab (Join outer from) row
320+ ( HasUnique tab from row
248321 , Has col row ty
249322 , GroupedBy tab col bys
250323 ) => IsLabel col
251− (Expression outer commons ('Grouped bys) schemas params from ty) where
324+ (Expression ('Grouped bys) commons schemas params from ty) where
252325 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
253326instance
254− ( HasUnique tab (Join outer from) row
255− , Has col row ty
256− , GroupedBy tab col bys
257− , tys ~ '[ty]
258− ) => IsLabel col
259− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
260− fromLabel = fromLabel @col :* Nil
261−instance
262− ( HasUnique tab (Join outer from) row
327+ ( HasUnique tab from row
263328 , Has col row ty
264329 , GroupedBy tab col bys
265330 , column ~ (col ::: ty)
266331 ) => IsLabel col
267− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
332+ (Aliased (Expression ('Grouped bys) commons schemas params from) column) where
268333 fromLabel = fromLabel @col `As` Alias
269334instance
270− ( HasUnique tab (Join outer from) row
335+ ( HasUnique tab from row
271336 , Has col row ty
272337 , GroupedBy tab col bys
273338 , columns ~ '[col ::: ty]
274339 ) => IsLabel col
275− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
340+ (NP (Aliased (Expression ('Grouped bys) commons schemas params from)) columns) where
276341 fromLabel = fromLabel @col :* Nil
277342
278343instance
279− ( Has tab (Join outer from) row
344+ ( Has tab from row
280345 , Has col row ty
281346 , GroupedBy tab col bys
282347 ) => IsQualified tab col
283− (Expression outer commons ('Grouped bys) schemas params from ty) where
348+ (Expression ('Grouped bys) commons schemas params from ty) where
284349 tab ! col = UnsafeExpression $
285350 renderSQL tab <> "." <> renderSQL col
286351instance
287− ( Has tab (Join outer from) row
288− , Has col row ty
289− , GroupedBy tab col bys
290− , tys ~ '[ty]
291− ) => IsQualified tab col
292− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
293− tab ! col = tab ! col :* Nil
294−instance
295− ( Has tab (Join outer from) row
352+ ( Has tab from row
296353 , Has col row ty
297354 , GroupedBy tab col bys
298355 , column ~ (col ::: ty)
299356 ) => IsQualified tab col
300− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
357+ (Aliased (Expression ('Grouped bys) commons schemas params from) column) where
301358 tab ! col = tab ! col `As` col
302359instance
303− ( Has tab (Join outer from) row
360+ ( Has tab from row
304361 , Has col row ty
305362 , GroupedBy tab col bys
306363 , columns ~ '[col ::: ty]
307364 ) => IsQualified tab col
308− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
365+ (NP (Aliased (Expression ('Grouped bys) commons schemas params from)) columns) where
309366 tab ! col = tab ! col :* Nil
310367
368+-- | analagous to `Nothing`
369+--
370+-- >>> printSQL null_
371+-- NULL
372+null_ :: Expression commons schemas rels grouping params ('Null ty)
373+null_ = UnsafeExpression "NULL"
374+
375+-- | analagous to `Just`
376+--
377+-- >>> printSQL $ notNull true
378+-- TRUE
379+notNull
380+ :: Expression commons schemas rels grouping params ('NotNull ty)
381+ -> Expression commons schemas rels grouping params ('Null ty)
382+notNull = UnsafeExpression . renderSQL
383+
384+-- | return the leftmost value which is not NULL
385+--
386+-- >>> printSQL $ coalesce [null_, true] false
387+-- COALESCE(NULL, TRUE, FALSE)
388+coalesce
389+ :: [Expression grp commons schemas params from ('Null ty)]
390+ -- ^ @NULL@s may be present
391+ -> Expression grp commons schemas params from ('NotNull ty)
392+ -- ^ @NULL@ is absent
393+ -> Expression grp commons schemas params from ('NotNull ty)
394+coalesce nullxs notNullx = UnsafeExpression $
395+ "COALESCE" <> parenthesized (commaSeparated
396+ ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
397+
398+-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
399+--
400+-- >>> printSQL $ fromNull true null_
401+-- COALESCE(NULL, TRUE)
402+fromNull
403+ :: Expression grp commons schemas params from ('NotNull ty)
404+ -- ^ what to convert @NULL@ to
405+ -> Expression grp commons schemas params from ('Null ty)
406+ -> Expression grp commons schemas params from ('NotNull ty)
407+fromNull notNullx nullx = coalesce [nullx] notNullx
408+
409+-- | >>> printSQL $ null_ & isNull
410+-- NULL IS NULL
411+isNull
412+ :: Expression grp commons schemas params from ('Null ty)
413+ -- ^ possibly @NULL@
414+ -> Condition grp commons schemas params from
415+isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
416+
417+-- | >>> printSQL $ null_ & isNotNull
418+-- NULL IS NOT NULL
419+isNotNull
420+ :: Expression grp commons schemas params from ('Null ty)
421+ -- ^ possibly @NULL@
422+ -> Condition grp commons schemas params from
423+isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
424+
425+-- | analagous to `maybe` using @IS NULL@
426+--
427+-- >>> printSQL $ matchNull true not_ null_
428+-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
429+matchNull
430+ :: Expression grp commons schemas params from (nullty)
431+ -- ^ what to convert @NULL@ to
432+ -> ( Expression grp commons schemas params from ('NotNull ty)
433+ -> Expression grp commons schemas params from (nullty) )
434+ -- ^ function to perform when @NULL@ is absent
435+ -> Expression grp commons schemas params from ('Null ty)
436+ -> Expression grp commons schemas params from (nullty)
437+matchNull y f x = ifThenElse (isNull x) y
438+ (f (UnsafeExpression (renderSQL x)))
439+
440+{-| right inverse to `fromNull`, if its arguments are equal then
441+`nullIf` gives @NULL@.
442+
443+>>> :set -XTypeApplications -XDataKinds
444+>>> let expr = nullIf false (param @1) :: Expression commons schemas '[ 'NotNull 'PGbool] grp from ('Null 'PGbool)
445+>>> printSQL expr
446+NULL IF (FALSE, ($1 :: bool))
447+-}
448+nullIf
449+ :: Expression grp commons schemas params from ('NotNull ty)
450+ -- ^ @NULL@ is absent
451+ -> Expression grp commons schemas params from ('NotNull ty)
452+ -- ^ @NULL@ is absent
453+ -> Expression grp commons schemas params from ('Null ty)
454+nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
455+ (renderSQL x <> ", " <> renderSQL y)
456+
457+-- | >>> printSQL $ array [null_, false, true]
458+-- ARRAY[NULL, FALSE, TRUE]
459+array
460+ :: [Expression grp commons schemas params from ty]
461+ -- ^ array elements
462+ -> Expression grp commons schemas params from (nullity ('PGvararray ty))
463+array xs = UnsafeExpression $
464+ "ARRAY[" <> commaSeparated (renderSQL <$> xs) <> "]"
465+
466+-- | >>> printSQL $ array [null_, false, true] & index 2
467+-- (ARRAY[NULL, FALSE, TRUE])[2]
468+index
469+ :: Word64 -- ^ index
470+ -> Expression grp commons schemas params from (nullity ('PGvararray ty)) -- ^ array
471+ -> Expression grp commons schemas params from (NullifyType ty)
472+index n expr = UnsafeExpression $
473+ parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
474+
311475instance (KnownSymbol label, label `In` labels) => IsPGlabel label
312− (Expression outer commons grp schemas params from (null ('PGenum labels))) where
476+ (Expression grp commons schemas params from (nullity ('PGenum labels))) where
313477 label = UnsafeExpression $ renderSQL (PGlabel @label)
314478
479+-- | A row constructor is an expression that builds a row value
480+-- (also called a composite value) using values for its member fields.
481+--
482+-- >>> :{
483+-- type Complex = 'PGcomposite
484+-- '[ "real" ::: 'NotNull 'PGfloat8
485+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
486+-- :}
487+--
488+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression grp commons schemas params from ('NotNull Complex)
489+-- >>> printSQL i
490+-- ROW(0, 1)
491+row
492+ :: SListI row
493+ => NP (Aliased (Expression grp commons schemas params from)) row
494+ -- ^ zero or more expressions for the row field values
495+ -> Expression grp commons schemas params from (nullity ('PGcomposite row))
496+row exprs = UnsafeExpression $ "ROW" <> parenthesized
497+ (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
498+
499+-- | >>> :{
500+-- type Complex = 'PGcomposite
501+-- '[ "real" ::: 'NotNull 'PGfloat8
502+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
503+-- type Schema = '["complex" ::: 'Typedef Complex]
504+-- :}
505+--
506+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression '[] (Public Schema) from grp params ('NotNull Complex)
507+-- >>> printSQL $ i & field #complex #imaginary
508+-- (ROW(0, 1)::"complex")."imaginary"
509+field
510+ :: ( Has sch schemas schema
511+ , Has tydef schema ('Typedef ('PGcomposite row))
512+ , Has field row ty)
513+ => QualifiedAlias sch tydef -- ^ row type
514+ -> Alias field -- ^ field name
515+ -> Expression grp commons schemas params from ('NotNull ('PGcomposite row))
516+ -> Expression grp commons schemas params from ty
517+field td fld expr = UnsafeExpression $
518+ parenthesized (renderSQL expr <> "::" <> renderSQL td)
519+ <> "." <> renderSQL fld
520+
521+instance Semigroup
522+ (Expression grp commons schemas params from (nullity ('PGvararray ty))) where
523+ (<>) = unsafeBinaryOp "||"
524+
525+instance Monoid
526+ (Expression grp commons schemas params from (nullity ('PGvararray ty))) where
527+ mempty = array []
528+ mappend = (<>)
529+
530+-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression commons schemas '[ 'NotNull 'PGtimestamptz] grp from ('NotNull 'PGtimestamptz)
531+-- >>> printSQL expr
532+-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
533+greatest
534+ :: Expression grp commons schemas params from (nullty)
535+ -- ^ needs at least 1 argument
536+ -> [Expression grp commons schemas params from (nullty)]
537+ -- ^ or more
538+ -> Expression grp commons schemas params from (nullty)
539+greatest x xs = UnsafeExpression $ "GREATEST("
540+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
541+
542+-- | >>> printSQL $ least currentTimestamp [null_]
543+-- LEAST(CURRENT_TIMESTAMP, NULL)
544+least
545+ :: Expression grp commons schemas params from (nullty)
546+ -- ^ needs at least 1 argument
547+ -> [Expression grp commons schemas params from (nullty)]
548+ -- ^ or more
549+ -> Expression grp commons schemas params from (nullty)
550+least x xs = UnsafeExpression $ "LEAST("
551+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
552+
315553-- | >>> printSQL $ unsafeBinaryOp "OR" true false
316554-- (TRUE OR FALSE)
317−unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
555+unsafeBinaryOp
556+ :: ByteString
557+ -- ^ operator
558+ -> Expression grp commons schemas params from (ty0)
559+ -> Expression grp commons schemas params from (ty1)
560+ -> Expression grp commons schemas params from (ty2)
318561unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
319562 renderSQL x <+> op <+> renderSQL y
320563
321−binaryOp
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
327−
328−-- | >>> printSQL $ unsafeLeftOp "NOT" true
564+-- | >>> printSQL $ unsafeUnaryOp "NOT" true
329565-- (NOT TRUE)
330−unsafeLeftOp :: ByteString -> x --> y
331−unsafeLeftOp op x = UnsafeExpression $ parenthesized $ op <+> renderSQL x
332−
333−leftOp
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
339−
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
344−
345−rightOp
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
566+unsafeUnaryOp
567+ :: ByteString
568+ -- ^ operator
569+ -> Expression grp commons schemas params from (ty0)
570+ -> Expression grp commons schemas params from (ty1)
571+unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
572+ op <+> renderSQL x
351573
352574-- | >>> printSQL $ unsafeFunction "f" true
353575-- f(TRUE)
354−unsafeFunction :: ByteString -> x --> y
576+unsafeFunction
577+ :: ByteString
578+ -- ^ function
579+ -> Expression grp commons schemas params from (xty)
580+ -> Expression grp commons schemas params from (yty)
355581unsafeFunction fun x = UnsafeExpression $
356582 fun <> parenthesized (renderSQL x)
357583
358−function
359− :: (Has sch schemas schema, Has fun schema ('Function ('[x] :=> 'Returns y)))
360− => QualifiedAlias sch fun
361− -> FunctionDB schemas x y
362−function = unsafeFunction . renderSQL
363−
364−-- | >>> printSQL $ unsafeFunctionN "f" (currentTime :* localTimestamp :* false *: literal 'a')
365−-- f(CURRENT_TIME, LOCALTIMESTAMP, FALSE, E'a')
366−unsafeFunctionN :: SListI xs => ByteString -> xs ---> y
367−unsafeFunctionN fun xs = UnsafeExpression $
368− fun <> parenthesized (renderCommaSeparated renderSQL xs)
369−
370−functionN
371− :: ( Has sch schemas schema
372− , Has fun schema ('Function (xs :=> 'Returns y))
373− , SListI xs )
374− => QualifiedAlias sch fun
375− -> FunctionNDB schemas xs y
376−functionN = unsafeFunctionN . renderSQL
584+-- | Helper for defining variadic functions.
585+unsafeVariadicFunction
586+ :: SListI elems
587+ => ByteString
588+ -- ^ function
589+ -> NP (Expression grp commons schemas params from) elems
590+ -> Expression grp commons schemas params from ret
591+unsafeVariadicFunction fun x = UnsafeExpression $
592+ fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderSQL) x)))
377593
378594instance ty `In` PGNum
379− => Num (Expression outer commons grp schemas params from (null ty)) where
595+ => Num (Expression grp commons schemas params from (nullity ty)) where
380596 (+) = unsafeBinaryOp "+"
381597 (-) = unsafeBinaryOp "-"
382598 (*) = unsafeBinaryOp "*"
@@ -388,17 +604,12 @@ instance ty `In` PGNum
388604 . show
389605
390606instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
391− (Expression outer commons grp schemas params from (null ty)) where
607+ (Expression grp commons schemas params from (nullity ty)) where
392608 (/) = unsafeBinaryOp "/"
393− fromRational
394− = UnsafeExpression
395− . fromString
396− . ($ "")
397− . showFFloat Nothing
398− . fromRat @Double
609+ fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
399610
400611instance (ty `In` PGNum, ty `In` PGFloating) => Floating
401− (Expression outer commons grp schemas params from (null ty)) where
612+ (Expression grp commons schemas params from (nullity ty)) where
402613 pi = UnsafeExpression "pi()"
403614 exp = unsafeFunction "exp"
404615 log = unsafeFunction "ln"
@@ -419,54 +630,1387 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
419630 acosh x = log (x + sqrt (x*x - 1))
420631 atanh x = log ((1 + x) / (1 - x)) / 2
421632
422−-- | Contained by operators
423−class PGSubset ty where
424− (@>) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
425− (@>) = unsafeBinaryOp "@>"
426− (<@) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
427− (<@) = unsafeBinaryOp "<@"
428−instance PGSubset 'PGjsonb
429−instance PGSubset 'PGtsquery
430−instance PGSubset ('PGvararray ty)
431−instance PGSubset ('PGrange ty)
432−
433−class PGIntersect ty where
434− (@&&) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
435− (@&&) = unsafeBinaryOp "&&"
436−instance PGIntersect ('PGvararray ty)
437−instance PGIntersect ('PGrange ty)
633+-- | >>> :{
634+-- let
635+-- expression :: Expression grp commons schemas params from (nullity 'PGfloat4)
636+-- expression = atan2_ pi 2
637+-- in printSQL expression
638+-- :}
639+-- atan2(pi(), 2)
640+atan2_
641+ :: float `In` PGFloating
642+ => Expression grp commons schemas params from (nullity float)
643+ -- ^ numerator
644+ -> Expression grp commons schemas params from (nullity float)
645+ -- ^ denominator
646+ -> Expression grp commons schemas params from (nullity float)
647+atan2_ y x = UnsafeExpression $
648+ "atan2(" <> renderSQL y <> ", " <> renderSQL x <> ")"
649+
650+-- When a `cast` is applied to an `Expression` of a known type, it
651+-- represents a run-time type conversion. The cast will succeed only if a
652+-- suitable type conversion operation has been defined.
653+--
654+-- | >>> printSQL $ true & cast int4
655+-- (TRUE :: int4)
656+cast
657+ :: TypeExpression schemas ty1
658+ -- ^ type to cast as
659+ -> Expression grp commons schemas params from ty0
660+ -- ^ value to convert
661+ -> Expression grp commons schemas params from ty1
662+cast ty x = UnsafeExpression $ parenthesized $
663+ renderSQL x <+> "::" <+> renderSQL ty
664+
665+-- | integer division, truncates the result
666+--
667+-- >>> :{
668+-- let
669+-- expression :: Expression grp commons schemas params from (nullity 'PGint2)
670+-- expression = 5 `quot_` 2
671+-- in printSQL expression
672+-- :}
673+-- (5 / 2)
674+quot_
675+ :: int `In` PGIntegral
676+ => Expression grp commons schemas params from (nullity int)
677+ -- ^ numerator
678+ -> Expression grp commons schemas params from (nullity int)
679+ -- ^ denominator
680+ -> Expression grp commons schemas params from (nullity int)
681+quot_ = unsafeBinaryOp "/"
682+
683+-- | remainder upon integer division
684+--
685+-- >>> :{
686+-- let
687+-- expression :: Expression grp commons schemas params from (nullity 'PGint2)
688+-- expression = 5 `rem_` 2
689+-- in printSQL expression
690+-- :}
691+-- (5 % 2)
692+rem_
693+ :: int `In` PGIntegral
694+ => Expression grp commons schemas params from (nullity int)
695+ -- ^ numerator
696+ -> Expression grp commons schemas params from (nullity int)
697+ -- ^ denominator
698+ -> Expression grp commons schemas params from (nullity int)
699+rem_ = unsafeBinaryOp "%"
700+
701+-- | >>> :{
702+-- let
703+-- expression :: Expression grp commons schemas params from (nullity 'PGfloat4)
704+-- expression = trunc pi
705+-- in printSQL expression
706+-- :}
707+-- trunc(pi())
708+trunc
709+ :: frac `In` PGFloating
710+ => Expression grp commons schemas params from (nullity frac)
711+ -- ^ fractional number
712+ -> Expression grp commons schemas params from (nullity frac)
713+trunc = unsafeFunction "trunc"
714+
715+-- | >>> :{
716+-- let
717+-- expression :: Expression grp commons schemas params from (nullity 'PGfloat4)
718+-- expression = round_ pi
719+-- in printSQL expression
720+-- :}
721+-- round(pi())
722+round_
723+ :: frac `In` PGFloating
724+ => Expression grp commons schemas params from (nullity frac)
725+ -- ^ fractional number
726+ -> Expression grp commons schemas params from (nullity frac)
727+round_ = unsafeFunction "round"
728+
729+-- | >>> :{
730+-- let
731+-- expression :: Expression grp commons schemas params from (nullity 'PGfloat4)
732+-- expression = ceiling_ pi
733+-- in printSQL expression
734+-- :}
735+-- ceiling(pi())
736+ceiling_
737+ :: frac `In` PGFloating
738+ => Expression grp commons schemas params from (nullity frac)
739+ -- ^ fractional number
740+ -> Expression grp commons schemas params from (nullity frac)
741+ceiling_ = unsafeFunction "ceiling"
742+
743+-- | A `Condition` is an `Expression`, which can evaluate
744+-- to `true`, `false` or `null_`. This is because SQL uses
745+-- a three valued logic.
746+type Condition grp commons schemas params from =
747+ Expression grp commons schemas params from ('Null 'PGbool)
748+
749+-- | >>> printSQL true
750+-- TRUE
751+true :: Expression grp commons schemas params from (nullity 'PGbool)
752+true = UnsafeExpression "TRUE"
753+
754+-- | >>> printSQL false
755+-- FALSE
756+false :: Expression grp commons schemas params from (nullity 'PGbool)
757+false = UnsafeExpression "FALSE"
758+
759+-- | >>> printSQL $ not_ true
760+-- (NOT TRUE)
761+not_
762+ :: Expression grp commons schemas params from (nullity 'PGbool)
763+ -> Expression grp commons schemas params from (nullity 'PGbool)
764+not_ = unsafeUnaryOp "NOT"
765+
766+-- | >>> printSQL $ true .&& false
767+-- (TRUE AND FALSE)
768+(.&&)
769+ :: Expression grp commons schemas params from (nullity 'PGbool)
770+ -> Expression grp commons schemas params from (nullity 'PGbool)
771+ -> Expression grp commons schemas params from (nullity 'PGbool)
772+infixr 3 .&&
773+(.&&) = unsafeBinaryOp "AND"
774+
775+-- | >>> printSQL $ true .|| false
776+-- (TRUE OR FALSE)
777+(.||)
778+ :: Expression grp commons schemas params from (nullity 'PGbool)
779+ -> Expression grp commons schemas params from (nullity 'PGbool)
780+ -> Expression grp commons schemas params from (nullity 'PGbool)
781+infixr 2 .||
782+(.||) = unsafeBinaryOp "OR"
783+
784+-- | >>> :{
785+-- let
786+-- expression :: Expression grp commons schemas params from (nullity 'PGint2)
787+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
788+-- in printSQL expression
789+-- :}
790+-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
791+caseWhenThenElse
792+ :: [ ( Condition grp commons schemas params from
793+ , Expression grp commons schemas params from ty
794+ ) ]
795+ -- ^ whens and thens
796+ -> Expression grp commons schemas params from ty
797+ -- ^ else
798+ -> Expression grp commons schemas params from ty
799+caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
800+ [ "CASE"
801+ , mconcat
802+ [ mconcat
803+ [ " WHEN ", renderSQL when_
804+ , " THEN ", renderSQL then_
805+ ]
806+ | (when_,then_) <- whenThens
807+ ]
808+ , " ELSE ", renderSQL else_
809+ , " END"
810+ ]
811+
812+-- | >>> :{
813+-- let
814+-- expression :: Expression grp commons schemas params from (nullity 'PGint2)
815+-- expression = ifThenElse true 1 0
816+-- in printSQL expression
817+-- :}
818+-- CASE WHEN TRUE THEN 1 ELSE 0 END
819+ifThenElse
820+ :: Condition grp commons schemas params from
821+ -> Expression grp commons schemas params from ty -- ^ then
822+ -> Expression grp commons schemas params from ty -- ^ else
823+ -> Expression grp commons schemas params from ty
824+ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
825+
826+-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
827+-- will produce @NULL@s if one of their arguments is @NULL@.
828+--
829+-- >>> printSQL $ true .== null_
830+-- (TRUE = NULL)
831+(.==)
832+ :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
833+ -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
834+ -> Condition grp commons schemas params from
835+(.==) = unsafeBinaryOp "="
836+infix 4 .==
837+
838+-- | >>> printSQL $ true ./= null_
839+-- (TRUE <> NULL)
840+(./=)
841+ :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
842+ -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
843+ -> Condition grp commons schemas params from
844+(./=) = unsafeBinaryOp "<>"
845+infix 4 ./=
846+
847+-- | >>> printSQL $ true .>= null_
848+-- (TRUE >= NULL)
849+(.>=)
850+ :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
851+ -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
852+ -> Condition grp commons schemas params from
853+(.>=) = unsafeBinaryOp ">="
854+infix 4 .>=
855+
856+-- | >>> printSQL $ true .< null_
857+-- (TRUE < NULL)
858+(.<)
859+ :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
860+ -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
861+ -> Condition grp commons schemas params from
862+(.<) = unsafeBinaryOp "<"
863+infix 4 .<
864+
865+-- | >>> printSQL $ true .<= null_
866+-- (TRUE <= NULL)
867+(.<=)
868+ :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
869+ -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
870+ -> Condition grp commons schemas params from
871+(.<=) = unsafeBinaryOp "<="
872+infix 4 .<=
873+
874+-- | >>> printSQL $ true .> null_
875+-- (TRUE > NULL)
876+(.>)
877+ :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
878+ -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
879+ -> Condition grp commons schemas params from
880+(.>) = unsafeBinaryOp ">"
881+infix 4 .>
882+
883+-- | >>> printSQL currentDate
884+-- CURRENT_DATE
885+currentDate
886+ :: Expression grp commons schemas params from (nullity 'PGdate)
887+currentDate = UnsafeExpression "CURRENT_DATE"
888+
889+-- | >>> printSQL currentTime
890+-- CURRENT_TIME
891+currentTime
892+ :: Expression grp commons schemas params from (nullity 'PGtimetz)
893+currentTime = UnsafeExpression "CURRENT_TIME"
894+
895+-- | >>> printSQL currentTimestamp
896+-- CURRENT_TIMESTAMP
897+currentTimestamp
898+ :: Expression grp commons schemas params from (nullity 'PGtimestamptz)
899+currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
900+
901+-- | >>> printSQL localTime
902+-- LOCALTIME
903+localTime
904+ :: Expression grp commons schemas params from (nullity 'PGtime)
905+localTime = UnsafeExpression "LOCALTIME"
906+
907+-- | >>> printSQL localTimestamp
908+-- LOCALTIMESTAMP
909+localTimestamp
910+ :: Expression grp commons schemas params from (nullity 'PGtimestamp)
911+localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
912+
913+{-----------------------------------------
914+text
915+-----------------------------------------}
438916
439917instance IsString
440− (Expression outer commons grp schemas params from (null 'PGtext)) where
918+ (Expression grp commons schemas params from (nullity 'PGtext)) where
441919 fromString str = UnsafeExpression $
442920 "E\'" <> fromString (escape =<< str) <> "\'"
443−instance IsString
444− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
445− fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
446− "E\'" <> fromString (escape =<< str) <> "\'"
447−instance IsString
448− (Expression outer commons grp schemas params from (null 'PGtsquery)) where
449− fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
450− "E\'" <> fromString (escape =<< str) <> "\'"
921+ where
922+ escape = \case
923+ '\NUL' -> "\\0"
924+ '\'' -> "''"
925+ '"' -> "\\\""
926+ '\b' -> "\\b"
927+ '\n' -> "\\n"
928+ '\r' -> "\\r"
929+ '\t' -> "\\t"
930+ '\\' -> "\\\\"
931+ c -> [c]
451932
452933instance Semigroup
453− (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
454− (<>) = unsafeBinaryOp "||"
455−instance Semigroup
456− (Expression outer commons grp schemas params from (null 'PGjsonb)) where
457− (<>) = unsafeBinaryOp "||"
458−instance Semigroup
459− (Expression outer commons grp schemas params from (null 'PGtext)) where
460− (<>) = unsafeBinaryOp "||"
461−instance Semigroup
462− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
934+ (Expression grp commons schemas params from (nullity 'PGtext)) where
463935 (<>) = unsafeBinaryOp "||"
464936
465937instance Monoid
466− (Expression outer commons grp schemas params from (null 'PGtext)) where
467− mempty = fromString ""
468− mappend = (<>)
469−instance Monoid
470− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
938+ (Expression grp commons schemas params from (nullity 'PGtext)) where
471939 mempty = fromString ""
472940 mappend = (<>)
941+
942+-- | >>> printSQL $ lower "ARRRGGG"
943+-- lower(E'ARRRGGG')
944+lower
945+ :: Expression grp commons schemas params from (nullity 'PGtext)
946+ -- ^ string to lower case
947+ -> Expression grp commons schemas params from (nullity 'PGtext)
948+lower = unsafeFunction "lower"
949+
950+-- | >>> printSQL $ upper "eeee"
951+-- upper(E'eeee')
952+upper
953+ :: Expression grp commons schemas params from (nullity 'PGtext)
954+ -- ^ string to upper case
955+ -> Expression grp commons schemas params from (nullity 'PGtext)
956+upper = unsafeFunction "upper"
957+
958+-- | >>> printSQL $ charLength "four"
959+-- char_length(E'four')
960+charLength
961+ :: Expression grp commons schemas params from (nullity 'PGtext)
962+ -- ^ string to measure
963+ -> Expression grp commons schemas params from (nullity 'PGint4)
964+charLength = unsafeFunction "char_length"
965+
966+-- | The `like` expression returns true if the @string@ matches
967+-- the supplied @pattern@. If @pattern@ does not contain percent signs
968+-- or underscores, then the pattern only represents the string itself;
969+-- in that case `like` acts like the equals operator. An underscore (_)
970+-- in pattern stands for (matches) any single character; a percent sign (%)
971+-- matches any sequence of zero or more characters.
972+--
973+-- >>> printSQL $ "abc" `like` "a%"
974+-- (E'abc' LIKE E'a%')
975+like
976+ :: Expression grp commons schemas params from (nullity 'PGtext)
977+ -- ^ string
978+ -> Expression grp commons schemas params from (nullity 'PGtext)
979+ -- ^ pattern
980+ -> Expression grp commons schemas params from (nullity 'PGbool)
981+like = unsafeBinaryOp "LIKE"
982+
983+-- | The key word ILIKE can be used instead of LIKE to make the
984+-- match case-insensitive according to the active locale.
985+--
986+-- >>> printSQL $ "abc" `ilike` "a%"
987+-- (E'abc' ILIKE E'a%')
988+ilike
989+ :: Expression grp commons schemas params from (nullity 'PGtext)
990+ -- ^ string
991+ -> Expression grp commons schemas params from (nullity 'PGtext)
992+ -- ^ pattern
993+ -> Expression grp commons schemas params from (nullity 'PGbool)
994+ilike = unsafeBinaryOp "ILIKE"
995+
996+{-----------------------------------------
997+ -- json and jsonb support
998+
999+See https://www.postgresql.org/docs/10/static/functions-json.html -- most
1000+comments lifted directly from this page.
1001+
1002+Table 9.44: json and jsonb operators
1003+-----------------------------------------}
1004+
1005+-- | Get JSON value (object field or array element) at a key.
1006+(.->)
1007+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1008+ => Expression grp commons schemas params from (nullity json)
1009+ -> Expression grp commons schemas params from (nullity key)
1010+ -> Expression grp commons schemas params from ('Null json)
1011+infixl 8 .->
1012+(.->) = unsafeBinaryOp "->"
1013+
1014+-- | Get JSON value (object field or array element) at a key, as text.
1015+(.->>)
1016+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1017+ => Expression grp commons schemas params from (nullity json)
1018+ -> Expression grp commons schemas params from (nullity key)
1019+ -> Expression grp commons schemas params from ('Null 'PGtext)
1020+infixl 8 .->>
1021+(.->>) = unsafeBinaryOp "->>"
1022+
1023+-- | Get JSON value at a specified path.
1024+(.#>)
1025+ :: (json `In` PGJsonType, PGTextArray "(.#>)" path)
1026+ => Expression grp commons schemas params from (nullity json)
1027+ -> Expression grp commons schemas params from (nullity path)
1028+ -> Expression grp commons schemas params from ('Null json)
1029+infixl 8 .#>
1030+(.#>) = unsafeBinaryOp "#>"
1031+
1032+-- | Get JSON value at a specified path as text.
1033+(.#>>)
1034+ :: (json `In` PGJsonType, PGTextArray "(.#>>)" path)
1035+ => Expression grp commons schemas params from (nullity json)
1036+ -> Expression grp commons schemas params from (nullity path)
1037+ -> Expression grp commons schemas params from ('Null 'PGtext)
1038+infixl 8 .#>>
1039+(.#>>) = unsafeBinaryOp "#>>"
1040+
1041+-- Additional jsonb operators
1042+
1043+-- | Does the left JSON value contain the right JSON path/value entries at the
1044+-- top level?
1045+(.@>)
1046+ :: Expression grp commons schemas params from (nullity 'PGjsonb)
1047+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1048+ -> Condition grp commons schemas params from
1049+infixl 9 .@>
1050+(.@>) = unsafeBinaryOp "@>"
1051+
1052+-- | Are the left JSON path/value entries contained at the top level within the
1053+-- right JSON value?
1054+(.<@)
1055+ :: Expression grp commons schemas params from (nullity 'PGjsonb)
1056+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1057+ -> Condition grp commons schemas params from
1058+infixl 9 .<@
1059+(.<@) = unsafeBinaryOp "<@"
1060+
1061+-- | Does the string exist as a top-level key within the JSON value?
1062+(.?)
1063+ :: Expression grp commons schemas params from (nullity 'PGjsonb)
1064+ -> Expression grp commons schemas params from (nullity 'PGtext)
1065+ -> Condition grp commons schemas params from
1066+infixl 9 .?
1067+(.?) = unsafeBinaryOp "?"
1068+
1069+-- | Do any of these array strings exist as top-level keys?
1070+(.?|)
1071+ :: Expression grp commons schemas params from (nullity 'PGjsonb)
1072+ -> Expression grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1073+ -> Condition grp commons schemas params from
1074+infixl 9 .?|
1075+(.?|) = unsafeBinaryOp "?|"
1076+
1077+-- | Do all of these array strings exist as top-level keys?
1078+(.?&)
1079+ :: Expression grp commons schemas params from (nullity 'PGjsonb)
1080+ -> Expression grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1081+ -> Condition grp commons schemas params from
1082+infixl 9 .?&
1083+(.?&) = unsafeBinaryOp "?&"
1084+
1085+-- | Concatenate two jsonb values into a new jsonb value.
1086+instance
1087+ Semigroup (Expression commons schemas from grouping param (nullity 'PGjsonb)) where
1088+ (<>) = unsafeBinaryOp "||"
1089+
1090+-- | Delete a key or keys from a JSON object, or remove an array element.
1091+--
1092+-- If the right operand is..
1093+--
1094+-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1095+-- are matched based on their key value.
1096+--
1097+-- @ text[] @: Delete multiple key/value pairs or string elements
1098+-- from left operand. Key/value pairs are matched based on their key value.
1099+--
1100+-- @ integer @: Delete the array element with specified index (Negative integers
1101+-- count from the end). Throws an error if top level container is not an array.
1102+(.-.)
1103+ :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1104+ => Expression grp commons schemas params from (nullity 'PGjsonb)
1105+ -> Expression grp commons schemas params from (nullity key)
1106+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1107+infixl 6 .-.
1108+(.-.) = unsafeBinaryOp "-"
1109+
1110+-- | Delete the field or element with specified path (for JSON arrays, negative
1111+-- integers count from the end)
1112+(#-.)
1113+ :: PGTextArray "(#-.)" arrayty
1114+ => Expression grp commons schemas params from (nullity 'PGjsonb)
1115+ -> Expression grp commons schemas params from (nullity arrayty)
1116+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1117+infixl 6 #-.
1118+(#-.) = unsafeBinaryOp "#-"
1119+
1120+{-----------------------------------------
1121+Table 9.45: JSON creation functions
1122+-----------------------------------------}
1123+
1124+-- | Literal binary JSON
1125+jsonbLit
1126+ :: JSON.ToJSON x
1127+ => x -> Expression grp commons schemas params from (nullity 'PGjsonb)
1128+jsonbLit = cast jsonb . UnsafeExpression
1129+ . singleQuotedUtf8 . toStrict . JSON.encode
1130+
1131+-- | Literal JSON
1132+jsonLit
1133+ :: JSON.ToJSON x
1134+ => x -> Expression grp commons schemas params from (nullity 'PGjson)
1135+jsonLit = cast json . UnsafeExpression
1136+ . singleQuotedUtf8 . toStrict . JSON.encode
1137+
1138+-- | Returns the value as json. Arrays and composites are converted
1139+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1140+-- type to json, the cast function will be used to perform the conversion;
1141+-- otherwise, a scalar value is produced. For any scalar type other than a
1142+-- number, a Boolean, or a null value, the text representation will be used, in
1143+-- such a fashion that it is a valid json value.
1144+toJson
1145+ :: Expression grp commons schemas params from (nullity ty)
1146+ -> Expression grp commons schemas params from (nullity 'PGjson)
1147+toJson = unsafeFunction "to_json"
1148+
1149+-- | Returns the value as jsonb. Arrays and composites are converted
1150+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1151+-- type to json, the cast function will be used to perform the conversion;
1152+-- otherwise, a scalar value is produced. For any scalar type other than a
1153+-- number, a Boolean, or a null value, the text representation will be used, in
1154+-- such a fashion that it is a valid jsonb value.
1155+toJsonb
1156+ :: Expression grp commons schemas params from (nullity ty)
1157+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1158+toJsonb = unsafeFunction "to_jsonb"
1159+
1160+-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1161+-- becomes a JSON array of arrays.
1162+arrayToJson
1163+ :: PGArray "arrayToJson" arr
1164+ => Expression grp commons schemas params from (nullity arr)
1165+ -> Expression grp commons schemas params from (nullity 'PGjson)
1166+arrayToJson = unsafeFunction "array_to_json"
1167+
1168+-- | Returns the row as a JSON object.
1169+rowToJson
1170+ :: Expression grp commons schemas params from (nullity ('PGcomposite ty))
1171+ -> Expression grp commons schemas params from (nullity 'PGjson)
1172+rowToJson = unsafeFunction "row_to_json"
1173+
1174+-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1175+-- argument list.
1176+jsonBuildArray
1177+ :: SListI elems
1178+ => NP (Expression grp commons schemas params from) elems
1179+ -> Expression grp commons schemas params from (nullity 'PGjson)
1180+jsonBuildArray = unsafeVariadicFunction "json_build_array"
1181+
1182+-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1183+-- variadic argument list.
1184+jsonbBuildArray
1185+ :: SListI elems
1186+ => NP (Expression grp commons schemas params from) elems
1187+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1188+jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1189+
1190+unsafeRowFunction
1191+ :: All Top elems
1192+ => NP (Aliased (Expression grp commons schemas params from)) elems
1193+ -> [ByteString]
1194+unsafeRowFunction =
1195+ (`appEndo` []) . hcfoldMap (Proxy :: Proxy Top)
1196+ (\(col `As` name) -> Endo $ \xs ->
1197+ renderAliasString name : renderSQL col : xs)
1198+ where
1199+ renderAliasString :: KnownSymbol alias => Alias alias -> ByteString
1200+ renderAliasString = singleQuotedText . fromString . symbolVal
1201+
1202+-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1203+-- argument list. The elements of the argument list must alternate between text
1204+-- and values.
1205+jsonBuildObject
1206+ :: All Top elems
1207+ => NP (Aliased (Expression grp commons schemas params from)) elems
1208+ -> Expression grp commons schemas params from (nullity 'PGjson)
1209+jsonBuildObject
1210+ = unsafeFunction "json_build_object"
1211+ . UnsafeExpression
1212+ . commaSeparated
1213+ . unsafeRowFunction
1214+
1215+-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1216+-- variadic argument list. The elements of the argument list must alternate
1217+-- between text and values.
1218+jsonbBuildObject
1219+ :: All Top elems
1220+ => NP (Aliased (Expression grp commons schemas params from)) elems
1221+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1222+jsonbBuildObject
1223+ = unsafeFunction "jsonb_build_object"
1224+ . UnsafeExpression
1225+ . commaSeparated
1226+ . unsafeRowFunction
1227+
1228+-- | Builds a JSON object out of a text array. The array must have either
1229+-- exactly one dimension with an even number of members, in which case they are
1230+-- taken as alternating key/value pairs, or two dimensions such that each inner
1231+-- array has exactly two elements, which are taken as a key/value pair.
1232+jsonObject
1233+ :: PGArrayOf "jsonObject" arr ('NotNull 'PGtext)
1234+ => Expression grp commons schemas params from (nullity arr)
1235+ -> Expression grp commons schemas params from (nullity 'PGjson)
1236+jsonObject = unsafeFunction "json_object"
1237+
1238+-- | Builds a binary JSON object out of a text array. The array must have either
1239+-- exactly one dimension with an even number of members, in which case they are
1240+-- taken as alternating key/value pairs, or two dimensions such that each inner
1241+-- array has exactly two elements, which are taken as a key/value pair.
1242+jsonbObject
1243+ :: PGArrayOf "jsonbObject" arr ('NotNull 'PGtext)
1244+ => Expression grp commons schemas params from (nullity arr)
1245+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1246+jsonbObject = unsafeFunction "jsonb_object"
1247+
1248+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1249+-- keys and one for values, that are zipped pairwise to create a JSON object.
1250+jsonZipObject
1251+ :: ( PGArrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1252+ , PGArrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
1253+ => Expression grp commons schemas params from (nullity keysArray)
1254+ -> Expression grp commons schemas params from (nullity valuesArray)
1255+ -> Expression grp commons schemas params from (nullity 'PGjson)
1256+jsonZipObject ks vs =
1257+ unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1258+
1259+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1260+-- keys and one for values, that are zipped pairwise to create a binary JSON
1261+-- object.
1262+jsonbZipObject
1263+ :: ( PGArrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1264+ , PGArrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
1265+ => Expression grp commons schemas params from (nullity keysArray)
1266+ -> Expression grp commons schemas params from (nullity valuesArray)
1267+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1268+jsonbZipObject ks vs =
1269+ unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1270+
1271+{-----------------------------------------
1272+Table 9.46: JSON processing functions
1273+-----------------------------------------}
1274+
1275+-- | Returns the number of elements in the outermost JSON array.
1276+jsonArrayLength
1277+ :: Expression grp commons schemas params from (nullity 'PGjson)
1278+ -> Expression grp commons schemas params from (nullity 'PGint4)
1279+jsonArrayLength = unsafeFunction "json_array_length"
1280+
1281+-- | Returns the number of elements in the outermost binary JSON array.
1282+jsonbArrayLength
1283+ :: Expression grp commons schemas params from (nullity 'PGjsonb)
1284+ -> Expression grp commons schemas params from (nullity 'PGint4)
1285+jsonbArrayLength = unsafeFunction "jsonb_array_length"
1286+
1287+-- | Returns JSON value pointed to by the given path (equivalent to #>
1288+-- operator).
1289+jsonExtractPath
1290+ :: SListI elems
1291+ => Expression grp commons schemas params from (nullity 'PGjson)
1292+ -> NP (Expression grp commons schemas params from) elems
1293+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1294+jsonExtractPath x xs =
1295+ unsafeVariadicFunction "json_extract_path" (x :* xs)
1296+
1297+-- | Returns JSON value pointed to by the given path (equivalent to #>
1298+-- operator).
1299+jsonbExtractPath
1300+ :: SListI elems
1301+ => Expression grp commons schemas params from (nullity 'PGjsonb)
1302+ -> NP (Expression grp commons schemas params from) elems
1303+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1304+jsonbExtractPath x xs =
1305+ unsafeVariadicFunction "jsonb_extract_path" (x :* xs)
1306+
1307+-- | Returns JSON value pointed to by the given path (equivalent to #>
1308+-- operator), as text.
1309+jsonExtractPathAsText
1310+ :: SListI elems
1311+ => Expression grp commons schemas params from (nullity 'PGjson)
1312+ -> NP (Expression grp commons schemas params from) elems
1313+ -> Expression grp commons schemas params from (nullity 'PGjson)
1314+jsonExtractPathAsText x xs =
1315+ unsafeVariadicFunction "json_extract_path_text" (x :* xs)
1316+
1317+-- | Returns JSON value pointed to by the given path (equivalent to #>
1318+-- operator), as text.
1319+jsonbExtractPathAsText
1320+ :: SListI elems
1321+ => Expression grp commons schemas params from (nullity 'PGjsonb)
1322+ -> NP (Expression grp commons schemas params from) elems
1323+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1324+jsonbExtractPathAsText x xs =
1325+ unsafeVariadicFunction "jsonb_extract_path_text" (x :* xs)
1326+
1327+-- | Returns the type of the outermost JSON value as a text string. Possible
1328+-- types are object, array, string, number, boolean, and null.
1329+jsonTypeof
1330+ :: Expression grp commons schemas params from (nullity 'PGjson)
1331+ -> Expression grp commons schemas params from (nullity 'PGtext)
1332+jsonTypeof = unsafeFunction "json_typeof"
1333+
1334+-- | Returns the type of the outermost binary JSON value as a text string.
1335+-- Possible types are object, array, string, number, boolean, and null.
1336+jsonbTypeof
1337+ :: Expression grp commons schemas params from (nullity 'PGjsonb)
1338+ -> Expression grp commons schemas params from (nullity 'PGtext)
1339+jsonbTypeof = unsafeFunction "jsonb_typeof"
1340+
1341+-- | Returns its argument with all object fields that have null values omitted.
1342+-- Other null values are untouched.
1343+jsonStripNulls
1344+ :: Expression grp commons schemas params from (nullity 'PGjson)
1345+ -> Expression grp commons schemas params from (nullity 'PGjson)
1346+jsonStripNulls = unsafeFunction "json_strip_nulls"
1347+
1348+-- | Returns its argument with all object fields that have null values omitted.
1349+-- Other null values are untouched.
1350+jsonbStripNulls
1351+ :: Expression grp commons schemas params from (nullity 'PGjsonb)
1352+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1353+jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1354+
1355+-- | @ jsonbSet target path new_value create_missing @
1356+--
1357+-- Returns target with the section designated by path replaced by new_value,
1358+-- or with new_value added if create_missing is true ( default is true) and the
1359+-- item designated by path does not exist. As with the path orientated
1360+-- operators, negative integers that appear in path count from the end of JSON
1361+-- arrays.
1362+jsonbSet
1363+ :: PGTextArray "jsonbSet" arr
1364+ => Expression grp commons schemas params from (nullity 'PGjsonb)
1365+ -> Expression grp commons schemas params from (nullity arr)
1366+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1367+ -> Maybe (Expression grp commons schemas params from (nullity 'PGbool))
1368+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1369+jsonbSet tgt path val createMissing = case createMissing of
1370+ Just m -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* m :* Nil)
1371+ Nothing -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* Nil)
1372+
1373+-- | @ jsonbInsert target path new_value insert_after @
1374+--
1375+-- Returns target with new_value inserted. If target section designated by
1376+-- path is in a JSONB array, new_value will be inserted before target or after
1377+-- if insert_after is true (default is false). If target section designated by
1378+-- path is in JSONB object, new_value will be inserted only if target does not
1379+-- exist. As with the path orientated operators, negative integers that appear
1380+-- in path count from the end of JSON arrays.
1381+jsonbInsert
1382+ :: PGTextArray "jsonbInsert" arr
1383+ => Expression grp commons schemas params from (nullity 'PGjsonb)
1384+ -> Expression grp commons schemas params from (nullity arr)
1385+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1386+ -> Maybe (Expression grp commons schemas params from (nullity 'PGbool))
1387+ -> Expression grp commons schemas params from (nullity 'PGjsonb)
1388+jsonbInsert tgt path val insertAfter = case insertAfter of
1389+ Just i -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1390+ Nothing -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* Nil)
1391+
1392+-- | Returns its argument as indented JSON text.
1393+jsonbPretty
1394+ :: Expression grp commons schemas params from (nullity 'PGjsonb)
1395+ -> Expression grp commons schemas params from (nullity 'PGtext)
1396+jsonbPretty = unsafeFunction "jsonb_pretty"
1397+
1398+{-----------------------------------------
1399+aggregation
1400+-----------------------------------------}
1401+
1402+-- | escape hatch to define aggregate functions
1403+unsafeAggregate
1404+ :: ByteString -- ^ aggregate function
1405+ -> Expression 'Ungrouped commons schemas params from xty
1406+ -> Expression ('Grouped bys) commons schemas params from yty
1407+unsafeAggregate fun x = UnsafeExpression $ mconcat
1408+ [fun, "(", renderSQL x, ")"]
1409+
1410+-- | escape hatch to define aggregate functions over distinct values
1411+unsafeAggregateDistinct
1412+ :: ByteString -- ^ aggregate function
1413+ -> Expression 'Ungrouped commons schemas params from xty
1414+ -> Expression ('Grouped bys) commons schemas params from yty
1415+unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
1416+ [fun, "(DISTINCT ", renderSQL x, ")"]
1417+
1418+-- | >>> :{
1419+-- let
1420+-- expression :: Expression ('Grouped bys) commons schemas params '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Null 'PGnumeric)
1421+-- expression = sum_ #col
1422+-- in printSQL expression
1423+-- :}
1424+-- sum("col")
1425+sum_
1426+ :: ty `In` PGNum
1427+ => Expression 'Ungrouped commons schemas params from (nullity ty)
1428+ -- ^ what to sum
1429+ -> Expression ('Grouped bys) commons schemas params from (nullity ty)
1430+sum_ = unsafeAggregate "sum"
1431+
1432+-- | >>> :{
1433+-- let
1434+-- expression :: Expression ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGnumeric]] (nullity 'PGnumeric)
1435+-- expression = sumDistinct #col
1436+-- in printSQL expression
1437+-- :}
1438+-- sum(DISTINCT "col")
1439+sumDistinct
1440+ :: ty `In` PGNum
1441+ => Expression 'Ungrouped commons schemas params from (nullity ty)
1442+ -- ^ what to sum
1443+ -> Expression ('Grouped bys) commons schemas params from (nullity ty)
1444+sumDistinct = unsafeAggregateDistinct "sum"
1445+
1446+-- | A constraint for `PGType`s that you can take averages of and the resulting
1447+-- `PGType`.
1448+class PGAvg ty avg | ty -> avg where
1449+ avg, avgDistinct
1450+ :: Expression 'Ungrouped commons schemas params from (nullity ty)
1451+ -- ^ what to average
1452+ -> Expression ('Grouped bys) commons schemas params from (nullity avg)
1453+ avg = unsafeAggregate "avg"
1454+ avgDistinct = unsafeAggregateDistinct "avg"
1455+instance PGAvg 'PGint2 'PGnumeric
1456+instance PGAvg 'PGint4 'PGnumeric
1457+instance PGAvg 'PGint8 'PGnumeric
1458+instance PGAvg 'PGnumeric 'PGnumeric
1459+instance PGAvg 'PGfloat4 'PGfloat8
1460+instance PGAvg 'PGfloat8 'PGfloat8
1461+instance PGAvg 'PGinterval 'PGinterval
1462+
1463+-- | >>> :{
1464+-- let
1465+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1466+-- expression = bitAnd #col
1467+-- in printSQL expression
1468+-- :}
1469+-- bit_and("col")
1470+bitAnd
1471+ :: int `In` PGIntegral
1472+ => Expression 'Ungrouped commons schemas params from (nullity int)
1473+ -- ^ what to aggregate
1474+ -> Expression ('Grouped bys) commons schemas params from (nullity int)
1475+bitAnd = unsafeAggregate "bit_and"
1476+
1477+-- | >>> :{
1478+-- let
1479+-- expression :: Expression ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1480+-- expression = bitOr #col
1481+-- in printSQL expression
1482+-- :}
1483+-- bit_or("col")
1484+bitOr
1485+ :: int `In` PGIntegral
1486+ => Expression 'Ungrouped commons schemas params from (nullity int)
1487+ -- ^ what to aggregate
1488+ -> Expression ('Grouped bys) commons schemas params from (nullity int)
1489+bitOr = unsafeAggregate "bit_or"
1490+
1491+-- | >>> :{
1492+-- let
1493+-- expression :: Expression ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1494+-- expression = bitAndDistinct #col
1495+-- in printSQL expression
1496+-- :}
1497+-- bit_and(DISTINCT "col")
1498+bitAndDistinct
1499+ :: int `In` PGIntegral
1500+ => Expression 'Ungrouped commons schemas params from (nullity int)
1501+ -- ^ what to aggregate
1502+ -> Expression ('Grouped bys) commons schemas params from (nullity int)
1503+bitAndDistinct = unsafeAggregateDistinct "bit_and"
1504+
1505+-- | >>> :{
1506+-- let
1507+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1508+-- expression = bitOrDistinct #col
1509+-- in printSQL expression
1510+-- :}
1511+-- bit_or(DISTINCT "col")
1512+bitOrDistinct
1513+ :: int `In` PGIntegral
1514+ => Expression 'Ungrouped commons schemas params from (nullity int)
1515+ -- ^ what to aggregate
1516+ -> Expression ('Grouped bys) commons schemas params from (nullity int)
1517+bitOrDistinct = unsafeAggregateDistinct "bit_or"
1518+
1519+-- | >>> :{
1520+-- let
1521+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1522+-- expression = boolAnd #col
1523+-- in printSQL expression
1524+-- :}
1525+-- bool_and("col")
1526+boolAnd
1527+ :: Expression 'Ungrouped commons schemas params from (nullity 'PGbool)
1528+ -- ^ what to aggregate
1529+ -> Expression ('Grouped bys) commons schemas params from (nullity 'PGbool)
1530+boolAnd = unsafeAggregate "bool_and"
1531+
1532+-- | >>> :{
1533+-- let
1534+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1535+-- expression = boolOr #col
1536+-- in printSQL expression
1537+-- :}
1538+-- bool_or("col")
1539+boolOr
1540+ :: Expression 'Ungrouped commons schemas params from (nullity 'PGbool)
1541+ -- ^ what to aggregate
1542+ -> Expression ('Grouped bys) commons schemas params from (nullity 'PGbool)
1543+boolOr = unsafeAggregate "bool_or"
1544+
1545+-- | >>> :{
1546+-- let
1547+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1548+-- expression = boolAndDistinct #col
1549+-- in printSQL expression
1550+-- :}
1551+-- bool_and(DISTINCT "col")
1552+boolAndDistinct
1553+ :: Expression 'Ungrouped commons schemas params from (nullity 'PGbool)
1554+ -- ^ what to aggregate
1555+ -> Expression ('Grouped bys) commons schemas params from (nullity 'PGbool)
1556+boolAndDistinct = unsafeAggregateDistinct "bool_and"
1557+
1558+-- | >>> :{
1559+-- let
1560+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1561+-- expression = boolOrDistinct #col
1562+-- in printSQL expression
1563+-- :}
1564+-- bool_or(DISTINCT "col")
1565+boolOrDistinct
1566+ :: Expression 'Ungrouped commons schemas params from (nullity 'PGbool)
1567+ -- ^ what to aggregate
1568+ -> Expression ('Grouped bys) commons schemas params from (nullity 'PGbool)
1569+boolOrDistinct = unsafeAggregateDistinct "bool_or"
1570+
1571+-- | A special aggregation that does not require an input
1572+--
1573+-- >>> printSQL countStar
1574+-- count(*)
1575+countStar
1576+ :: Expression ('Grouped bys) commons schemas params from ('NotNull 'PGint8)
1577+countStar = UnsafeExpression $ "count(*)"
1578+
1579+-- | >>> :{
1580+-- let
1581+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1582+-- expression = count #col
1583+-- in printSQL expression
1584+-- :}
1585+-- count("col")
1586+count
1587+ :: Expression 'Ungrouped commons schemas params from ty
1588+ -- ^ what to count
1589+ -> Expression ('Grouped bys) commons schemas params from ('NotNull 'PGint8)
1590+count = unsafeAggregate "count"
1591+
1592+-- | >>> :{
1593+-- let
1594+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1595+-- expression = countDistinct #col
1596+-- in printSQL expression
1597+-- :}
1598+-- count(DISTINCT "col")
1599+countDistinct
1600+ :: Expression 'Ungrouped commons schemas params from ty
1601+ -- ^ what to count
1602+ -> Expression ('Grouped bys) commons schemas params from ('NotNull 'PGint8)
1603+countDistinct = unsafeAggregateDistinct "count"
1604+
1605+-- | synonym for `boolAnd`
1606+--
1607+-- >>> :{
1608+-- let
1609+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1610+-- expression = every #col
1611+-- in printSQL expression
1612+-- :}
1613+-- every("col")
1614+every
1615+ :: Expression 'Ungrouped commons schemas params from (nullity 'PGbool)
1616+ -- ^ what to aggregate
1617+ -> Expression ('Grouped bys) commons schemas params from (nullity 'PGbool)
1618+every = unsafeAggregate "every"
1619+
1620+-- | synonym for `boolAndDistinct`
1621+--
1622+-- >>> :{
1623+-- let
1624+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1625+-- expression = everyDistinct #col
1626+-- in printSQL expression
1627+-- :}
1628+-- every(DISTINCT "col")
1629+everyDistinct
1630+ :: Expression 'Ungrouped commons schemas params from (nullity 'PGbool)
1631+ -- ^ what to aggregate
1632+ -> Expression ('Grouped bys) commons schemas params from (nullity 'PGbool)
1633+everyDistinct = unsafeAggregateDistinct "every"
1634+
1635+-- | minimum and maximum aggregation
1636+max_, min_, maxDistinct, minDistinct
1637+ :: Expression 'Ungrouped commons schemas params from (nullity ty)
1638+ -- ^ what to aggregate
1639+ -> Expression ('Grouped bys) commons schemas params from (nullity ty)
1640+max_ = unsafeAggregate "max"
1641+min_ = unsafeAggregate "min"
1642+maxDistinct = unsafeAggregateDistinct "max"
1643+minDistinct = unsafeAggregateDistinct "min"
1644+
1645+{-----------------------------------------
1646+type expressions
1647+-----------------------------------------}
1648+
1649+-- | `TypeExpression`s are used in `cast`s and `createTable` commands.
1650+newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
1651+ = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1652+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
1653+instance RenderSQL (TypeExpression schemas ty) where
1654+ renderSQL = renderTypeExpression
1655+
1656+-- | The enum or composite type in a `Typedef` can be expressed by its alias.
1657+typedef
1658+ :: (Has sch schemas schema, Has td schema ('Typedef ty))
1659+ => QualifiedAlias sch td
1660+ -> TypeExpression schemas (nullity ty)
1661+typedef = UnsafeTypeExpression . renderSQL
1662+
1663+-- | The composite type corresponding to a `Table` definition can be expressed
1664+-- by its alias.
1665+typetable
1666+ :: (Has sch schemas schema, Has tab schema ('Table table))
1667+ => QualifiedAlias sch tab
1668+ -> TypeExpression schemas (nullity ('PGcomposite (TableToRow table)))
1669+typetable = UnsafeTypeExpression . renderSQL
1670+
1671+-- | The composite type corresponding to a `View` definition can be expressed
1672+-- by its alias.
1673+typeview
1674+ :: (Has sch schemas schema, Has vw schema ('View view))
1675+ => QualifiedAlias sch vw
1676+ -> TypeExpression schemas (nullity ('PGcomposite view))
1677+typeview = UnsafeTypeExpression . renderSQL
1678+
1679+-- | logical Boolean (true/false)
1680+bool :: TypeExpression schemas (nullity 'PGbool)
1681+bool = UnsafeTypeExpression "bool"
1682+-- | signed two-byte integer
1683+int2, smallint :: TypeExpression schemas (nullity 'PGint2)
1684+int2 = UnsafeTypeExpression "int2"
1685+smallint = UnsafeTypeExpression "smallint"
1686+-- | signed four-byte integer
1687+int4, int, integer :: TypeExpression schemas (nullity 'PGint4)
1688+int4 = UnsafeTypeExpression "int4"
1689+int = UnsafeTypeExpression "int"
1690+integer = UnsafeTypeExpression "integer"
1691+-- | signed eight-byte integer
1692+int8, bigint :: TypeExpression schemas (nullity 'PGint8)
1693+int8 = UnsafeTypeExpression "int8"
1694+bigint = UnsafeTypeExpression "bigint"
1695+-- | arbitrary precision numeric type
1696+numeric :: TypeExpression schemas (nullity 'PGnumeric)
1697+numeric = UnsafeTypeExpression "numeric"
1698+-- | single precision floating-point number (4 bytes)
1699+float4, real :: TypeExpression schemas (nullity 'PGfloat4)
1700+float4 = UnsafeTypeExpression "float4"
1701+real = UnsafeTypeExpression "real"
1702+-- | double precision floating-point number (8 bytes)
1703+float8, doublePrecision :: TypeExpression schemas (nullity 'PGfloat8)
1704+float8 = UnsafeTypeExpression "float8"
1705+doublePrecision = UnsafeTypeExpression "double precision"
1706+-- | variable-length character string
1707+text :: TypeExpression schemas (nullity 'PGtext)
1708+text = UnsafeTypeExpression "text"
1709+-- | fixed-length character string
1710+char, character
1711+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
1712+ => TypeExpression schemas (nullity ('PGchar n))
1713+char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
1714+character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
1715+-- | variable-length character string
1716+varchar, characterVarying
1717+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
1718+ => TypeExpression schemas (nullity ('PGvarchar n))
1719+varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
1720+characterVarying = UnsafeTypeExpression $
1721+ "character varying(" <> renderNat @n <> ")"
1722+-- | binary data ("byte array")
1723+bytea :: TypeExpression schemas (nullity 'PGbytea)
1724+bytea = UnsafeTypeExpression "bytea"
1725+-- | date and time (no time zone)
1726+timestamp :: TypeExpression schemas (nullity 'PGtimestamp)
1727+timestamp = UnsafeTypeExpression "timestamp"
1728+-- | date and time, including time zone
1729+timestampWithTimeZone :: TypeExpression schemas (nullity 'PGtimestamptz)
1730+timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1731+-- | calendar date (year, month, day)
1732+date :: TypeExpression schemas (nullity 'PGdate)
1733+date = UnsafeTypeExpression "date"
1734+-- | time of day (no time zone)
1735+time :: TypeExpression schemas (nullity 'PGtime)
1736+time = UnsafeTypeExpression "time"
1737+-- | time of day, including time zone
1738+timeWithTimeZone :: TypeExpression schemas (nullity 'PGtimetz)
1739+timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1740+-- | time span
1741+interval :: TypeExpression schemas (nullity 'PGinterval)
1742+interval = UnsafeTypeExpression "interval"
1743+-- | universally unique identifier
1744+uuid :: TypeExpression schemas (nullity 'PGuuid)
1745+uuid = UnsafeTypeExpression "uuid"
1746+-- | IPv4 or IPv6 host address
1747+inet :: TypeExpression schemas (nullity 'PGinet)
1748+inet = UnsafeTypeExpression "inet"
1749+-- | textual JSON data
1750+json :: TypeExpression schemas (nullity 'PGjson)
1751+json = UnsafeTypeExpression "json"
1752+-- | binary JSON data, decomposed
1753+jsonb :: TypeExpression schemas (nullity 'PGjsonb)
1754+jsonb = UnsafeTypeExpression "jsonb"
1755+-- | variable length array
1756+vararray
1757+ :: TypeExpression schemas pg
1758+ -> TypeExpression schemas (nullity ('PGvararray pg))
1759+vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
1760+-- | fixed length array
1761+--
1762+-- >>> renderSQL (fixarray @'[2] json)
1763+-- "json[2]"
1764+fixarray
1765+ :: forall dims schemas nullity pg. All KnownNat dims
1766+ => TypeExpression schemas pg
1767+ -> TypeExpression schemas (nullity ('PGfixarray dims pg))
1768+fixarray ty = UnsafeTypeExpression $
1769+ renderSQL ty <> renderDims @dims
1770+ where
1771+ renderDims :: forall ns. All KnownNat ns => ByteString
1772+ renderDims =
1773+ ("[" <>)
1774+ . (<> "]")
1775+ . ByteString.intercalate "]["
1776+ . hcollapse
1777+ $ hcmap (Proxy @KnownNat)
1778+ (K . fromString . show . natVal)
1779+ (hpure Proxy :: NP Proxy ns)
1780+
1781+-- | `pgtype` is a demoted version of a `PGType`
1782+class PGTyped schemas (ty :: NullityType) where
1783+ pgtype :: TypeExpression schemas ty
1784+instance PGTyped schemas (nullity 'PGbool) where pgtype = bool
1785+instance PGTyped schemas (nullity 'PGint2) where pgtype = int2
1786+instance PGTyped schemas (nullity 'PGint4) where pgtype = int4
1787+instance PGTyped schemas (nullity 'PGint8) where pgtype = int8
1788+instance PGTyped schemas (nullity 'PGnumeric) where pgtype = numeric
1789+instance PGTyped schemas (nullity 'PGfloat4) where pgtype = float4
1790+instance PGTyped schemas (nullity 'PGfloat8) where pgtype = float8
1791+instance PGTyped schemas (nullity 'PGtext) where pgtype = text
1792+instance (KnownNat n, 1 <= n)
1793+ => PGTyped schemas (nullity ('PGchar n)) where pgtype = char @n
1794+instance (KnownNat n, 1 <= n)
1795+ => PGTyped schemas (nullity ('PGvarchar n)) where pgtype = varchar @n
1796+instance PGTyped schemas (nullity 'PGbytea) where pgtype = bytea
1797+instance PGTyped schemas (nullity 'PGtimestamp) where pgtype = timestamp
1798+instance PGTyped schemas (nullity 'PGtimestamptz) where pgtype = timestampWithTimeZone
1799+instance PGTyped schemas (nullity 'PGdate) where pgtype = date
1800+instance PGTyped schemas (nullity 'PGtime) where pgtype = time
1801+instance PGTyped schemas (nullity 'PGtimetz) where pgtype = timeWithTimeZone
1802+instance PGTyped schemas (nullity 'PGinterval) where pgtype = interval
1803+instance PGTyped schemas (nullity 'PGuuid) where pgtype = uuid
1804+instance PGTyped schemas (nullity 'PGjson) where pgtype = json
1805+instance PGTyped schemas (nullity 'PGjsonb) where pgtype = jsonb
1806+instance PGTyped schemas ty
1807+ => PGTyped schemas (nullity ('PGvararray ty)) where
1808+ pgtype = vararray (pgtype @schemas @ty)
1809+instance (All KnownNat dims, PGTyped schemas ty)
1810+ => PGTyped schemas (nullity ('PGfixarray dims ty)) where
1811+ pgtype = fixarray @dims (pgtype @schemas @ty)
1812+
1813+{-----------------------------------------
1814+Sorting
1815+-----------------------------------------}
1816+
1817+-- | `SortExpression`s are used by `sortBy` to optionally sort the results
1818+-- of a `Query`. `Asc` or `Desc` set the sort direction of a `NotNull` result
1819+-- column to ascending or descending. Ascending order puts smaller values
1820+-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
1821+-- descending order is determined with the `.>` operator. `AscNullsFirst`,
1822+-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
1823+-- determine whether nulls appear before or after non-null values in the sort
1824+-- ordering of a `Null` result column.
1825+data SortExpression grp commons schemas params from where
1826+ Asc
1827+ :: Expression grp commons schemas params from ('NotNull ty)
1828+ -> SortExpression grp commons schemas params from
1829+ Desc
1830+ :: Expression grp commons schemas params from ('NotNull ty)
1831+ -> SortExpression grp commons schemas params from
1832+ AscNullsFirst
1833+ :: Expression grp commons schemas params from ('Null ty)
1834+ -> SortExpression grp commons schemas params from
1835+ AscNullsLast
1836+ :: Expression grp commons schemas params from ('Null ty)
1837+ -> SortExpression grp commons schemas params from
1838+ DescNullsFirst
1839+ :: Expression grp commons schemas params from ('Null ty)
1840+ -> SortExpression grp commons schemas params from
1841+ DescNullsLast
1842+ :: Expression grp commons schemas params from ('Null ty)
1843+ -> SortExpression grp commons schemas params from
1844+deriving instance Show (SortExpression grp commons schemas params from)
1845+
1846+class OrderBy expr where
1847+ orderBy
1848+ :: [SortExpression grp commons schemas params from]
1849+ -> expr grp commons schemas params from
1850+ -> expr grp commons schemas params from
1851+
1852+-- | Render a `SortExpression`.
1853+instance RenderSQL (SortExpression grp commons schemas params from) where
1854+ renderSQL = \case
1855+ Asc expression -> renderSQL expression <+> "ASC"
1856+ Desc expression -> renderSQL expression <+> "DESC"
1857+ AscNullsFirst expression -> renderSQL expression
1858+ <+> "ASC NULLS FIRST"
1859+ DescNullsFirst expression -> renderSQL expression
1860+ <+> "DESC NULLS FIRST"
1861+ AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
1862+ DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
1863+
1864+data WindowDefinition grp commons schemas params from where
1865+ WindowDefinition
1866+ :: SListI bys
1867+ => NP (Expression grp commons schemas params from) bys
1868+ -> [SortExpression grp commons schemas params from]
1869+ -> WindowDefinition grp commons schemas params from
1870+
1871+instance OrderBy WindowDefinition where
1872+ orderBy sortsR (WindowDefinition parts sortsL)
1873+ = WindowDefinition parts (sortsL ++ sortsR)
1874+
1875+instance RenderSQL (WindowDefinition commons schemas from grp params) where
1876+ renderSQL (WindowDefinition part ord) =
1877+ renderPartitionByClause part <> renderOrderByClause ord
1878+ where
1879+ renderPartitionByClause = \case
1880+ Nil -> ""
1881+ parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
1882+ renderOrderByClause = \case
1883+ [] -> ""
1884+ srts -> " ORDER" <+> "BY"
1885+ <+> commaSeparated (renderSQL <$> srts)
1886+
1887+partitionBy
1888+ :: SListI bys
1889+ => NP (Expression grp commons schemas params from) bys
1890+ -> WindowDefinition grp commons schemas params from
1891+partitionBy bys = WindowDefinition bys []
1892+
1893+newtype WindowFunction
1894+ (grp :: Grouping)
1895+ (commons :: FromType)
1896+ (schemas :: SchemasType)
1897+ (params :: [NullityType])
1898+ (from :: FromType)
1899+ (ty :: NullityType)
1900+ = UnsafeWindowFunction { renderWindowFunction :: ByteString }
1901+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
1902+
1903+instance RenderSQL (WindowFunction grp commons schemas params from ty) where
1904+ renderSQL = renderWindowFunction
1905+
1906+{- | rank of the current row with gaps; same as `rowNumber` of its first peer
1907+>>> printSQL rank
1908+rank()
1909+-}
1910+rank :: WindowFunction grp commons schemas params from ('NotNull 'PGint8)
1911+rank = UnsafeWindowFunction "rank()"
1912+
1913+{- | number of the current row within its partition, counting from 1
1914+>>> printSQL rowNumber
1915+row_number()
1916+-}
1917+rowNumber :: WindowFunction grp commons schemas params from ('NotNull 'PGint8)
1918+rowNumber = UnsafeWindowFunction "row_number()"
1919+
1920+{- | rank of the current row without gaps; this function counts peer groups
1921+>>> printSQL denseRank
1922+dense_rank()
1923+-}
1924+denseRank :: WindowFunction grp commons schemas params from ('NotNull 'PGint8)
1925+denseRank = UnsafeWindowFunction "dense_rank()"
1926+
1927+{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
1928+>>> printSQL percentRank
1929+percent_rank()
1930+-}
1931+percentRank :: WindowFunction grp commons schemas params from ('NotNull 'PGfloat8)
1932+percentRank = UnsafeWindowFunction "percent_rank()"
1933+
1934+{- | cumulative distribution: (number of partition rows
1935+preceding or peer with current row) / total partition rows
1936+>>> printSQL cumeDist
1937+cume_dist()
1938+-}
1939+cumeDist :: WindowFunction grp commons schemas params from ('NotNull 'PGfloat8)
1940+cumeDist = UnsafeWindowFunction "cume_dist()"
1941+
1942+{- | integer ranging from 1 to the argument value,
1943+dividing the partition as equally as possible
1944+-}
1945+ntile
1946+ :: Expression grp commons schemas params from ('NotNull 'PGint4)
1947+ -- ^ numuckets
1948+ -> WindowFunction grp commons schemas params from ('NotNull 'PGint4)
1949+ntile numBuckets = UnsafeWindowFunction $ "ntile"
1950+ <> parenthesized (renderSQL numBuckets)
1951+
1952+{- | returns value evaluated at the row that is offset rows before the current
1953+row within the partition; if there is no such row, instead return default
1954+(which must be of the same type as value). Both offset and default are
1955+evaluated with respect to the current row.
1956+-}
1957+lag
1958+ :: Expression grp commons schemas params from ty
1959+ -- ^ value
1960+ -> Expression grp commons schemas params from ('NotNull 'PGint4)
1961+ -- ^ offset
1962+ -> Expression grp commons schemas params from ty
1963+ -- ^ default
1964+ -> WindowFunction grp commons schemas params from ty
1965+lag value offset def = UnsafeWindowFunction $ "lag"
1966+ <> parenthesized
1967+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
1968+
1969+{- | returns value evaluated at the row that is offset rows after the current
1970+row within the partition; if there is no such row, instead return default
1971+(which must be of the same type as value). Both offset and default are
1972+evaluated with respect to the current row.
1973+-}
1974+lead
1975+ :: Expression grp commons schemas params from ty
1976+ -- ^ value
1977+ -> Expression grp commons schemas params from ('NotNull 'PGint4)
1978+ -- ^ offset
1979+ -> Expression grp commons schemas params from ty
1980+ -- ^ default
1981+ -> WindowFunction grp commons schemas params from ty
1982+lead value offset def = UnsafeWindowFunction $ "lag"
1983+ <> parenthesized
1984+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
1985+
1986+{- | returns value evaluated at the row that is the
1987+first row of the window frame
1988+-}
1989+firstValue
1990+ :: Expression grp commons schemas params from ty
1991+ -- ^ value
1992+ -> WindowFunction grp commons schemas params from ty
1993+firstValue value = UnsafeWindowFunction $ "first_value"
1994+ <> parenthesized (renderSQL value)
1995+
1996+{- | returns value evaluated at the row that is the
1997+last row of the window frame
1998+-}
1999+lastValue
2000+ :: Expression grp commons schemas params from ty
2001+ -- ^ value
2002+ -> WindowFunction grp commons schemas params from ty
2003+lastValue value = UnsafeWindowFunction $ "last_value"
2004+ <> parenthesized (renderSQL value)
2005+
2006+{- | returns value evaluated at the row that is the nth
2007+row of the window frame (counting from 1); null if no such row
2008+-}
2009+nthValue
2010+ :: Expression grp commons schemas params from (nullity ty)
2011+ -- ^ value
2012+ -> Expression grp commons schemas params from ('NotNull 'PGint4)
2013+ -- ^ nth
2014+ -> WindowFunction grp commons schemas params from ('Null ty)
2015+nthValue value nth = UnsafeWindowFunction $ "nth_value"
2016+ <> parenthesized (commaSeparated [renderSQL value, renderSQL nth])