@@ -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,564 @@ 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
75221import qualified GHC.Generics as GHC
76222
77−import Squeal.PostgreSQL.Alias
78−import Squeal.PostgreSQL.List
79223import Squeal.PostgreSQL.Render
80224import Squeal.PostgreSQL.Schema
81225
82−-- $setup
83−-- >>> import Squeal.PostgreSQL
84−
85226{-----------------------------------------
86227column expressions
87228-----------------------------------------}
88229
89230{- | `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,
231+such as in the target list of the `Squeal.PostgreSQL.Query.select` command,
92232as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
93233`Squeal.PostgreSQL.Manipulation.update`,
94−or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
234+or in search `Condition`s in a number of commands.
95235
96236The expression syntax allows the calculation of
97237values from primitive expression using arithmetic, logical,
98238and 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`.
113239-}
114240newtype Expression
115− (outer :: FromType)
116241 (commons :: FromType)
117− (grp :: Grouping)
118242 (schemas :: SchemasType)
119243 (params :: [NullityType])
244+ (grp :: Grouping)
120245 (from :: FromType)
121246 (ty :: NullityType)
122247 = UnsafeExpression { renderExpression :: ByteString }
123248 deriving (GHC.Generic,Show,Eq,Ord,NFData)
124−instance RenderSQL (Expression outer commons grp schemas params from ty) where
249+
250+instance RenderSQL (Expression commons schemas params grp from ty) where
125251 renderSQL = renderExpression
126252
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.
253+{- | A `HasParameter` constraint is used to indicate a value that is
254+supplied externally to a SQL statement.
255+`Squeal.PostgreSQL.PQ.manipulateParams`,
256+`Squeal.PostgreSQL.PQ.queryParams` and
257+`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
258+separately from the SQL command string, in which case `param`s are used to
259+refer to the out-of-line data values.
198260-}
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)
261+class KnownNat n => HasParameter
262+ (n :: Nat)
263+ (params :: [NullityType])
264+ (ty :: NullityType)
265+ | n params -> ty where
266+ -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
267+ --
268+ -- >>> let expr = parameter @1 int4 :: Expression '[] schemas '[ 'Null 'PGint4] grp from ('Null 'PGint4)
269+ -- >>> printSQL expr
270+ -- ($1 :: int4)
271+ parameter
272+ :: TypeExpression schemas ty
273+ -> Expression commons schemas params grp from ty
274+ parameter ty = UnsafeExpression $ parenthesized $
275+ "$" <> renderNat @n <+> "::"
276+ <+> renderSQL ty
277+instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
278+instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
279+ => HasParameter n (ty' : params) ty
280+
281+-- | `param` takes a `Nat` using type application and for basic types,
282+-- infers a `TypeExpression`.
283+--
284+-- >>> let expr = param @1 :: Expression commons schemas '[ 'Null 'PGint4] grp from ('Null 'PGint4)
285+-- >>> printSQL expr
286+-- ($1 :: int4)
287+param
288+ :: forall n commons schemas params from grp ty
289+ . (PGTyped schemas ty, HasParameter n params ty)
290+ => Expression commons schemas params grp from ty -- ^ param
291+param = parameter @n (pgtype @schemas)
214292
215−instance (HasUnique tab (Join outer from) row, Has col row ty)
216− => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
293+instance (HasUnique tab from row, Has col row ty)
294+ => IsLabel col (Expression commons schemas params 'Ungrouped from ty) where
217295 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))
296+instance (HasUnique tab from row, Has col row ty, column ~ (col ::: ty))
222297 => IsLabel col
223− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
298+ (Aliased (Expression commons schemas params 'Ungrouped from) column) where
224299 fromLabel = fromLabel @col `As` Alias
225−instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
300+instance (HasUnique tab from row, Has col row ty, columns ~ '[col ::: ty])
226301 => IsLabel col
227− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
302+ (NP (Aliased (Expression commons schemas params 'Ungrouped from)) columns) where
228303 fromLabel = fromLabel @col :* Nil
229304
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
305+instance (Has tab from row, Has col row ty)
306+ => IsQualified tab col (Expression commons schemas params 'Ungrouped from ty) where
232307 tab ! col = UnsafeExpression $
233308 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))
309+instance (Has tab from row, Has col row ty, column ~ (col ::: ty))
238310 => IsQualified tab col
239− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
311+ (Aliased (Expression commons schemas params 'Ungrouped from) column) where
240312 tab ! col = tab ! col `As` col
241−instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
313+instance (Has tab from row, Has col row ty, columns ~ '[col ::: ty])
242314 => IsQualified tab col
243− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
315+ (NP (Aliased (Expression commons schemas params 'Ungrouped from)) columns) where
244316 tab ! col = tab ! col :* Nil
245317
246318instance
247− ( HasUnique tab (Join outer from) row
319+ ( HasUnique tab from row
248320 , Has col row ty
249321 , GroupedBy tab col bys
250322 ) => IsLabel col
251− (Expression outer commons ('Grouped bys) schemas params from ty) where
323+ (Expression commons schemas params ('Grouped bys) from ty) where
252324 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
253325instance
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
326+ ( HasUnique tab from row
263327 , Has col row ty
264328 , GroupedBy tab col bys
265329 , column ~ (col ::: ty)
266330 ) => IsLabel col
267− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
331+ (Aliased (Expression commons schemas params ('Grouped bys) from) column) where
268332 fromLabel = fromLabel @col `As` Alias
269333instance
270− ( HasUnique tab (Join outer from) row
334+ ( HasUnique tab from row
271335 , Has col row ty
272336 , GroupedBy tab col bys
273337 , columns ~ '[col ::: ty]
274338 ) => IsLabel col
275− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
339+ (NP (Aliased (Expression commons schemas params ('Grouped bys) from)) columns) where
276340 fromLabel = fromLabel @col :* Nil
277341
278342instance
279− ( Has tab (Join outer from) row
343+ ( Has tab from row
280344 , Has col row ty
281345 , GroupedBy tab col bys
282346 ) => IsQualified tab col
283− (Expression outer commons ('Grouped bys) schemas params from ty) where
347+ (Expression commons schemas params ('Grouped bys) from ty) where
284348 tab ! col = UnsafeExpression $
285349 renderSQL tab <> "." <> renderSQL col
286350instance
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
351+ ( Has tab from row
296352 , Has col row ty
297353 , GroupedBy tab col bys
298354 , column ~ (col ::: ty)
299355 ) => IsQualified tab col
300− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
356+ (Aliased (Expression commons schemas params ('Grouped bys) from) column) where
301357 tab ! col = tab ! col `As` col
302358instance
303− ( Has tab (Join outer from) row
359+ ( Has tab from row
304360 , Has col row ty
305361 , GroupedBy tab col bys
306362 , columns ~ '[col ::: ty]
307363 ) => IsQualified tab col
308− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
364+ (NP (Aliased (Expression commons schemas params ('Grouped bys) from)) columns) where
309365 tab ! col = tab ! col :* Nil
310366
367+-- | analagous to `Nothing`
368+--
369+-- >>> printSQL null_
370+-- NULL
371+null_ :: Expression commons schemas rels grouping params ('Null ty)
372+null_ = UnsafeExpression "NULL"
373+
374+-- | analagous to `Just`
375+--
376+-- >>> printSQL $ notNull true
377+-- TRUE
378+notNull
379+ :: Expression commons schemas rels grouping params ('NotNull ty)
380+ -> Expression commons schemas rels grouping params ('Null ty)
381+notNull = UnsafeExpression . renderSQL
382+
383+-- | return the leftmost value which is not NULL
384+--
385+-- >>> printSQL $ coalesce [null_, true] false
386+-- COALESCE(NULL, TRUE, FALSE)
387+coalesce
388+ :: [Expression commons schemas params grp from ('Null ty)]
389+ -- ^ @NULL@s may be present
390+ -> Expression commons schemas params grp from ('NotNull ty)
391+ -- ^ @NULL@ is absent
392+ -> Expression commons schemas params grp from ('NotNull ty)
393+coalesce nullxs notNullx = UnsafeExpression $
394+ "COALESCE" <> parenthesized (commaSeparated
395+ ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
396+
397+-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
398+--
399+-- >>> printSQL $ fromNull true null_
400+-- COALESCE(NULL, TRUE)
401+fromNull
402+ :: Expression commons schemas params grp from ('NotNull ty)
403+ -- ^ what to convert @NULL@ to
404+ -> Expression commons schemas params grp from ('Null ty)
405+ -> Expression commons schemas params grp from ('NotNull ty)
406+fromNull notNullx nullx = coalesce [nullx] notNullx
407+
408+-- | >>> printSQL $ null_ & isNull
409+-- NULL IS NULL
410+isNull
411+ :: Expression commons schemas params grp from ('Null ty)
412+ -- ^ possibly @NULL@
413+ -> Condition commons schemas params grp from
414+isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
415+
416+-- | >>> printSQL $ null_ & isNotNull
417+-- NULL IS NOT NULL
418+isNotNull
419+ :: Expression commons schemas params grp from ('Null ty)
420+ -- ^ possibly @NULL@
421+ -> Condition commons schemas params grp from
422+isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
423+
424+-- | analagous to `maybe` using @IS NULL@
425+--
426+-- >>> printSQL $ matchNull true not_ null_
427+-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
428+matchNull
429+ :: Expression commons schemas params grp from (nullty)
430+ -- ^ what to convert @NULL@ to
431+ -> ( Expression commons schemas params grp from ('NotNull ty)
432+ -> Expression commons schemas params grp from (nullty) )
433+ -- ^ function to perform when @NULL@ is absent
434+ -> Expression commons schemas params grp from ('Null ty)
435+ -> Expression commons schemas params grp from (nullty)
436+matchNull y f x = ifThenElse (isNull x) y
437+ (f (UnsafeExpression (renderSQL x)))
438+
439+{-| right inverse to `fromNull`, if its arguments are equal then
440+`nullIf` gives @NULL@.
441+
442+>>> :set -XTypeApplications -XDataKinds
443+>>> let expr = nullIf false (param @1) :: Expression commons schemas '[ 'NotNull 'PGbool] grp from ('Null 'PGbool)
444+>>> printSQL expr
445+NULL IF (FALSE, ($1 :: bool))
446+-}
447+nullIf
448+ :: Expression commons schemas params grp from ('NotNull ty)
449+ -- ^ @NULL@ is absent
450+ -> Expression commons schemas params grp from ('NotNull ty)
451+ -- ^ @NULL@ is absent
452+ -> Expression commons schemas params grp from ('Null ty)
453+nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
454+ (renderSQL x <> ", " <> renderSQL y)
455+
456+-- | >>> printSQL $ array [null_, false, true]
457+-- ARRAY[NULL, FALSE, TRUE]
458+array
459+ :: [Expression commons schemas params grp from ty]
460+ -- ^ array elements
461+ -> Expression commons schemas params grp from (nullity ('PGvararray ty))
462+array xs = UnsafeExpression $
463+ "ARRAY[" <> commaSeparated (renderSQL <$> xs) <> "]"
464+
465+-- | >>> printSQL $ array [null_, false, true] & index 2
466+-- (ARRAY[NULL, FALSE, TRUE])[2]
467+index
468+ :: Word64 -- ^ index
469+ -> Expression commons schemas params grp from (nullity ('PGvararray ty)) -- ^ array
470+ -> Expression commons schemas params grp from (NullifyType ty)
471+index n expr = UnsafeExpression $
472+ parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
473+
311474instance (KnownSymbol label, label `In` labels) => IsPGlabel label
312− (Expression outer commons grp schemas params from (null ('PGenum labels))) where
475+ (Expression commons schemas params grp from (nullity ('PGenum labels))) where
313476 label = UnsafeExpression $ renderSQL (PGlabel @label)
314477
478+-- | A row constructor is an expression that builds a row value
479+-- (also called a composite value) using values for its member fields.
480+--
481+-- >>> :{
482+-- type Complex = 'PGcomposite
483+-- '[ "real" ::: 'NotNull 'PGfloat8
484+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
485+-- :}
486+--
487+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression commons schemas from grp params ('NotNull Complex)
488+-- >>> printSQL i
489+-- ROW(0, 1)
490+row
491+ :: SListI row
492+ => NP (Aliased (Expression commons schemas params grp from)) row
493+ -- ^ zero or more expressions for the row field values
494+ -> Expression commons schemas params grp from (nullity ('PGcomposite row))
495+row exprs = UnsafeExpression $ "ROW" <> parenthesized
496+ (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
497+
498+-- | >>> :{
499+-- type Complex = 'PGcomposite
500+-- '[ "real" ::: 'NotNull 'PGfloat8
501+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
502+-- type Schema = '["complex" ::: 'Typedef Complex]
503+-- :}
504+--
505+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression '[] (Public Schema) from grp params ('NotNull Complex)
506+-- >>> printSQL $ i & field #complex #imaginary
507+-- (ROW(0, 1)::"complex")."imaginary"
508+field
509+ :: ( Has sch schemas schema
510+ , Has tydef schema ('Typedef ('PGcomposite row))
511+ , Has field row ty)
512+ => QualifiedAlias sch tydef -- ^ row type
513+ -> Alias field -- ^ field name
514+ -> Expression commons schemas params grp from ('NotNull ('PGcomposite row))
515+ -> Expression commons schemas params grp from ty
516+field td fld expr = UnsafeExpression $
517+ parenthesized (renderSQL expr <> "::" <> renderSQL td)
518+ <> "." <> renderSQL fld
519+
520+instance Semigroup
521+ (Expression commons schemas params grp from (nullity ('PGvararray ty))) where
522+ (<>) = unsafeBinaryOp "||"
523+
524+instance Monoid
525+ (Expression commons schemas params grp from (nullity ('PGvararray ty))) where
526+ mempty = array []
527+ mappend = (<>)
528+
529+-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression commons schemas '[ 'NotNull 'PGtimestamptz] grp from ('NotNull 'PGtimestamptz)
530+-- >>> printSQL expr
531+-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
532+greatest
533+ :: Expression commons schemas params grp from (nullty)
534+ -- ^ needs at least 1 argument
535+ -> [Expression commons schemas params grp from (nullty)]
536+ -- ^ or more
537+ -> Expression commons schemas params grp from (nullty)
538+greatest x xs = UnsafeExpression $ "GREATEST("
539+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
540+
541+-- | >>> printSQL $ least currentTimestamp [null_]
542+-- LEAST(CURRENT_TIMESTAMP, NULL)
543+least
544+ :: Expression commons schemas params grp from (nullty)
545+ -- ^ needs at least 1 argument
546+ -> [Expression commons schemas params grp from (nullty)]
547+ -- ^ or more
548+ -> Expression commons schemas params grp from (nullty)
549+least x xs = UnsafeExpression $ "LEAST("
550+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
551+
315552-- | >>> printSQL $ unsafeBinaryOp "OR" true false
316553-- (TRUE OR FALSE)
317−unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
554+unsafeBinaryOp
555+ :: ByteString
556+ -- ^ operator
557+ -> Expression commons schemas params grp from (ty0)
558+ -> Expression commons schemas params grp from (ty1)
559+ -> Expression commons schemas params grp from (ty2)
318560unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
319561 renderSQL x <+> op <+> renderSQL y
320562
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
563+-- | >>> printSQL $ unsafeUnaryOp "NOT" true
329564-- (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
565+unsafeUnaryOp
566+ :: ByteString
567+ -- ^ operator
568+ -> Expression commons schemas params grp from (ty0)
569+ -> Expression commons schemas params grp from (ty1)
570+unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
571+ op <+> renderSQL x
351572
352573-- | >>> printSQL $ unsafeFunction "f" true
353574-- f(TRUE)
354−unsafeFunction :: ByteString -> x --> y
575+unsafeFunction
576+ :: ByteString
577+ -- ^ function
578+ -> Expression commons schemas params grp from (xty)
579+ -> Expression commons schemas params grp from (yty)
355580unsafeFunction fun x = UnsafeExpression $
356581 fun <> parenthesized (renderSQL x)
357582
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
583+-- | Helper for defining variadic functions.
584+unsafeVariadicFunction
585+ :: SListI elems
586+ => ByteString
587+ -- ^ function
588+ -> NP (Expression commons schemas params grp from) elems
589+ -> Expression commons schemas params grp from ret
590+unsafeVariadicFunction fun x = UnsafeExpression $
591+ fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderSQL) x)))
377592
378593instance ty `In` PGNum
379− => Num (Expression outer commons grp schemas params from (null ty)) where
594+ => Num (Expression commons schemas params grp from (nullity ty)) where
380595 (+) = unsafeBinaryOp "+"
381596 (-) = unsafeBinaryOp "-"
382597 (*) = unsafeBinaryOp "*"
@@ -388,17 +603,12 @@ instance ty `In` PGNum
388603 . show
389604
390605instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
391− (Expression outer commons grp schemas params from (null ty)) where
606+ (Expression commons schemas params grp from (nullity ty)) where
392607 (/) = unsafeBinaryOp "/"
393− fromRational
394− = UnsafeExpression
395− . fromString
396− . ($ "")
397− . showFFloat Nothing
398− . fromRat @Double
608+ fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
399609
400610instance (ty `In` PGNum, ty `In` PGFloating) => Floating
401− (Expression outer commons grp schemas params from (null ty)) where
611+ (Expression commons schemas params grp from (nullity ty)) where
402612 pi = UnsafeExpression "pi()"
403613 exp = unsafeFunction "exp"
404614 log = unsafeFunction "ln"
@@ -419,54 +629,1377 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
419629 acosh x = log (x + sqrt (x*x - 1))
420630 atanh x = log ((1 + x) / (1 - x)) / 2
421631
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)
632+-- | >>> :{
633+-- let
634+-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
635+-- expression = atan2_ pi 2
636+-- in printSQL expression
637+-- :}
638+-- atan2(pi(), 2)
639+atan2_
640+ :: float `In` PGFloating
641+ => Expression commons schemas params grp from (nullity float)
642+ -- ^ numerator
643+ -> Expression commons schemas params grp from (nullity float)
644+ -- ^ denominator
645+ -> Expression commons schemas params grp from (nullity float)
646+atan2_ y x = UnsafeExpression $
647+ "atan2(" <> renderSQL y <> ", " <> renderSQL x <> ")"
648+
649+-- When a `cast` is applied to an `Expression` of a known type, it
650+-- represents a run-time type conversion. The cast will succeed only if a
651+-- suitable type conversion operation has been defined.
652+--
653+-- | >>> printSQL $ true & cast int4
654+-- (TRUE :: int4)
655+cast
656+ :: TypeExpression schemas ty1
657+ -- ^ type to cast as
658+ -> Expression commons schemas params grp from ty0
659+ -- ^ value to convert
660+ -> Expression commons schemas params grp from ty1
661+cast ty x = UnsafeExpression $ parenthesized $
662+ renderSQL x <+> "::" <+> renderSQL ty
663+
664+-- | integer division, truncates the result
665+--
666+-- >>> :{
667+-- let
668+-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
669+-- expression = 5 `quot_` 2
670+-- in printSQL expression
671+-- :}
672+-- (5 / 2)
673+quot_
674+ :: int `In` PGIntegral
675+ => Expression commons schemas params grp from (nullity int)
676+ -- ^ numerator
677+ -> Expression commons schemas params grp from (nullity int)
678+ -- ^ denominator
679+ -> Expression commons schemas params grp from (nullity int)
680+quot_ = unsafeBinaryOp "/"
681+
682+-- | remainder upon integer division
683+--
684+-- >>> :{
685+-- let
686+-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
687+-- expression = 5 `rem_` 2
688+-- in printSQL expression
689+-- :}
690+-- (5 % 2)
691+rem_
692+ :: int `In` PGIntegral
693+ => Expression commons schemas params grp from (nullity int)
694+ -- ^ numerator
695+ -> Expression commons schemas params grp from (nullity int)
696+ -- ^ denominator
697+ -> Expression commons schemas params grp from (nullity int)
698+rem_ = unsafeBinaryOp "%"
699+
700+-- | >>> :{
701+-- let
702+-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
703+-- expression = trunc pi
704+-- in printSQL expression
705+-- :}
706+-- trunc(pi())
707+trunc
708+ :: frac `In` PGFloating
709+ => Expression commons schemas params grp from (nullity frac)
710+ -- ^ fractional number
711+ -> Expression commons schemas params grp from (nullity frac)
712+trunc = unsafeFunction "trunc"
713+
714+-- | >>> :{
715+-- let
716+-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
717+-- expression = round_ pi
718+-- in printSQL expression
719+-- :}
720+-- round(pi())
721+round_
722+ :: frac `In` PGFloating
723+ => Expression commons schemas params grp from (nullity frac)
724+ -- ^ fractional number
725+ -> Expression commons schemas params grp from (nullity frac)
726+round_ = unsafeFunction "round"
727+
728+-- | >>> :{
729+-- let
730+-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
731+-- expression = ceiling_ pi
732+-- in printSQL expression
733+-- :}
734+-- ceiling(pi())
735+ceiling_
736+ :: frac `In` PGFloating
737+ => Expression commons schemas params grp from (nullity frac)
738+ -- ^ fractional number
739+ -> Expression commons schemas params grp from (nullity frac)
740+ceiling_ = unsafeFunction "ceiling"
741+
742+-- | A `Condition` is an `Expression`, which can evaluate
743+-- to `true`, `false` or `null_`. This is because SQL uses
744+-- a three valued logic.
745+type Condition commons schemas params grp from =
746+ Expression commons schemas params grp from ('Null 'PGbool)
747+
748+-- | >>> printSQL true
749+-- TRUE
750+true :: Expression commons schemas params grp from (nullity 'PGbool)
751+true = UnsafeExpression "TRUE"
752+
753+-- | >>> printSQL false
754+-- FALSE
755+false :: Expression commons schemas params grp from (nullity 'PGbool)
756+false = UnsafeExpression "FALSE"
757+
758+-- | >>> printSQL $ not_ true
759+-- (NOT TRUE)
760+not_
761+ :: Expression commons schemas params grp from (nullity 'PGbool)
762+ -> Expression commons schemas params grp from (nullity 'PGbool)
763+not_ = unsafeUnaryOp "NOT"
764+
765+-- | >>> printSQL $ true .&& false
766+-- (TRUE AND FALSE)
767+(.&&)
768+ :: Expression commons schemas params grp from (nullity 'PGbool)
769+ -> Expression commons schemas params grp from (nullity 'PGbool)
770+ -> Expression commons schemas params grp from (nullity 'PGbool)
771+infixr 3 .&&
772+(.&&) = unsafeBinaryOp "AND"
773+
774+-- | >>> printSQL $ true .|| false
775+-- (TRUE OR FALSE)
776+(.||)
777+ :: Expression commons schemas params grp from (nullity 'PGbool)
778+ -> Expression commons schemas params grp from (nullity 'PGbool)
779+ -> Expression commons schemas params grp from (nullity 'PGbool)
780+infixr 2 .||
781+(.||) = unsafeBinaryOp "OR"
782+
783+-- | >>> :{
784+-- let
785+-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
786+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
787+-- in printSQL expression
788+-- :}
789+-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
790+caseWhenThenElse
791+ :: [ ( Condition commons schemas params grp from
792+ , Expression commons schemas params grp from ty
793+ ) ]
794+ -- ^ whens and thens
795+ -> Expression commons schemas params grp from ty
796+ -- ^ else
797+ -> Expression commons schemas params grp from ty
798+caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
799+ [ "CASE"
800+ , mconcat
801+ [ mconcat
802+ [ " WHEN ", renderSQL when_
803+ , " THEN ", renderSQL then_
804+ ]
805+ | (when_,then_) <- whenThens
806+ ]
807+ , " ELSE ", renderSQL else_
808+ , " END"
809+ ]
810+
811+-- | >>> :{
812+-- let
813+-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
814+-- expression = ifThenElse true 1 0
815+-- in printSQL expression
816+-- :}
817+-- CASE WHEN TRUE THEN 1 ELSE 0 END
818+ifThenElse
819+ :: Condition commons schemas params grp from
820+ -> Expression commons schemas params grp from ty -- ^ then
821+ -> Expression commons schemas params grp from ty -- ^ else
822+ -> Expression commons schemas params grp from ty
823+ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
824+
825+-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
826+-- will produce @NULL@s if one of their arguments is @NULL@.
827+--
828+-- >>> printSQL $ true .== null_
829+-- (TRUE = NULL)
830+(.==)
831+ :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
832+ -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
833+ -> Condition commons schemas params grp from
834+(.==) = unsafeBinaryOp "="
835+infix 4 .==
836+
837+-- | >>> printSQL $ true ./= null_
838+-- (TRUE <> NULL)
839+(./=)
840+ :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
841+ -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
842+ -> Condition commons schemas params grp from
843+(./=) = unsafeBinaryOp "<>"
844+infix 4 ./=
845+
846+-- | >>> printSQL $ true .>= null_
847+-- (TRUE >= NULL)
848+(.>=)
849+ :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
850+ -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
851+ -> Condition commons schemas params grp from
852+(.>=) = unsafeBinaryOp ">="
853+infix 4 .>=
854+
855+-- | >>> printSQL $ true .< null_
856+-- (TRUE < NULL)
857+(.<)
858+ :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
859+ -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
860+ -> Condition commons schemas params grp from
861+(.<) = unsafeBinaryOp "<"
862+infix 4 .<
863+
864+-- | >>> printSQL $ true .<= null_
865+-- (TRUE <= NULL)
866+(.<=)
867+ :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
868+ -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
869+ -> Condition commons schemas params grp from
870+(.<=) = unsafeBinaryOp "<="
871+infix 4 .<=
872+
873+-- | >>> printSQL $ true .> null_
874+-- (TRUE > NULL)
875+(.>)
876+ :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
877+ -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
878+ -> Condition commons schemas params grp from
879+(.>) = unsafeBinaryOp ">"
880+infix 4 .>
881+
882+-- | >>> printSQL currentDate
883+-- CURRENT_DATE
884+currentDate
885+ :: Expression commons schemas params grp from (nullity 'PGdate)
886+currentDate = UnsafeExpression "CURRENT_DATE"
887+
888+-- | >>> printSQL currentTime
889+-- CURRENT_TIME
890+currentTime
891+ :: Expression commons schemas params grp from (nullity 'PGtimetz)
892+currentTime = UnsafeExpression "CURRENT_TIME"
893+
894+-- | >>> printSQL currentTimestamp
895+-- CURRENT_TIMESTAMP
896+currentTimestamp
897+ :: Expression commons schemas params grp from (nullity 'PGtimestamptz)
898+currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
899+
900+-- | >>> printSQL localTime
901+-- LOCALTIME
902+localTime
903+ :: Expression commons schemas params grp from (nullity 'PGtime)
904+localTime = UnsafeExpression "LOCALTIME"
905+
906+-- | >>> printSQL localTimestamp
907+-- LOCALTIMESTAMP
908+localTimestamp
909+ :: Expression commons schemas params grp from (nullity 'PGtimestamp)
910+localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
911+
912+{-----------------------------------------
913+text
914+-----------------------------------------}
438915
439916instance IsString
440− (Expression outer commons grp schemas params from (null 'PGtext)) where
917+ (Expression commons schemas params grp from (nullity 'PGtext)) where
441918 fromString str = UnsafeExpression $
442919 "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) <> "\'"
920+ where
921+ escape = \case
922+ '\NUL' -> "\\0"
923+ '\'' -> "''"
924+ '"' -> "\\\""
925+ '\b' -> "\\b"
926+ '\n' -> "\\n"
927+ '\r' -> "\\r"
928+ '\t' -> "\\t"
929+ '\\' -> "\\\\"
930+ c -> [c]
451931
452932instance 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
933+ (Expression commons schemas params grp from (nullity 'PGtext)) where
463934 (<>) = unsafeBinaryOp "||"
464935
465936instance 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
937+ (Expression commons schemas params grp from (nullity 'PGtext)) where
471938 mempty = fromString ""
472939 mappend = (<>)
940+
941+-- | >>> printSQL $ lower "ARRRGGG"
942+-- lower(E'ARRRGGG')
943+lower
944+ :: Expression commons schemas params grp from (nullity 'PGtext)
945+ -- ^ string to lower case
946+ -> Expression commons schemas params grp from (nullity 'PGtext)
947+lower = unsafeFunction "lower"
948+
949+-- | >>> printSQL $ upper "eeee"
950+-- upper(E'eeee')
951+upper
952+ :: Expression commons schemas params grp from (nullity 'PGtext)
953+ -- ^ string to upper case
954+ -> Expression commons schemas params grp from (nullity 'PGtext)
955+upper = unsafeFunction "upper"
956+
957+-- | >>> printSQL $ charLength "four"
958+-- char_length(E'four')
959+charLength
960+ :: Expression commons schemas params grp from (nullity 'PGtext)
961+ -- ^ string to measure
962+ -> Expression commons schemas params grp from (nullity 'PGint4)
963+charLength = unsafeFunction "char_length"
964+
965+-- | The `like` expression returns true if the @string@ matches
966+-- the supplied @pattern@. If @pattern@ does not contain percent signs
967+-- or underscores, then the pattern only represents the string itself;
968+-- in that case `like` acts like the equals operator. An underscore (_)
969+-- in pattern stands for (matches) any single character; a percent sign (%)
970+-- matches any sequence of zero or more characters.
971+--
972+-- >>> printSQL $ "abc" `like` "a%"
973+-- (E'abc' LIKE E'a%')
974+like
975+ :: Expression commons schemas params grp from (nullity 'PGtext)
976+ -- ^ string
977+ -> Expression commons schemas params grp from (nullity 'PGtext)
978+ -- ^ pattern
979+ -> Expression commons schemas params grp from (nullity 'PGbool)
980+like = unsafeBinaryOp "LIKE"
981+
982+-- | The key word ILIKE can be used instead of LIKE to make the
983+-- match case-insensitive according to the active locale.
984+--
985+-- >>> printSQL $ "abc" `ilike` "a%"
986+-- (E'abc' ILIKE E'a%')
987+ilike
988+ :: Expression commons schemas params grp from (nullity 'PGtext)
989+ -- ^ string
990+ -> Expression commons schemas params grp from (nullity 'PGtext)
991+ -- ^ pattern
992+ -> Expression commons schemas params grp from (nullity 'PGbool)
993+ilike = unsafeBinaryOp "ILIKE"
994+
995+{-----------------------------------------
996+ -- json and jsonb support
997+
998+See https://www.postgresql.org/docs/10/static/functions-json.html -- most
999+comments lifted directly from this page.
1000+
1001+Table 9.44: json and jsonb operators
1002+-----------------------------------------}
1003+
1004+-- | Get JSON value (object field or array element) at a key.
1005+(.->)
1006+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1007+ => Expression commons schemas params grp from (nullity json)
1008+ -> Expression commons schemas params grp from (nullity key)
1009+ -> Expression commons schemas params grp from ('Null json)
1010+infixl 8 .->
1011+(.->) = unsafeBinaryOp "->"
1012+
1013+-- | Get JSON value (object field or array element) at a key, as text.
1014+(.->>)
1015+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1016+ => Expression commons schemas params grp from (nullity json)
1017+ -> Expression commons schemas params grp from (nullity key)
1018+ -> Expression commons schemas params grp from ('Null 'PGtext)
1019+infixl 8 .->>
1020+(.->>) = unsafeBinaryOp "->>"
1021+
1022+-- | Get JSON value at a specified path.
1023+(.#>)
1024+ :: (json `In` PGJsonType, PGTextArray "(.#>)" path)
1025+ => Expression commons schemas params grp from (nullity json)
1026+ -> Expression commons schemas params grp from (nullity path)
1027+ -> Expression commons schemas params grp from ('Null json)
1028+infixl 8 .#>
1029+(.#>) = unsafeBinaryOp "#>"
1030+
1031+-- | Get JSON value at a specified path as text.
1032+(.#>>)
1033+ :: (json `In` PGJsonType, PGTextArray "(.#>>)" path)
1034+ => Expression commons schemas params grp from (nullity json)
1035+ -> Expression commons schemas params grp from (nullity path)
1036+ -> Expression commons schemas params grp from ('Null 'PGtext)
1037+infixl 8 .#>>
1038+(.#>>) = unsafeBinaryOp "#>>"
1039+
1040+-- Additional jsonb operators
1041+
1042+-- | Does the left JSON value contain the right JSON path/value entries at the
1043+-- top level?
1044+(.@>)
1045+ :: Expression commons schemas params grp from (nullity 'PGjsonb)
1046+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1047+ -> Condition commons schemas params grp from
1048+infixl 9 .@>
1049+(.@>) = unsafeBinaryOp "@>"
1050+
1051+-- | Are the left JSON path/value entries contained at the top level within the
1052+-- right JSON value?
1053+(.<@)
1054+ :: Expression commons schemas params grp from (nullity 'PGjsonb)
1055+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1056+ -> Condition commons schemas params grp from
1057+infixl 9 .<@
1058+(.<@) = unsafeBinaryOp "<@"
1059+
1060+-- | Does the string exist as a top-level key within the JSON value?
1061+(.?)
1062+ :: Expression commons schemas params grp from (nullity 'PGjsonb)
1063+ -> Expression commons schemas params grp from (nullity 'PGtext)
1064+ -> Condition commons schemas params grp from
1065+infixl 9 .?
1066+(.?) = unsafeBinaryOp "?"
1067+
1068+-- | Do any of these array strings exist as top-level keys?
1069+(.?|)
1070+ :: Expression commons schemas params grp from (nullity 'PGjsonb)
1071+ -> Expression commons schemas params grp from (nullity ('PGvararray ('NotNull 'PGtext)))
1072+ -> Condition commons schemas params grp from
1073+infixl 9 .?|
1074+(.?|) = unsafeBinaryOp "?|"
1075+
1076+-- | Do all of these array strings exist as top-level keys?
1077+(.?&)
1078+ :: Expression commons schemas params grp from (nullity 'PGjsonb)
1079+ -> Expression commons schemas params grp from (nullity ('PGvararray ('NotNull 'PGtext)))
1080+ -> Condition commons schemas params grp from
1081+infixl 9 .?&
1082+(.?&) = unsafeBinaryOp "?&"
1083+
1084+-- | Concatenate two jsonb values into a new jsonb value.
1085+instance
1086+ Semigroup (Expression commons schemas from grouping param (nullity 'PGjsonb)) where
1087+ (<>) = unsafeBinaryOp "||"
1088+
1089+-- | Delete a key or keys from a JSON object, or remove an array element.
1090+--
1091+-- If the right operand is..
1092+--
1093+-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1094+-- are matched based on their key value.
1095+--
1096+-- @ text[] @: Delete multiple key/value pairs or string elements
1097+-- from left operand. Key/value pairs are matched based on their key value.
1098+--
1099+-- @ integer @: Delete the array element with specified index (Negative integers
1100+-- count from the end). Throws an error if top level container is not an array.
1101+(.-.)
1102+ :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1103+ => Expression commons schemas params grp from (nullity 'PGjsonb)
1104+ -> Expression commons schemas params grp from (nullity key)
1105+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1106+infixl 6 .-.
1107+(.-.) = unsafeBinaryOp "-"
1108+
1109+-- | Delete the field or element with specified path (for JSON arrays, negative
1110+-- integers count from the end)
1111+(#-.)
1112+ :: PGTextArray "(#-.)" arrayty
1113+ => Expression commons schemas params grp from (nullity 'PGjsonb)
1114+ -> Expression commons schemas params grp from (nullity arrayty)
1115+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1116+infixl 6 #-.
1117+(#-.) = unsafeBinaryOp "#-"
1118+
1119+{-----------------------------------------
1120+Table 9.45: JSON creation functions
1121+-----------------------------------------}
1122+
1123+-- | Literal binary JSON
1124+jsonbLit
1125+ :: JSON.ToJSON x
1126+ => x -> Expression commons schemas params grp from (nullity 'PGjsonb)
1127+jsonbLit = cast jsonb . UnsafeExpression
1128+ . singleQuotedUtf8 . toStrict . JSON.encode
1129+
1130+-- | Literal JSON
1131+jsonLit
1132+ :: JSON.ToJSON x
1133+ => x -> Expression commons schemas params grp from (nullity 'PGjson)
1134+jsonLit = cast json . UnsafeExpression
1135+ . singleQuotedUtf8 . toStrict . JSON.encode
1136+
1137+-- | Returns the value as json. Arrays and composites are converted
1138+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1139+-- type to json, the cast function will be used to perform the conversion;
1140+-- otherwise, a scalar value is produced. For any scalar type other than a
1141+-- number, a Boolean, or a null value, the text representation will be used, in
1142+-- such a fashion that it is a valid json value.
1143+toJson
1144+ :: Expression commons schemas params grp from (nullity ty)
1145+ -> Expression commons schemas params grp from (nullity 'PGjson)
1146+toJson = unsafeFunction "to_json"
1147+
1148+-- | Returns the value as jsonb. Arrays and composites are converted
1149+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1150+-- type to json, the cast function will be used to perform the conversion;
1151+-- otherwise, a scalar value is produced. For any scalar type other than a
1152+-- number, a Boolean, or a null value, the text representation will be used, in
1153+-- such a fashion that it is a valid jsonb value.
1154+toJsonb
1155+ :: Expression commons schemas params grp from (nullity ty)
1156+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1157+toJsonb = unsafeFunction "to_jsonb"
1158+
1159+-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1160+-- becomes a JSON array of arrays.
1161+arrayToJson
1162+ :: PGArray "arrayToJson" arr
1163+ => Expression commons schemas params grp from (nullity arr)
1164+ -> Expression commons schemas params grp from (nullity 'PGjson)
1165+arrayToJson = unsafeFunction "array_to_json"
1166+
1167+-- | Returns the row as a JSON object.
1168+rowToJson
1169+ :: Expression commons schemas params grp from (nullity ('PGcomposite ty))
1170+ -> Expression commons schemas params grp from (nullity 'PGjson)
1171+rowToJson = unsafeFunction "row_to_json"
1172+
1173+-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1174+-- argument list.
1175+jsonBuildArray
1176+ :: SListI elems
1177+ => NP (Expression commons schemas params grp from) elems
1178+ -> Expression commons schemas params grp from (nullity 'PGjson)
1179+jsonBuildArray = unsafeVariadicFunction "json_build_array"
1180+
1181+-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1182+-- variadic argument list.
1183+jsonbBuildArray
1184+ :: SListI elems
1185+ => NP (Expression commons schemas params grp from) elems
1186+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1187+jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1188+
1189+unsafeRowFunction
1190+ :: All Top elems
1191+ => NP (Aliased (Expression commons schemas params grp from)) elems
1192+ -> [ByteString]
1193+unsafeRowFunction =
1194+ (`appEndo` []) . hcfoldMap (Proxy :: Proxy Top)
1195+ (\(col `As` name) -> Endo $ \xs ->
1196+ renderAliasString name : renderSQL col : xs)
1197+ where
1198+ renderAliasString :: KnownSymbol alias => Alias alias -> ByteString
1199+ renderAliasString = singleQuotedText . fromString . symbolVal
1200+
1201+-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1202+-- argument list. The elements of the argument list must alternate between text
1203+-- and values.
1204+jsonBuildObject
1205+ :: All Top elems
1206+ => NP (Aliased (Expression commons schemas params grp from)) elems
1207+ -> Expression commons schemas params grp from (nullity 'PGjson)
1208+jsonBuildObject
1209+ = unsafeFunction "json_build_object"
1210+ . UnsafeExpression
1211+ . commaSeparated
1212+ . unsafeRowFunction
1213+
1214+-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1215+-- variadic argument list. The elements of the argument list must alternate
1216+-- between text and values.
1217+jsonbBuildObject
1218+ :: All Top elems
1219+ => NP (Aliased (Expression commons schemas params grp from)) elems
1220+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1221+jsonbBuildObject
1222+ = unsafeFunction "jsonb_build_object"
1223+ . UnsafeExpression
1224+ . commaSeparated
1225+ . unsafeRowFunction
1226+
1227+-- | Builds a JSON object out of a text array. The array must have either
1228+-- exactly one dimension with an even number of members, in which case they are
1229+-- taken as alternating key/value pairs, or two dimensions such that each inner
1230+-- array has exactly two elements, which are taken as a key/value pair.
1231+jsonObject
1232+ :: PGArrayOf "jsonObject" arr ('NotNull 'PGtext)
1233+ => Expression commons schemas params grp from (nullity arr)
1234+ -> Expression commons schemas params grp from (nullity 'PGjson)
1235+jsonObject = unsafeFunction "json_object"
1236+
1237+-- | Builds a binary JSON object out of a text array. The array must have either
1238+-- exactly one dimension with an even number of members, in which case they are
1239+-- taken as alternating key/value pairs, or two dimensions such that each inner
1240+-- array has exactly two elements, which are taken as a key/value pair.
1241+jsonbObject
1242+ :: PGArrayOf "jsonbObject" arr ('NotNull 'PGtext)
1243+ => Expression commons schemas params grp from (nullity arr)
1244+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1245+jsonbObject = unsafeFunction "jsonb_object"
1246+
1247+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1248+-- keys and one for values, that are zipped pairwise to create a JSON object.
1249+jsonZipObject
1250+ :: ( PGArrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1251+ , PGArrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
1252+ => Expression commons schemas params grp from (nullity keysArray)
1253+ -> Expression commons schemas params grp from (nullity valuesArray)
1254+ -> Expression commons schemas params grp from (nullity 'PGjson)
1255+jsonZipObject ks vs =
1256+ unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1257+
1258+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1259+-- keys and one for values, that are zipped pairwise to create a binary JSON
1260+-- object.
1261+jsonbZipObject
1262+ :: ( PGArrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1263+ , PGArrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
1264+ => Expression commons schemas params grp from (nullity keysArray)
1265+ -> Expression commons schemas params grp from (nullity valuesArray)
1266+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1267+jsonbZipObject ks vs =
1268+ unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1269+
1270+{-----------------------------------------
1271+Table 9.46: JSON processing functions
1272+-----------------------------------------}
1273+
1274+-- | Returns the number of elements in the outermost JSON array.
1275+jsonArrayLength
1276+ :: Expression commons schemas params grp from (nullity 'PGjson)
1277+ -> Expression commons schemas params grp from (nullity 'PGint4)
1278+jsonArrayLength = unsafeFunction "json_array_length"
1279+
1280+-- | Returns the number of elements in the outermost binary JSON array.
1281+jsonbArrayLength
1282+ :: Expression commons schemas params grp from (nullity 'PGjsonb)
1283+ -> Expression commons schemas params grp from (nullity 'PGint4)
1284+jsonbArrayLength = unsafeFunction "jsonb_array_length"
1285+
1286+-- | Returns JSON value pointed to by the given path (equivalent to #>
1287+-- operator).
1288+jsonExtractPath
1289+ :: SListI elems
1290+ => Expression commons schemas params grp from (nullity 'PGjson)
1291+ -> NP (Expression commons schemas params grp from) elems
1292+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1293+jsonExtractPath x xs =
1294+ unsafeVariadicFunction "json_extract_path" (x :* xs)
1295+
1296+-- | Returns JSON value pointed to by the given path (equivalent to #>
1297+-- operator).
1298+jsonbExtractPath
1299+ :: SListI elems
1300+ => Expression commons schemas params grp from (nullity 'PGjsonb)
1301+ -> NP (Expression commons schemas params grp from) elems
1302+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1303+jsonbExtractPath x xs =
1304+ unsafeVariadicFunction "jsonb_extract_path" (x :* xs)
1305+
1306+-- | Returns JSON value pointed to by the given path (equivalent to #>
1307+-- operator), as text.
1308+jsonExtractPathAsText
1309+ :: SListI elems
1310+ => Expression commons schemas params grp from (nullity 'PGjson)
1311+ -> NP (Expression commons schemas params grp from) elems
1312+ -> Expression commons schemas params grp from (nullity 'PGjson)
1313+jsonExtractPathAsText x xs =
1314+ unsafeVariadicFunction "json_extract_path_text" (x :* xs)
1315+
1316+-- | Returns JSON value pointed to by the given path (equivalent to #>
1317+-- operator), as text.
1318+jsonbExtractPathAsText
1319+ :: SListI elems
1320+ => Expression commons schemas params grp from (nullity 'PGjsonb)
1321+ -> NP (Expression commons schemas params grp from) elems
1322+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1323+jsonbExtractPathAsText x xs =
1324+ unsafeVariadicFunction "jsonb_extract_path_text" (x :* xs)
1325+
1326+-- | Returns the type of the outermost JSON value as a text string. Possible
1327+-- types are object, array, string, number, boolean, and null.
1328+jsonTypeof
1329+ :: Expression commons schemas params grp from (nullity 'PGjson)
1330+ -> Expression commons schemas params grp from (nullity 'PGtext)
1331+jsonTypeof = unsafeFunction "json_typeof"
1332+
1333+-- | Returns the type of the outermost binary JSON value as a text string.
1334+-- Possible types are object, array, string, number, boolean, and null.
1335+jsonbTypeof
1336+ :: Expression commons schemas params grp from (nullity 'PGjsonb)
1337+ -> Expression commons schemas params grp from (nullity 'PGtext)
1338+jsonbTypeof = unsafeFunction "jsonb_typeof"
1339+
1340+-- | Returns its argument with all object fields that have null values omitted.
1341+-- Other null values are untouched.
1342+jsonStripNulls
1343+ :: Expression commons schemas params grp from (nullity 'PGjson)
1344+ -> Expression commons schemas params grp from (nullity 'PGjson)
1345+jsonStripNulls = unsafeFunction "json_strip_nulls"
1346+
1347+-- | Returns its argument with all object fields that have null values omitted.
1348+-- Other null values are untouched.
1349+jsonbStripNulls
1350+ :: Expression commons schemas params grp from (nullity 'PGjsonb)
1351+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1352+jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1353+
1354+-- | @ jsonbSet target path new_value create_missing @
1355+--
1356+-- Returns target with the section designated by path replaced by new_value,
1357+-- or with new_value added if create_missing is true ( default is true) and the
1358+-- item designated by path does not exist. As with the path orientated
1359+-- operators, negative integers that appear in path count from the end of JSON
1360+-- arrays.
1361+jsonbSet
1362+ :: PGTextArray "jsonbSet" arr
1363+ => Expression commons schemas params grp from (nullity 'PGjsonb)
1364+ -> Expression commons schemas params grp from (nullity arr)
1365+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1366+ -> Maybe (Expression commons schemas params grp from (nullity 'PGbool))
1367+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1368+jsonbSet tgt path val createMissing = case createMissing of
1369+ Just m -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* m :* Nil)
1370+ Nothing -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* Nil)
1371+
1372+-- | @ jsonbInsert target path new_value insert_after @
1373+--
1374+-- Returns target with new_value inserted. If target section designated by
1375+-- path is in a JSONB array, new_value will be inserted before target or after
1376+-- if insert_after is true (default is false). If target section designated by
1377+-- path is in JSONB object, new_value will be inserted only if target does not
1378+-- exist. As with the path orientated operators, negative integers that appear
1379+-- in path count from the end of JSON arrays.
1380+jsonbInsert
1381+ :: PGTextArray "jsonbInsert" arr
1382+ => Expression commons schemas params grp from (nullity 'PGjsonb)
1383+ -> Expression commons schemas params grp from (nullity arr)
1384+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1385+ -> Maybe (Expression commons schemas params grp from (nullity 'PGbool))
1386+ -> Expression commons schemas params grp from (nullity 'PGjsonb)
1387+jsonbInsert tgt path val insertAfter = case insertAfter of
1388+ Just i -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1389+ Nothing -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* Nil)
1390+
1391+-- | Returns its argument as indented JSON text.
1392+jsonbPretty
1393+ :: Expression commons schemas params grp from (nullity 'PGjsonb)
1394+ -> Expression commons schemas params grp from (nullity 'PGtext)
1395+jsonbPretty = unsafeFunction "jsonb_pretty"
1396+
1397+{-----------------------------------------
1398+aggregation
1399+-----------------------------------------}
1400+
1401+-- | escape hatch to define aggregate functions
1402+unsafeAggregate
1403+ :: ByteString -- ^ aggregate function
1404+ -> Expression commons schemas from 'Ungrouped params (xty)
1405+ -> Expression commons schemas from ('Grouped bys) params (yty)
1406+unsafeAggregate fun x = UnsafeExpression $ mconcat
1407+ [fun, "(", renderSQL x, ")"]
1408+
1409+-- | escape hatch to define aggregate functions over distinct values
1410+unsafeAggregateDistinct
1411+ :: ByteString -- ^ aggregate function
1412+ -> Expression commons schemas from 'Ungrouped params (xty)
1413+ -> Expression commons schemas from ('Grouped bys) params (yty)
1414+unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
1415+ [fun, "(DISTINCT ", renderSQL x, ")"]
1416+
1417+-- | >>> :{
1418+-- let
1419+-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Null 'PGnumeric)
1420+-- expression = sum_ #col
1421+-- in printSQL expression
1422+-- :}
1423+-- sum("col")
1424+sum_
1425+ :: ty `In` PGNum
1426+ => Expression commons schemas from 'Ungrouped params (nullity ty)
1427+ -- ^ what to sum
1428+ -> Expression commons schemas from ('Grouped bys) params (nullity ty)
1429+sum_ = unsafeAggregate "sum"
1430+
1431+-- | >>> :{
1432+-- let
1433+-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: nullity 'PGnumeric]] (nullity 'PGnumeric)
1434+-- expression = sumDistinct #col
1435+-- in printSQL expression
1436+-- :}
1437+-- sum(DISTINCT "col")
1438+sumDistinct
1439+ :: ty `In` PGNum
1440+ => Expression commons schemas from 'Ungrouped params (nullity ty)
1441+ -- ^ what to sum
1442+ -> Expression commons schemas from ('Grouped bys) params (nullity ty)
1443+sumDistinct = unsafeAggregateDistinct "sum"
1444+
1445+-- | A constraint for `PGType`s that you can take averages of and the resulting
1446+-- `PGType`.
1447+class PGAvg ty avg | ty -> avg where
1448+ avg, avgDistinct
1449+ :: Expression commons schemas from 'Ungrouped params (nullity ty)
1450+ -- ^ what to average
1451+ -> Expression commons schemas from ('Grouped bys) params (nullity avg)
1452+ avg = unsafeAggregate "avg"
1453+ avgDistinct = unsafeAggregateDistinct "avg"
1454+instance PGAvg 'PGint2 'PGnumeric
1455+instance PGAvg 'PGint4 'PGnumeric
1456+instance PGAvg 'PGint8 'PGnumeric
1457+instance PGAvg 'PGnumeric 'PGnumeric
1458+instance PGAvg 'PGfloat4 'PGfloat8
1459+instance PGAvg 'PGfloat8 'PGfloat8
1460+instance PGAvg 'PGinterval 'PGinterval
1461+
1462+-- | >>> :{
1463+-- let
1464+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1465+-- expression = bitAnd #col
1466+-- in printSQL expression
1467+-- :}
1468+-- bit_and("col")
1469+bitAnd
1470+ :: int `In` PGIntegral
1471+ => Expression commons schemas from 'Ungrouped params (nullity int)
1472+ -- ^ what to aggregate
1473+ -> Expression commons schemas from ('Grouped bys) params (nullity int)
1474+bitAnd = unsafeAggregate "bit_and"
1475+
1476+-- | >>> :{
1477+-- let
1478+-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1479+-- expression = bitOr #col
1480+-- in printSQL expression
1481+-- :}
1482+-- bit_or("col")
1483+bitOr
1484+ :: int `In` PGIntegral
1485+ => Expression commons schemas from 'Ungrouped params (nullity int)
1486+ -- ^ what to aggregate
1487+ -> Expression commons schemas from ('Grouped bys) params (nullity int)
1488+bitOr = unsafeAggregate "bit_or"
1489+
1490+-- | >>> :{
1491+-- let
1492+-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1493+-- expression = bitAndDistinct #col
1494+-- in printSQL expression
1495+-- :}
1496+-- bit_and(DISTINCT "col")
1497+bitAndDistinct
1498+ :: int `In` PGIntegral
1499+ => Expression commons schemas from 'Ungrouped params (nullity int)
1500+ -- ^ what to aggregate
1501+ -> Expression commons schemas from ('Grouped bys) params (nullity int)
1502+bitAndDistinct = unsafeAggregateDistinct "bit_and"
1503+
1504+-- | >>> :{
1505+-- let
1506+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1507+-- expression = bitOrDistinct #col
1508+-- in printSQL expression
1509+-- :}
1510+-- bit_or(DISTINCT "col")
1511+bitOrDistinct
1512+ :: int `In` PGIntegral
1513+ => Expression commons schemas from 'Ungrouped params (nullity int)
1514+ -- ^ what to aggregate
1515+ -> Expression commons schemas from ('Grouped bys) params (nullity int)
1516+bitOrDistinct = unsafeAggregateDistinct "bit_or"
1517+
1518+-- | >>> :{
1519+-- let
1520+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1521+-- expression = boolAnd #col
1522+-- in printSQL expression
1523+-- :}
1524+-- bool_and("col")
1525+boolAnd
1526+ :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1527+ -- ^ what to aggregate
1528+ -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1529+boolAnd = unsafeAggregate "bool_and"
1530+
1531+-- | >>> :{
1532+-- let
1533+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1534+-- expression = boolOr #col
1535+-- in printSQL expression
1536+-- :}
1537+-- bool_or("col")
1538+boolOr
1539+ :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1540+ -- ^ what to aggregate
1541+ -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1542+boolOr = unsafeAggregate "bool_or"
1543+
1544+-- | >>> :{
1545+-- let
1546+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1547+-- expression = boolAndDistinct #col
1548+-- in printSQL expression
1549+-- :}
1550+-- bool_and(DISTINCT "col")
1551+boolAndDistinct
1552+ :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1553+ -- ^ what to aggregate
1554+ -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1555+boolAndDistinct = unsafeAggregateDistinct "bool_and"
1556+
1557+-- | >>> :{
1558+-- let
1559+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1560+-- expression = boolOrDistinct #col
1561+-- in printSQL expression
1562+-- :}
1563+-- bool_or(DISTINCT "col")
1564+boolOrDistinct
1565+ :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1566+ -- ^ what to aggregate
1567+ -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1568+boolOrDistinct = unsafeAggregateDistinct "bool_or"
1569+
1570+-- | A special aggregation that does not require an input
1571+--
1572+-- >>> printSQL countStar
1573+-- count(*)
1574+countStar
1575+ :: Expression commons schemas from ('Grouped bys) params ('NotNull 'PGint8)
1576+countStar = UnsafeExpression $ "count(*)"
1577+
1578+-- | >>> :{
1579+-- let
1580+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1581+-- expression = count #col
1582+-- in printSQL expression
1583+-- :}
1584+-- count("col")
1585+count
1586+ :: Expression commons schemas from 'Ungrouped params ty
1587+ -- ^ what to count
1588+ -> Expression commons schemas from ('Grouped bys) params ('NotNull 'PGint8)
1589+count = unsafeAggregate "count"
1590+
1591+-- | >>> :{
1592+-- let
1593+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1594+-- expression = countDistinct #col
1595+-- in printSQL expression
1596+-- :}
1597+-- count(DISTINCT "col")
1598+countDistinct
1599+ :: Expression commons schemas from 'Ungrouped params ty
1600+ -- ^ what to count
1601+ -> Expression commons schemas from ('Grouped bys) params ('NotNull 'PGint8)
1602+countDistinct = unsafeAggregateDistinct "count"
1603+
1604+-- | synonym for `boolAnd`
1605+--
1606+-- >>> :{
1607+-- let
1608+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1609+-- expression = every #col
1610+-- in printSQL expression
1611+-- :}
1612+-- every("col")
1613+every
1614+ :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1615+ -- ^ what to aggregate
1616+ -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1617+every = unsafeAggregate "every"
1618+
1619+-- | synonym for `boolAndDistinct`
1620+--
1621+-- >>> :{
1622+-- let
1623+-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1624+-- expression = everyDistinct #col
1625+-- in printSQL expression
1626+-- :}
1627+-- every(DISTINCT "col")
1628+everyDistinct
1629+ :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1630+ -- ^ what to aggregate
1631+ -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1632+everyDistinct = unsafeAggregateDistinct "every"
1633+
1634+-- | minimum and maximum aggregation
1635+max_, min_, maxDistinct, minDistinct
1636+ :: Expression commons schemas from 'Ungrouped params (nullity ty)
1637+ -- ^ what to aggregate
1638+ -> Expression commons schemas from ('Grouped bys) params (nullity ty)
1639+max_ = unsafeAggregate "max"
1640+min_ = unsafeAggregate "min"
1641+maxDistinct = unsafeAggregateDistinct "max"
1642+minDistinct = unsafeAggregateDistinct "min"
1643+
1644+{-----------------------------------------
1645+type expressions
1646+-----------------------------------------}
1647+
1648+-- | `TypeExpression`s are used in `cast`s and `createTable` commands.
1649+newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
1650+ = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1651+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
1652+instance RenderSQL (TypeExpression schemas ty) where
1653+ renderSQL = renderTypeExpression
1654+
1655+-- | The enum or composite type in a `Typedef` can be expressed by its alias.
1656+typedef
1657+ :: (Has sch schemas schema, Has td schema ('Typedef ty))
1658+ => QualifiedAlias sch td
1659+ -> TypeExpression schemas (nullity ty)
1660+typedef = UnsafeTypeExpression . renderSQL
1661+
1662+-- | The composite type corresponding to a `Table` definition can be expressed
1663+-- by its alias.
1664+typetable
1665+ :: (Has sch schemas schema, Has tab schema ('Table table))
1666+ => QualifiedAlias sch tab
1667+ -> TypeExpression schemas (nullity ('PGcomposite (TableToRow table)))
1668+typetable = UnsafeTypeExpression . renderSQL
1669+
1670+-- | The composite type corresponding to a `View` definition can be expressed
1671+-- by its alias.
1672+typeview
1673+ :: (Has sch schemas schema, Has vw schema ('View view))
1674+ => QualifiedAlias sch vw
1675+ -> TypeExpression schemas (nullity ('PGcomposite view))
1676+typeview = UnsafeTypeExpression . renderSQL
1677+
1678+-- | logical Boolean (true/false)
1679+bool :: TypeExpression schemas (nullity 'PGbool)
1680+bool = UnsafeTypeExpression "bool"
1681+-- | signed two-byte integer
1682+int2, smallint :: TypeExpression schemas (nullity 'PGint2)
1683+int2 = UnsafeTypeExpression "int2"
1684+smallint = UnsafeTypeExpression "smallint"
1685+-- | signed four-byte integer
1686+int4, int, integer :: TypeExpression schemas (nullity 'PGint4)
1687+int4 = UnsafeTypeExpression "int4"
1688+int = UnsafeTypeExpression "int"
1689+integer = UnsafeTypeExpression "integer"
1690+-- | signed eight-byte integer
1691+int8, bigint :: TypeExpression schemas (nullity 'PGint8)
1692+int8 = UnsafeTypeExpression "int8"
1693+bigint = UnsafeTypeExpression "bigint"
1694+-- | arbitrary precision numeric type
1695+numeric :: TypeExpression schemas (nullity 'PGnumeric)
1696+numeric = UnsafeTypeExpression "numeric"
1697+-- | single precision floating-point number (4 bytes)
1698+float4, real :: TypeExpression schemas (nullity 'PGfloat4)
1699+float4 = UnsafeTypeExpression "float4"
1700+real = UnsafeTypeExpression "real"
1701+-- | double precision floating-point number (8 bytes)
1702+float8, doublePrecision :: TypeExpression schemas (nullity 'PGfloat8)
1703+float8 = UnsafeTypeExpression "float8"
1704+doublePrecision = UnsafeTypeExpression "double precision"
1705+-- | variable-length character string
1706+text :: TypeExpression schemas (nullity 'PGtext)
1707+text = UnsafeTypeExpression "text"
1708+-- | fixed-length character string
1709+char, character
1710+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
1711+ => TypeExpression schemas (nullity ('PGchar n))
1712+char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
1713+character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
1714+-- | variable-length character string
1715+varchar, characterVarying
1716+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
1717+ => TypeExpression schemas (nullity ('PGvarchar n))
1718+varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
1719+characterVarying = UnsafeTypeExpression $
1720+ "character varying(" <> renderNat @n <> ")"
1721+-- | binary data ("byte array")
1722+bytea :: TypeExpression schemas (nullity 'PGbytea)
1723+bytea = UnsafeTypeExpression "bytea"
1724+-- | date and time (no time zone)
1725+timestamp :: TypeExpression schemas (nullity 'PGtimestamp)
1726+timestamp = UnsafeTypeExpression "timestamp"
1727+-- | date and time, including time zone
1728+timestampWithTimeZone :: TypeExpression schemas (nullity 'PGtimestamptz)
1729+timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1730+-- | calendar date (year, month, day)
1731+date :: TypeExpression schemas (nullity 'PGdate)
1732+date = UnsafeTypeExpression "date"
1733+-- | time of day (no time zone)
1734+time :: TypeExpression schemas (nullity 'PGtime)
1735+time = UnsafeTypeExpression "time"
1736+-- | time of day, including time zone
1737+timeWithTimeZone :: TypeExpression schemas (nullity 'PGtimetz)
1738+timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1739+-- | time span
1740+interval :: TypeExpression schemas (nullity 'PGinterval)
1741+interval = UnsafeTypeExpression "interval"
1742+-- | universally unique identifier
1743+uuid :: TypeExpression schemas (nullity 'PGuuid)
1744+uuid = UnsafeTypeExpression "uuid"
1745+-- | IPv4 or IPv6 host address
1746+inet :: TypeExpression schemas (nullity 'PGinet)
1747+inet = UnsafeTypeExpression "inet"
1748+-- | textual JSON data
1749+json :: TypeExpression schemas (nullity 'PGjson)
1750+json = UnsafeTypeExpression "json"
1751+-- | binary JSON data, decomposed
1752+jsonb :: TypeExpression schemas (nullity 'PGjsonb)
1753+jsonb = UnsafeTypeExpression "jsonb"
1754+-- | variable length array
1755+vararray
1756+ :: TypeExpression schemas pg
1757+ -> TypeExpression schemas (nullity ('PGvararray pg))
1758+vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
1759+-- | fixed length array
1760+--
1761+-- >>> renderSQL (fixarray @2 json)
1762+-- "json[2]"
1763+fixarray
1764+ :: forall n schemas nullity pg. KnownNat n
1765+ => TypeExpression schemas pg
1766+ -> TypeExpression schemas (nullity ('PGfixarray n pg))
1767+fixarray ty = UnsafeTypeExpression $
1768+ renderSQL ty <> "[" <> renderNat @n <> "]"
1769+
1770+-- | `pgtype` is a demoted version of a `PGType`
1771+class PGTyped schemas (ty :: NullityType) where
1772+ pgtype :: TypeExpression schemas ty
1773+instance PGTyped schemas (nullity 'PGbool) where pgtype = bool
1774+instance PGTyped schemas (nullity 'PGint2) where pgtype = int2
1775+instance PGTyped schemas (nullity 'PGint4) where pgtype = int4
1776+instance PGTyped schemas (nullity 'PGint8) where pgtype = int8
1777+instance PGTyped schemas (nullity 'PGnumeric) where pgtype = numeric
1778+instance PGTyped schemas (nullity 'PGfloat4) where pgtype = float4
1779+instance PGTyped schemas (nullity 'PGfloat8) where pgtype = float8
1780+instance PGTyped schemas (nullity 'PGtext) where pgtype = text
1781+instance (KnownNat n, 1 <= n)
1782+ => PGTyped schemas (nullity ('PGchar n)) where pgtype = char @n
1783+instance (KnownNat n, 1 <= n)
1784+ => PGTyped schemas (nullity ('PGvarchar n)) where pgtype = varchar @n
1785+instance PGTyped schemas (nullity 'PGbytea) where pgtype = bytea
1786+instance PGTyped schemas (nullity 'PGtimestamp) where pgtype = timestamp
1787+instance PGTyped schemas (nullity 'PGtimestamptz) where pgtype = timestampWithTimeZone
1788+instance PGTyped schemas (nullity 'PGdate) where pgtype = date
1789+instance PGTyped schemas (nullity 'PGtime) where pgtype = time
1790+instance PGTyped schemas (nullity 'PGtimetz) where pgtype = timeWithTimeZone
1791+instance PGTyped schemas (nullity 'PGinterval) where pgtype = interval
1792+instance PGTyped schemas (nullity 'PGuuid) where pgtype = uuid
1793+instance PGTyped schemas (nullity 'PGjson) where pgtype = json
1794+instance PGTyped schemas (nullity 'PGjsonb) where pgtype = jsonb
1795+instance PGTyped schemas ty
1796+ => PGTyped schemas (nullity ('PGvararray ty)) where
1797+ pgtype = vararray (pgtype @schemas @ty)
1798+instance (KnownNat n, PGTyped schemas ty)
1799+ => PGTyped schemas (nullity ('PGfixarray n ty)) where
1800+ pgtype = fixarray @n (pgtype @schemas @ty)
1801+
1802+{-----------------------------------------
1803+Sorting
1804+-----------------------------------------}
1805+
1806+-- | `SortExpression`s are used by `sortBy` to optionally sort the results
1807+-- of a `Query`. `Asc` or `Desc` set the sort direction of a `NotNull` result
1808+-- column to ascending or descending. Ascending order puts smaller values
1809+-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
1810+-- descending order is determined with the `.>` operator. `AscNullsFirst`,
1811+-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
1812+-- determine whether nulls appear before or after non-null values in the sort
1813+-- ordering of a `Null` result column.
1814+data SortExpression commons schemas params grp from where
1815+ Asc
1816+ :: Expression commons schemas params grp from ('NotNull ty)
1817+ -> SortExpression commons schemas params grp from
1818+ Desc
1819+ :: Expression commons schemas params grp from ('NotNull ty)
1820+ -> SortExpression commons schemas params grp from
1821+ AscNullsFirst
1822+ :: Expression commons schemas params grp from ('Null ty)
1823+ -> SortExpression commons schemas params grp from
1824+ AscNullsLast
1825+ :: Expression commons schemas params grp from ('Null ty)
1826+ -> SortExpression commons schemas params grp from
1827+ DescNullsFirst
1828+ :: Expression commons schemas params grp from ('Null ty)
1829+ -> SortExpression commons schemas params grp from
1830+ DescNullsLast
1831+ :: Expression commons schemas params grp from ('Null ty)
1832+ -> SortExpression commons schemas params grp from
1833+deriving instance Show (SortExpression commons schemas params grp from)
1834+
1835+class OrderBy expr where
1836+ orderBy
1837+ :: [SortExpression commons schemas params grp from]
1838+ -> expr commons schemas params grp from
1839+ -> expr commons schemas params grp from
1840+
1841+-- | Render a `SortExpression`.
1842+instance RenderSQL (SortExpression commons schemas params grp from) where
1843+ renderSQL = \case
1844+ Asc expression -> renderSQL expression <+> "ASC"
1845+ Desc expression -> renderSQL expression <+> "DESC"
1846+ AscNullsFirst expression -> renderSQL expression
1847+ <+> "ASC NULLS FIRST"
1848+ DescNullsFirst expression -> renderSQL expression
1849+ <+> "DESC NULLS FIRST"
1850+ AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
1851+ DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
1852+
1853+data WindowDefinition commons schemas params grp from where
1854+ WindowDefinition
1855+ :: SListI bys
1856+ => NP (Expression commons schemas params grp from) bys
1857+ -> [SortExpression commons schemas params grp from]
1858+ -> WindowDefinition commons schemas params grp from
1859+
1860+instance OrderBy WindowDefinition where
1861+ orderBy sortsR (WindowDefinition parts sortsL)
1862+ = WindowDefinition parts (sortsL ++ sortsR)
1863+
1864+instance RenderSQL (WindowDefinition commons schemas from grp params) where
1865+ renderSQL (WindowDefinition part ord) =
1866+ renderPartitionByClause part <> renderOrderByClause ord
1867+ where
1868+ renderPartitionByClause = \case
1869+ Nil -> ""
1870+ parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
1871+ renderOrderByClause = \case
1872+ [] -> ""
1873+ srts -> " ORDER" <+> "BY"
1874+ <+> commaSeparated (renderSQL <$> srts)
1875+
1876+partitionBy
1877+ :: SListI bys
1878+ => NP (Expression commons schemas params grp from) bys
1879+ -> WindowDefinition commons schemas params grp from
1880+partitionBy bys = WindowDefinition bys []
1881+
1882+newtype WindowFunction
1883+ (commons :: FromType)
1884+ (schemas :: SchemasType)
1885+ (params :: [NullityType])
1886+ (grp :: Grouping)
1887+ (from :: FromType)
1888+ (ty :: NullityType)
1889+ = UnsafeWindowFunction { renderWindowFunction :: ByteString }
1890+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
1891+
1892+instance RenderSQL (WindowFunction commons schemas params grp from ty) where
1893+ renderSQL = renderWindowFunction
1894+
1895+{- | rank of the current row with gaps; same as `rowNumber` of its first peer
1896+>>> printSQL rank
1897+rank()
1898+-}
1899+rank :: WindowFunction commons schemas from grp params ('NotNull 'PGint8)
1900+rank = UnsafeWindowFunction "rank()"
1901+
1902+{- | number of the current row within its partition, counting from 1
1903+>>> printSQL rowNumber
1904+row_number()
1905+-}
1906+rowNumber :: WindowFunction commons schemas from grp params ('NotNull 'PGint8)
1907+rowNumber = UnsafeWindowFunction "row_number()"
1908+
1909+{- | rank of the current row without gaps; this function counts peer groups
1910+>>> printSQL denseRank
1911+dense_rank()
1912+-}
1913+denseRank :: WindowFunction commons schemas from grp params ('NotNull 'PGint8)
1914+denseRank = UnsafeWindowFunction "dense_rank()"
1915+
1916+{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
1917+>>> printSQL percentRank
1918+percent_rank()
1919+-}
1920+percentRank :: WindowFunction commons schemas from grp params ('NotNull 'PGfloat8)
1921+percentRank = UnsafeWindowFunction "percent_rank()"
1922+
1923+{- | cumulative distribution: (number of partition rows
1924+preceding or peer with current row) / total partition rows
1925+>>> printSQL cumeDist
1926+cume_dist()
1927+-}
1928+cumeDist :: WindowFunction commons schemas from grp params ('NotNull 'PGfloat8)
1929+cumeDist = UnsafeWindowFunction "cume_dist()"
1930+
1931+{- | integer ranging from 1 to the argument value,
1932+dividing the partition as equally as possible
1933+-}
1934+ntile
1935+ :: Expression commons schemas from grp params ('NotNull 'PGint4)
1936+ -- ^ numuckets
1937+ -> WindowFunction commons schemas from grp params ('NotNull 'PGint4)
1938+ntile numBuckets = UnsafeWindowFunction $ "ntile"
1939+ <> parenthesized (renderSQL numBuckets)
1940+
1941+{- | returns value evaluated at the row that is offset rows before the current
1942+row within the partition; if there is no such row, instead return default
1943+(which must be of the same type as value). Both offset and default are
1944+evaluated with respect to the current row.
1945+-}
1946+lag
1947+ :: Expression commons schemas from grp params ty
1948+ -- ^ value
1949+ -> Expression commons schemas from grp params ('NotNull 'PGint4)
1950+ -- ^ offset
1951+ -> Expression commons schemas from grp params ty
1952+ -- ^ default
1953+ -> WindowFunction commons schemas from grp params ty
1954+lag value offset def = UnsafeWindowFunction $ "lag"
1955+ <> parenthesized
1956+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
1957+
1958+{- | returns value evaluated at the row that is offset rows after the current
1959+row within the partition; if there is no such row, instead return default
1960+(which must be of the same type as value). Both offset and default are
1961+evaluated with respect to the current row.
1962+-}
1963+lead
1964+ :: Expression commons schemas from grp params ty
1965+ -- ^ value
1966+ -> Expression commons schemas from grp params ('NotNull 'PGint4)
1967+ -- ^ offset
1968+ -> Expression commons schemas from grp params ty
1969+ -- ^ default
1970+ -> WindowFunction commons schemas from grp params ty
1971+lead value offset def = UnsafeWindowFunction $ "lag"
1972+ <> parenthesized
1973+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
1974+
1975+{- | returns value evaluated at the row that is the
1976+first row of the window frame
1977+-}
1978+firstValue
1979+ :: Expression commons schemas from grp params ty
1980+ -- ^ value
1981+ -> WindowFunction commons schemas from grp params ty
1982+firstValue value = UnsafeWindowFunction $ "first_value"
1983+ <> parenthesized (renderSQL value)
1984+
1985+{- | returns value evaluated at the row that is the
1986+last row of the window frame
1987+-}
1988+lastValue
1989+ :: Expression commons schemas from grp params ty
1990+ -- ^ value
1991+ -> WindowFunction commons schemas from grp params ty
1992+lastValue value = UnsafeWindowFunction $ "last_value"
1993+ <> parenthesized (renderSQL value)
1994+
1995+{- | returns value evaluated at the row that is the nth
1996+row of the window frame (counting from 1); null if no such row
1997+-}
1998+nthValue
1999+ :: Expression commons schemas from grp params (nullity ty)
2000+ -- ^ value
2001+ -> Expression commons schemas from grp params ('NotNull 'PGint4)
2002+ -- ^ nth
2003+ -> WindowFunction commons schemas from grp params ('Null ty)
2004+nthValue value nth = UnsafeWindowFunction $ "nth_value"
2005+ <> parenthesized (commaSeparated [renderSQL value, renderSQL nth])