@@ -1,13 +1,14 @@
11{-|
22Module: Squeal.PostgreSQL.Expression
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,214 +34,334 @@ 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
4537 , Operator
46− , OperatorDB
38+ , HasParameter (parameter)
39+ , param
40+ -- ** Null
41+ , null_
42+ , notNull
43+ , coalesce
44+ , fromNull
45+ , isNull
46+ , isNotNull
47+ , matchNull
48+ , nullIf
49+ -- ** Collections
50+ , array
51+ , cardinality
52+ , index
53+ , row
54+ , field
55+ -- ** Functions
4756 , unsafeBinaryOp
48− , binaryOp
49− , FunctionVar
50− , unsafeFunctionVar
51− , type (--->)
52− , FunctionNDB
53− , unsafeFunctionN
54− , functionN
55− , PGSubset (..)
56− , PGIntersect (..)
57+ , unsafeUnaryOp
58+ , unsafeFunction
59+ , unsafeFunction2
60+ , unsafeVariadicFunction
61+ , atan2_
62+ , cast
63+ , quot_
64+ , rem_
65+ , trunc
66+ , round_
67+ , ceiling_
68+ , greatest
69+ , least
70+ -- ** Conditions
71+ , true
72+ , false
73+ , not_
74+ , (.&&)
75+ , (.||)
76+ , Condition
77+ , caseWhenThenElse
78+ , ifThenElse
79+ , (.==)
80+ , (./=)
81+ , (.>=)
82+ , (.<)
83+ , (.<=)
84+ , (.>)
85+ , between
86+ , notBetween
87+ , betweenSymmetric
88+ , notBetweenSymmetric
89+ , isDistinctFrom
90+ , isNotDistinctFrom
91+ , isTrue
92+ , isNotTrue
93+ , isFalse
94+ , isNotFalse
95+ , isUnknown
96+ , isNotUnknown
97+ -- ** Time
98+ , currentDate
99+ , currentTime
100+ , currentTimestamp
101+ , localTime
102+ , localTimestamp
103+ , TimeOp (..)
104+ , makeDate
105+ , makeTime
106+ , makeTimestamp
107+ , makeTimestamptz
108+ -- ** Text
109+ , lower
110+ , upper
111+ , charLength
112+ , like
113+ , ilike
114+ -- ** Json
115+ -- *** Json and Jsonb operators
116+ , (.->)
117+ , (.->>)
118+ , (.#>)
119+ , (.#>>)
120+ -- *** Jsonb operators
121+ , (.@>)
122+ , (.<@)
123+ , (.?)
124+ , (.?|)
125+ , (.?&)
126+ , (.-.)
127+ , (#-.)
128+ -- *** Functions
129+ , jsonLit
130+ , jsonbLit
131+ , toJson
132+ , toJsonb
133+ , arrayToJson
134+ , rowToJson
135+ , jsonBuildArray
136+ , jsonbBuildArray
137+ , jsonBuildObject
138+ , jsonbBuildObject
139+ , jsonObject
140+ , jsonbObject
141+ , jsonZipObject
142+ , jsonbZipObject
143+ , jsonArrayLength
144+ , jsonbArrayLength
145+ , jsonExtractPath
146+ , jsonbExtractPath
147+ , jsonExtractPathAsText
148+ , jsonbExtractPathAsText
149+ , jsonTypeof
150+ , jsonbTypeof
151+ , jsonStripNulls
152+ , jsonbStripNulls
153+ , jsonbSet
154+ , jsonbInsert
155+ , jsonbPretty
156+ -- ** Text Search
157+ , (@@)
158+ , (.&)
159+ , (.|)
160+ , (.!)
161+ , (<->)
162+ -- ** Aggregation
163+ , Aggregate (..)
164+ , Distinction (..)
165+ , PGAvg
166+ -- * Window Functions
167+ , WindowDefinition (..)
168+ , partitionBy
169+ , WindowFunction (..)
170+ , rank
171+ , rowNumber
172+ , denseRank
173+ , percentRank
174+ , cumeDist
175+ , ntile
176+ , lag
177+ , lead
178+ , firstValue
179+ , lastValue
180+ , nthValue
181+ -- * Sorting
182+ , SortExpression (..)
183+ , OrderBy (..)
184+ -- * Types
185+ , TypeExpression (..)
186+ , PGTyped (..)
187+ , typedef
188+ , typetable
189+ , typeview
190+ , bool
191+ , int2
192+ , smallint
193+ , int4
194+ , int
195+ , integer
196+ , int8
197+ , bigint
198+ , numeric
199+ , float4
200+ , real
201+ , float8
202+ , doublePrecision
203+ , money
204+ , text
205+ , char
206+ , character
207+ , varchar
208+ , characterVarying
209+ , bytea
210+ , timestamp
211+ , timestampWithTimeZone
212+ , date
213+ , time
214+ , timeWithTimeZone
215+ , interval
216+ , uuid
217+ , inet
218+ , json
219+ , jsonb
220+ , vararray
221+ , fixarray
222+ , tsvector
223+ , tsquery
224+ , arrayToTSvector
225+ , tsvectorLength
226+ , numnode
227+ , plainToTSquery
228+ , phraseToTSquery
229+ , websearchToTSquery
230+ , queryTree
231+ , toTSquery
232+ , toTSvector
57233 -- * Re-export
58234 , (&)
235+ , NP (..)
236+ , (:*:) (..)
59237 , K (..)
60− , unK
61238 ) where
62239
63240import Control.Category
64241import Control.DeepSeq
65242import Data.ByteString (ByteString)
243+import Data.ByteString.Lazy (toStrict)
66244import Data.Function ((&))
67245import Data.Semigroup hiding (All)
246+import qualified Data.Aeson as JSON
68247import Data.String
248+import Data.Word
69249import Generics.SOP hiding (All, from)
250+import GHC.Generics ((:*:) (..))
70251import GHC.OverloadedLabels
71252import GHC.TypeLits
72253import Numeric
73254import Prelude hiding (id, (.))
74255
256+import qualified Data.ByteString as ByteString
75257import qualified GHC.Generics as GHC
258+import qualified Generics.SOP as SOP
76259
77−import Squeal.PostgreSQL.Alias
78−import Squeal.PostgreSQL.List
79260import Squeal.PostgreSQL.Render
80261import Squeal.PostgreSQL.Schema
81262
82−-- $setup
83−-- >>> import Squeal.PostgreSQL
84−
85263{-----------------------------------------
86264column expressions
87265-----------------------------------------}
88266
89267{- | `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,
268+such as in the target list of the `Squeal.PostgreSQL.Query.select` command,
92269as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
93270`Squeal.PostgreSQL.Manipulation.update`,
94−or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
271+or in search `Condition`s in a number of commands.
95272
96273The expression syntax allows the calculation of
97274values from primitive expression using arithmetic, logical,
98275and 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`.
113276-}
114277newtype Expression
115278 (outer :: FromType)
116− (commons :: FromType)
117279 (grp :: Grouping)
280+ (commons :: FromType)
118281 (schemas :: SchemasType)
119282 (params :: [NullityType])
120283 (from :: FromType)
121284 (ty :: NullityType)
122285 = UnsafeExpression { renderExpression :: ByteString }
123286 deriving (GHC.Generic,Show,Eq,Ord,NFData)
124−instance RenderSQL (Expression outer commons grp schemas params from ty) where
287+instance RenderSQL (Expression outer grp commons schemas params from ty) where
125288 renderSQL = renderExpression
126289
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.
198−-}
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)
290+type Operator ty1 ty2 ty3
291+ = forall outer grp commons schemas params from
292+ . Expression outer grp commons schemas params from ty1
293+ -> Expression outer grp commons schemas params from ty2
294+ -> Expression outer grp commons schemas params from ty3
295+
296+{- | A `HasParameter` constraint is used to indicate a value that is
297+supplied externally to a SQL statement.
298+`Squeal.PostgreSQL.PQ.manipulateParams`,
299+`Squeal.PostgreSQL.PQ.queryParams` and
300+`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
301+separately from the SQL command string, in which case `param`s are used to
302+refer to the out-of-line data values.
303+-}
304+class KnownNat n => HasParameter
305+ (n :: Nat)
306+ (params :: [NullityType])
307+ (ty :: NullityType)
308+ | n params -> ty where
309+ -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
310+ --
311+ -- >>> let expr = parameter @1 int4 :: Expression outer grp '[] schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
312+ -- >>> printSQL expr
313+ -- ($1 :: int4)
314+ parameter
315+ :: TypeExpression schemas ty
316+ -> Expression outer grp commons schemas params from ty
317+ parameter ty = UnsafeExpression $ parenthesized $
318+ "$" <> renderNat @n <+> "::"
319+ <+> renderSQL ty
320+instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
321+instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
322+ => HasParameter n (ty' : params) ty
323+
324+-- | `param` takes a `Nat` using type application and for basic types,
325+-- infers a `TypeExpression`.
326+--
327+-- >>> let expr = param @1 :: Expression outer grp commons schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
328+-- >>> printSQL expr
329+-- ($1 :: int4)
330+param
331+ :: forall n outer commons schemas params from grp ty
332+ . (PGTyped schemas ty, HasParameter n params ty)
333+ => Expression outer grp commons schemas params from ty -- ^ param
334+param = parameter @n (pgtype @schemas)
214335
215336instance (HasUnique tab (Join outer from) row, Has col row ty)
216− => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
337+ => IsLabel col (Expression outer 'Ungrouped commons schemas params from ty) where
217338 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
218339instance (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
340+ => IsLabel col (NP (Expression outer 'Ungrouped commons schemas params from) tys) where
220341 fromLabel = fromLabel @col :* Nil
221342instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
222343 => IsLabel col
223− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
344+ (Aliased (Expression outer 'Ungrouped commons schemas params from) column) where
224345 fromLabel = fromLabel @col `As` Alias
225346instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
226347 => IsLabel col
227− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
348+ (NP (Aliased (Expression outer 'Ungrouped commons schemas params from)) columns) where
228349 fromLabel = fromLabel @col :* Nil
229350
230351instance (Has tab (Join outer from) row, Has col row ty)
231− => IsQualified tab col (Expression outer commons 'Ungrouped schemas params from ty) where
352+ => IsQualified tab col (Expression outer 'Ungrouped commons schemas params from ty) where
232353 tab ! col = UnsafeExpression $
233354 renderSQL tab <> "." <> renderSQL col
234355instance (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
356+ => IsQualified tab col (NP (Expression outer 'Ungrouped commons schemas params from) tys) where
236357 tab ! col = tab ! col :* Nil
237358instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
238359 => IsQualified tab col
239− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
360+ (Aliased (Expression outer 'Ungrouped commons schemas params from) column) where
240361 tab ! col = tab ! col `As` col
241362instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
242363 => IsQualified tab col
243− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
364+ (NP (Aliased (Expression outer 'Ungrouped commons schemas params from)) columns) where
244365 tab ! col = tab ! col :* Nil
245366
246367instance
@@ -248,7 +369,7 @@ instance
248369 , Has col row ty
249370 , GroupedBy tab col bys
250371 ) => IsLabel col
251− (Expression outer commons ('Grouped bys) schemas params from ty) where
372+ (Expression outer ('Grouped bys) commons schemas params from ty) where
252373 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
253374instance
254375 ( HasUnique tab (Join outer from) row
@@ -256,7 +377,7 @@ instance
256377 , GroupedBy tab col bys
257378 , tys ~ '[ty]
258379 ) => IsLabel col
259− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
380+ (NP (Expression outer ('Grouped bys) commons schemas params from) tys) where
260381 fromLabel = fromLabel @col :* Nil
261382instance
262383 ( HasUnique tab (Join outer from) row
@@ -264,7 +385,7 @@ instance
264385 , GroupedBy tab col bys
265386 , column ~ (col ::: ty)
266387 ) => IsLabel col
267− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
388+ (Aliased (Expression outer ('Grouped bys) commons schemas params from) column) where
268389 fromLabel = fromLabel @col `As` Alias
269390instance
270391 ( HasUnique tab (Join outer from) row
@@ -272,7 +393,7 @@ instance
272393 , GroupedBy tab col bys
273394 , columns ~ '[col ::: ty]
274395 ) => IsLabel col
275− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
396+ (NP (Aliased (Expression outer ('Grouped bys) commons schemas params from)) columns) where
276397 fromLabel = fromLabel @col :* Nil
277398
278399instance
@@ -280,7 +401,7 @@ instance
280401 , Has col row ty
281402 , GroupedBy tab col bys
282403 ) => IsQualified tab col
283− (Expression outer commons ('Grouped bys) schemas params from ty) where
404+ (Expression outer ('Grouped bys) commons schemas params from ty) where
284405 tab ! col = UnsafeExpression $
285406 renderSQL tab <> "." <> renderSQL col
286407instance
@@ -289,7 +410,7 @@ instance
289410 , GroupedBy tab col bys
290411 , tys ~ '[ty]
291412 ) => IsQualified tab col
292− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
413+ (NP (Expression outer ('Grouped bys) commons schemas params from) tys) where
293414 tab ! col = tab ! col :* Nil
294415instance
295416 ( Has tab (Join outer from) row
@@ -297,7 +418,7 @@ instance
297418 , GroupedBy tab col bys
298419 , column ~ (col ::: ty)
299420 ) => IsQualified tab col
300− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
421+ (Aliased (Expression outer ('Grouped bys) commons schemas params from) column) where
301422 tab ! col = tab ! col `As` col
302423instance
303424 ( Has tab (Join outer from) row
@@ -305,78 +426,251 @@ instance
305426 , GroupedBy tab col bys
306427 , columns ~ '[col ::: ty]
307428 ) => IsQualified tab col
308− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
429+ (NP (Aliased (Expression outer ('Grouped bys) commons schemas params from)) columns) where
309430 tab ! col = tab ! col :* Nil
310431
432+-- | analagous to `Nothing`
433+--
434+-- >>> printSQL null_
435+-- NULL
436+null_ :: Expression outer grp commons schemas params from ('Null ty)
437+null_ = UnsafeExpression "NULL"
438+
439+-- | analagous to `Just`
440+--
441+-- >>> printSQL $ notNull true
442+-- TRUE
443+notNull
444+ :: Expression outer grp commons schemas params from ('NotNull ty)
445+ -> Expression outer grp commons schemas params from ('Null ty)
446+notNull = UnsafeExpression . renderSQL
447+
448+-- | return the leftmost value which is not NULL
449+--
450+-- >>> printSQL $ coalesce [null_, true] false
451+-- COALESCE(NULL, TRUE, FALSE)
452+coalesce
453+ :: [Expression outer grp commons schemas params from ('Null ty)]
454+ -- ^ @NULL@s may be present
455+ -> Expression outer grp commons schemas params from ('NotNull ty)
456+ -- ^ @NULL@ is absent
457+ -> Expression outer grp commons schemas params from ('NotNull ty)
458+coalesce nullxs notNullx = UnsafeExpression $
459+ "COALESCE" <> parenthesized (commaSeparated
460+ ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
461+
462+-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
463+--
464+-- >>> printSQL $ fromNull true null_
465+-- COALESCE(NULL, TRUE)
466+fromNull
467+ :: Expression outer grp commons schemas params from ('NotNull ty)
468+ -- ^ what to convert @NULL@ to
469+ -> Expression outer grp commons schemas params from ('Null ty)
470+ -> Expression outer grp commons schemas params from ('NotNull ty)
471+fromNull notNullx nullx = coalesce [nullx] notNullx
472+
473+-- | >>> printSQL $ null_ & isNull
474+-- NULL IS NULL
475+isNull
476+ :: Expression outer grp commons schemas params from ('Null ty)
477+ -- ^ possibly @NULL@
478+ -> Condition outer grp commons schemas params from
479+isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
480+
481+-- | >>> printSQL $ null_ & isNotNull
482+-- NULL IS NOT NULL
483+isNotNull
484+ :: Expression outer grp commons schemas params from ('Null ty)
485+ -- ^ possibly @NULL@
486+ -> Condition outer grp commons schemas params from
487+isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
488+
489+-- | analagous to `maybe` using @IS NULL@
490+--
491+-- >>> printSQL $ matchNull true not_ null_
492+-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
493+matchNull
494+ :: Expression outer grp commons schemas params from (nullty)
495+ -- ^ what to convert @NULL@ to
496+ -> ( Expression outer grp commons schemas params from ('NotNull ty)
497+ -> Expression outer grp commons schemas params from (nullty) )
498+ -- ^ function to perform when @NULL@ is absent
499+ -> Expression outer grp commons schemas params from ('Null ty)
500+ -> Expression outer grp commons schemas params from (nullty)
501+matchNull y f x = ifThenElse (isNull x) y
502+ (f (UnsafeExpression (renderSQL x)))
503+
504+{-| right inverse to `fromNull`, if its arguments are equal then
505+`nullIf` gives @NULL@.
506+
507+>>> :set -XTypeApplications -XDataKinds
508+>>> let expr = nullIf false (param @1) :: Expression outer grp commons schemas '[ 'NotNull 'PGbool] from ('Null 'PGbool)
509+>>> printSQL expr
510+NULL IF (FALSE, ($1 :: bool))
511+-}
512+nullIf
513+ :: Expression outer grp commons schemas params from ('NotNull ty)
514+ -- ^ @NULL@ is absent
515+ -> Expression outer grp commons schemas params from ('NotNull ty)
516+ -- ^ @NULL@ is absent
517+ -> Expression outer grp commons schemas params from ('Null ty)
518+nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
519+ (renderSQL x <> ", " <> renderSQL y)
520+
521+-- | >>> printSQL $ array [null_, false, true]
522+-- ARRAY[NULL, FALSE, TRUE]
523+array
524+ :: [Expression outer grp commons schemas params from ty]
525+ -- ^ array elements
526+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ty))
527+array xs = UnsafeExpression $
528+ "ARRAY[" <> commaSeparated (renderSQL <$> xs) <> "]"
529+
530+-- | >>> printSQL $ cardinality (array [null_, false, true])
531+-- cardinality(ARRAY[NULL, FALSE, TRUE])
532+cardinality
533+ :: Expression outer grp commons schemas params from (nullity ('PGvararray ty))
534+ -> Expression outer grp commons schemas params from (nullity 'PGint8)
535+cardinality = unsafeFunction "cardinality"
536+
537+-- | >>> printSQL $ array [null_, false, true] & index 2
538+-- (ARRAY[NULL, FALSE, TRUE])[2]
539+index
540+ :: Word64 -- ^ index
541+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ty)) -- ^ array
542+ -> Expression outer grp commons schemas params from (NullifyType ty)
543+index n expr = UnsafeExpression $
544+ parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
545+
311546instance (KnownSymbol label, label `In` labels) => IsPGlabel label
312− (Expression outer commons grp schemas params from (null ('PGenum labels))) where
547+ (Expression outer grp commons schemas params from (nullity ('PGenum labels))) where
313548 label = UnsafeExpression $ renderSQL (PGlabel @label)
314549
550+-- | A row constructor is an expression that builds a row value
551+-- (also called a composite value) using values for its member fields.
552+--
553+-- >>> :{
554+-- type Complex = 'PGcomposite
555+-- '[ "real" ::: 'NotNull 'PGfloat8
556+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
557+-- :}
558+--
559+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer grp commons schemas params from ('NotNull Complex)
560+-- >>> printSQL i
561+-- ROW(0, 1)
562+row
563+ :: SListI row
564+ => NP (Aliased (Expression outer grp commons schemas params from)) row
565+ -- ^ zero or more expressions for the row field values
566+ -> Expression outer grp commons schemas params from (nullity ('PGcomposite row))
567+row exprs = UnsafeExpression $ "ROW" <> parenthesized
568+ (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
569+
570+-- | >>> :{
571+-- type Complex = 'PGcomposite
572+-- '[ "real" ::: 'NotNull 'PGfloat8
573+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
574+-- type Schema = '["complex" ::: 'Typedef Complex]
575+-- :}
576+--
577+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer grp '[] (Public Schema) from params ('NotNull Complex)
578+-- >>> printSQL $ i & field #complex #imaginary
579+-- (ROW(0, 1)::"complex")."imaginary"
580+field
581+ :: ( Has sch schemas schema
582+ , Has tydef schema ('Typedef ('PGcomposite row))
583+ , Has field row ty)
584+ => QualifiedAlias sch tydef -- ^ row type
585+ -> Alias field -- ^ field name
586+ -> Expression outer grp commons schemas params from ('NotNull ('PGcomposite row))
587+ -> Expression outer grp commons schemas params from ty
588+field td fld expr = UnsafeExpression $
589+ parenthesized (renderSQL expr <> "::" <> renderSQL td)
590+ <> "." <> renderSQL fld
591+
592+instance Semigroup
593+ (Expression outer grp commons schemas params from (nullity ('PGvararray ty))) where
594+ (<>) = unsafeBinaryOp "||"
595+
596+instance Monoid
597+ (Expression outer grp commons schemas params from (nullity ('PGvararray ty))) where
598+ mempty = array []
599+ mappend = (<>)
600+
601+-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression outer grp commons schemas '[ 'NotNull 'PGtimestamptz] from ('NotNull 'PGtimestamptz)
602+-- >>> printSQL expr
603+-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
604+greatest
605+ :: Expression outer grp commons schemas params from (nullty)
606+ -- ^ needs at least 1 argument
607+ -> [Expression outer grp commons schemas params from (nullty)]
608+ -- ^ or more
609+ -> Expression outer grp commons schemas params from (nullty)
610+greatest x xs = UnsafeExpression $ "GREATEST("
611+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
612+
613+-- | >>> printSQL $ least currentTimestamp [null_]
614+-- LEAST(CURRENT_TIMESTAMP, NULL)
615+least
616+ :: Expression outer grp commons schemas params from (nullty)
617+ -- ^ needs at least 1 argument
618+ -> [Expression outer grp commons schemas params from (nullty)]
619+ -- ^ or more
620+ -> Expression outer grp commons schemas params from (nullty)
621+least x xs = UnsafeExpression $ "LEAST("
622+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
623+
315624-- | >>> printSQL $ unsafeBinaryOp "OR" true false
316625-- (TRUE OR FALSE)
317−unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
626+unsafeBinaryOp
627+ :: ByteString
628+ -- ^ operator
629+ -> Operator ty0 ty1 ty2
318630unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
319631 renderSQL x <+> op <+> renderSQL y
320632
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
633+-- | >>> printSQL $ unsafeUnaryOp "NOT" true
329634-- (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
635+unsafeUnaryOp
636+ :: ByteString
637+ -- ^ operator
638+ -> Expression outer grp commons schemas params from (ty0)
639+ -> Expression outer grp commons schemas params from (ty1)
640+unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
641+ op <+> renderSQL x
351642
352643-- | >>> printSQL $ unsafeFunction "f" true
353644-- f(TRUE)
354−unsafeFunction :: ByteString -> x --> y
645+unsafeFunction
646+ :: ByteString
647+ -- ^ function
648+ -> Expression outer grp commons schemas params from xty
649+ -> Expression outer grp commons schemas params from yty
355650unsafeFunction fun x = UnsafeExpression $
356651 fun <> parenthesized (renderSQL x)
357652
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
653+unsafeFunction2
654+ :: ByteString
655+ -- ^ function
656+ -> Expression outer grp commons schemas params from ty1
657+ -> Expression outer grp commons schemas params from ty2
658+ -> Expression outer grp commons schemas params from ty
659+unsafeFunction2 fun x1 x2 = UnsafeExpression $
660+ fun <> parenthesized (commaSeparated [renderSQL x1, renderSQL x2])
363661
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
662+-- | Helper for defining variadic functions.
663+unsafeVariadicFunction
664+ :: SListI elems
665+ => ByteString
666+ -- ^ function
667+ -> NP (Expression outer grp commons schemas params from) elems
668+ -> Expression outer grp commons schemas params from ret
669+unsafeVariadicFunction fun x = UnsafeExpression $
670+ fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderSQL) x)))
377671
378672instance ty `In` PGNum
379− => Num (Expression outer commons grp schemas params from (null ty)) where
673+ => Num (Expression outer grp commons schemas params from (nullity ty)) where
380674 (+) = unsafeBinaryOp "+"
381675 (-) = unsafeBinaryOp "-"
382676 (*) = unsafeBinaryOp "*"
@@ -388,7 +682,7 @@ instance ty `In` PGNum
388682 . show
389683
390684instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
391− (Expression outer commons grp schemas params from (null ty)) where
685+ (Expression outer grp commons schemas params from (nullity ty)) where
392686 (/) = unsafeBinaryOp "/"
393687 fromRational
394688 = UnsafeExpression
@@ -398,7 +692,7 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
398692 . fromRat @Double
399693
400694instance (ty `In` PGNum, ty `In` PGFloating) => Floating
401− (Expression outer commons grp schemas params from (null ty)) where
695+ (Expression outer grp commons schemas params from (nullity ty)) where
402696 pi = UnsafeExpression "pi()"
403697 exp = unsafeFunction "exp"
404698 log = unsafeFunction "ln"
@@ -419,54 +713,1894 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
419713 acosh x = log (x + sqrt (x*x - 1))
420714 atanh x = log ((1 + x) / (1 - x)) / 2
421715
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)
716+-- | >>> :{
717+-- let
718+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
719+-- expression = atan2_ pi 2
720+-- in printSQL expression
721+-- :}
722+-- atan2(pi(), 2)
723+atan2_
724+ :: float `In` PGFloating
725+ => Expression outer grp commons schemas params from (nullity float)
726+ -- ^ numerator
727+ -> Expression outer grp commons schemas params from (nullity float)
728+ -- ^ denominator
729+ -> Expression outer grp commons schemas params from (nullity float)
730+atan2_ y x = UnsafeExpression $
731+ "atan2(" <> renderSQL y <> ", " <> renderSQL x <> ")"
732+
733+-- When a `cast` is applied to an `Expression` of a known type, it
734+-- represents a run-time type conversion. The cast will succeed only if a
735+-- suitable type conversion operation has been defined.
736+--
737+-- | >>> printSQL $ true & cast int4
738+-- (TRUE :: int4)
739+cast
740+ :: TypeExpression schemas ty1
741+ -- ^ type to cast as
742+ -> Expression outer grp commons schemas params from ty0
743+ -- ^ value to convert
744+ -> Expression outer grp commons schemas params from ty1
745+cast ty x = UnsafeExpression $ parenthesized $
746+ renderSQL x <+> "::" <+> renderSQL ty
747+
748+-- | integer division, truncates the result
749+--
750+-- >>> :{
751+-- let
752+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
753+-- expression = 5 `quot_` 2
754+-- in printSQL expression
755+-- :}
756+-- (5 / 2)
757+quot_
758+ :: int `In` PGIntegral
759+ => Operator (nullity int) (nullity int) (nullity int)
760+quot_ = unsafeBinaryOp "/"
761+
762+-- | remainder upon integer division
763+--
764+-- >>> :{
765+-- let
766+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
767+-- expression = 5 `rem_` 2
768+-- in printSQL expression
769+-- :}
770+-- (5 % 2)
771+rem_
772+ :: int `In` PGIntegral
773+ => Operator (nullity int) (nullity int) (nullity int)
774+rem_ = unsafeBinaryOp "%"
775+
776+-- | >>> :{
777+-- let
778+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
779+-- expression = trunc pi
780+-- in printSQL expression
781+-- :}
782+-- trunc(pi())
783+trunc
784+ :: frac `In` PGFloating
785+ => Expression outer grp commons schemas params from (nullity frac)
786+ -- ^ fractional number
787+ -> Expression outer grp commons schemas params from (nullity frac)
788+trunc = unsafeFunction "trunc"
789+
790+-- | >>> :{
791+-- let
792+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
793+-- expression = round_ pi
794+-- in printSQL expression
795+-- :}
796+-- round(pi())
797+round_
798+ :: frac `In` PGFloating
799+ => Expression outer grp commons schemas params from (nullity frac)
800+ -- ^ fractional number
801+ -> Expression outer grp commons schemas params from (nullity frac)
802+round_ = unsafeFunction "round"
803+
804+-- | >>> :{
805+-- let
806+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
807+-- expression = ceiling_ pi
808+-- in printSQL expression
809+-- :}
810+-- ceiling(pi())
811+ceiling_
812+ :: frac `In` PGFloating
813+ => Expression outer grp commons schemas params from (nullity frac)
814+ -- ^ fractional number
815+ -> Expression outer grp commons schemas params from (nullity frac)
816+ceiling_ = unsafeFunction "ceiling"
817+
818+-- | A `Condition` is an `Expression`, which can evaluate
819+-- to `true`, `false` or `null_`. This is because SQL uses
820+-- a three valued logic.
821+type Condition outer grp commons schemas params from =
822+ Expression outer grp commons schemas params from ('Null 'PGbool)
823+
824+-- | >>> printSQL true
825+-- TRUE
826+true :: Expression outer grp commons schemas params from (nullity 'PGbool)
827+true = UnsafeExpression "TRUE"
828+
829+-- | >>> printSQL false
830+-- FALSE
831+false :: Expression outer grp commons schemas params from (nullity 'PGbool)
832+false = UnsafeExpression "FALSE"
833+
834+-- | >>> printSQL $ not_ true
835+-- (NOT TRUE)
836+not_
837+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
838+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
839+not_ = unsafeUnaryOp "NOT"
840+
841+-- | >>> printSQL $ true .&& false
842+-- (TRUE AND FALSE)
843+(.&&) :: Operator (nullity 'PGbool) (nullity 'PGbool) (nullity 'PGbool)
844+infixr 3 .&&
845+(.&&) = unsafeBinaryOp "AND"
846+
847+-- | >>> printSQL $ true .|| false
848+-- (TRUE OR FALSE)
849+(.||) :: Operator (nullity 'PGbool) (nullity 'PGbool) (nullity 'PGbool)
850+infixr 2 .||
851+(.||) = unsafeBinaryOp "OR"
852+
853+-- | >>> :{
854+-- let
855+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
856+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
857+-- in printSQL expression
858+-- :}
859+-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
860+caseWhenThenElse
861+ :: [ ( Condition outer grp commons schemas params from
862+ , Expression outer grp commons schemas params from ty
863+ ) ]
864+ -- ^ whens and thens
865+ -> Expression outer grp commons schemas params from ty
866+ -- ^ else
867+ -> Expression outer grp commons schemas params from ty
868+caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
869+ [ "CASE"
870+ , mconcat
871+ [ mconcat
872+ [ " WHEN ", renderSQL when_
873+ , " THEN ", renderSQL then_
874+ ]
875+ | (when_,then_) <- whenThens
876+ ]
877+ , " ELSE ", renderSQL else_
878+ , " END"
879+ ]
880+
881+-- | >>> :{
882+-- let
883+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
884+-- expression = ifThenElse true 1 0
885+-- in printSQL expression
886+-- :}
887+-- CASE WHEN TRUE THEN 1 ELSE 0 END
888+ifThenElse
889+ :: Condition outer grp commons schemas params from
890+ -> Expression outer grp commons schemas params from ty -- ^ then
891+ -> Expression outer grp commons schemas params from ty -- ^ else
892+ -> Expression outer grp commons schemas params from ty
893+ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
894+
895+-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
896+-- will produce @NULL@s if one of their arguments is @NULL@.
897+--
898+-- >>> printSQL $ true .== null_
899+-- (TRUE = NULL)
900+(.==) :: Operator (nullity0 ty) (nullity1 ty) ('Null 'PGbool)
901+(.==) = unsafeBinaryOp "="
902+infix 4 .==
903+
904+-- | >>> printSQL $ true ./= null_
905+-- (TRUE <> NULL)
906+(./=) :: Operator (nullity0 ty) (nullity1 ty) ('Null 'PGbool)
907+(./=) = unsafeBinaryOp "<>"
908+infix 4 ./=
909+
910+-- | >>> printSQL $ true .>= null_
911+-- (TRUE >= NULL)
912+(.>=) :: Operator (nullity0 ty) (nullity1 ty) ('Null 'PGbool)
913+(.>=) = unsafeBinaryOp ">="
914+infix 4 .>=
915+
916+-- | >>> printSQL $ true .< null_
917+-- (TRUE < NULL)
918+(.<) :: Operator (nullity0 ty) (nullity1 ty) ('Null 'PGbool)
919+(.<) = unsafeBinaryOp "<"
920+infix 4 .<
921+
922+-- | >>> printSQL $ true .<= null_
923+-- (TRUE <= NULL)
924+(.<=) :: Operator (nullity0 ty) (nullity1 ty) ('Null 'PGbool)
925+(.<=) = unsafeBinaryOp "<="
926+infix 4 .<=
927+
928+-- | >>> printSQL $ true .> null_
929+-- (TRUE > NULL)
930+(.>) :: Operator (nullity0 ty) (nullity1 ty) ('Null 'PGbool)
931+(.>) = unsafeBinaryOp ">"
932+infix 4 .>
933+
934+{- | between
935+>>> printSQL $ true `between` (null_, false)
936+TRUE BETWEEN NULL AND FALSE
937+-}
938+between
939+ :: Expression outer grp commons schemas params from (nullity ty)
940+ -> ( Expression outer grp commons schemas params from (nullity ty)
941+ , Expression outer grp commons schemas params from (nullity ty) ) -- ^ bounds
942+ -> Condition outer grp commons schemas params from
943+between a (x,y) = UnsafeExpression $ renderSQL a <+> "BETWEEN"
944+ <+> renderSQL x <+> "AND" <+> renderSQL y
945+
946+{- | not between
947+>>> printSQL $ true `notBetween` (null_, false)
948+TRUE NOT BETWEEN NULL AND FALSE
949+-}
950+notBetween
951+ :: Expression outer grp commons schemas params from (nullity ty)
952+ -> ( Expression outer grp commons schemas params from (nullity ty)
953+ , Expression outer grp commons schemas params from (nullity ty) ) -- ^ bounds
954+ -> Condition outer grp commons schemas params from
955+notBetween a (x,y) = UnsafeExpression $ renderSQL a <+> "NOT BETWEEN"
956+ <+> renderSQL x <+> "AND" <+> renderSQL y
957+
958+{- | between, after sorting the comparison values
959+>>> printSQL $ true `betweenSymmetric` (null_, false)
960+TRUE BETWEEN SYMMETRIC NULL AND FALSE
961+-}
962+betweenSymmetric
963+ :: Expression outer grp commons schemas params from (nullity ty)
964+ -> ( Expression outer grp commons schemas params from (nullity ty)
965+ , Expression outer grp commons schemas params from (nullity ty) ) -- ^ bounds
966+ -> Condition outer grp commons schemas params from
967+betweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
968+ <+> "BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
969+
970+{- | not between, after sorting the comparison values
971+>>> printSQL $ true `notBetweenSymmetric` (null_, false)
972+TRUE NOT BETWEEN SYMMETRIC NULL AND FALSE
973+-}
974+notBetweenSymmetric
975+ :: Expression outer grp commons schemas params from (nullity ty)
976+ -> ( Expression outer grp commons schemas params from (nullity ty)
977+ , Expression outer grp commons schemas params from (nullity ty) ) -- ^ bounds
978+ -> Condition outer grp commons schemas params from
979+notBetweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
980+ <+> "NOT BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
981+
982+{- | not equal, treating null like an ordinary value
983+>>> printSQL $ true `isDistinctFrom` null_
984+(TRUE IS DISTINCT FROM NULL)
985+-}
986+isDistinctFrom :: Operator (nullity0 ty) (nullity1 ty) ('Null 'PGbool)
987+isDistinctFrom = unsafeBinaryOp "IS DISTINCT FROM"
988+
989+{- | equal, treating null like an ordinary value
990+>>> printSQL $ true `isNotDistinctFrom` null_
991+(TRUE IS NOT DISTINCT FROM NULL)
992+-}
993+isNotDistinctFrom :: Operator (nullity0 ty) (nullity1 ty) ('Null 'PGbool)
994+isNotDistinctFrom = unsafeBinaryOp "IS NOT DISTINCT FROM"
995+
996+{- | is true
997+>>> printSQL $ true & isTrue
998+TRUE IS TRUE
999+-}
1000+isTrue
1001+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1002+ -> Condition outer grp commons schemas params from
1003+isTrue b = UnsafeExpression $ renderSQL b <+> "IS TRUE"
1004+
1005+{- | is false or unknown
1006+>>> printSQL $ true & isNotTrue
1007+TRUE IS NOT TRUE
1008+-}
1009+isNotTrue
1010+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1011+ -> Condition outer grp commons schemas params from
1012+isNotTrue b = UnsafeExpression $ renderSQL b <+> "IS NOT TRUE"
1013+
1014+{- | is false
1015+>>> printSQL $ true & isFalse
1016+TRUE IS FALSE
1017+-}
1018+isFalse
1019+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1020+ -> Condition outer grp commons schemas params from
1021+isFalse b = UnsafeExpression $ renderSQL b <+> "IS FALSE"
1022+
1023+{- | is true or unknown
1024+>>> printSQL $ true & isNotFalse
1025+TRUE IS NOT FALSE
1026+-}
1027+isNotFalse
1028+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1029+ -> Condition outer grp commons schemas params from
1030+isNotFalse b = UnsafeExpression $ renderSQL b <+> "IS NOT FALSE"
1031+
1032+{- | is unknown
1033+>>> printSQL $ true & isUnknown
1034+TRUE IS UNKNOWN
1035+-}
1036+isUnknown
1037+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1038+ -> Condition outer grp commons schemas params from
1039+isUnknown b = UnsafeExpression $ renderSQL b <+> "IS UNKNOWN"
1040+
1041+{- | is true or false
1042+>>> printSQL $ true & isNotUnknown
1043+TRUE IS NOT UNKNOWN
1044+-}
1045+isNotUnknown
1046+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1047+ -> Condition outer grp commons schemas params from
1048+isNotUnknown b = UnsafeExpression $ renderSQL b <+> "IS NOT UNKNOWN"
1049+
1050+-- | >>> printSQL currentDate
1051+-- CURRENT_DATE
1052+currentDate
1053+ :: Expression outer grp commons schemas params from (nullity 'PGdate)
1054+currentDate = UnsafeExpression "CURRENT_DATE"
1055+
1056+-- | >>> printSQL currentTime
1057+-- CURRENT_TIME
1058+currentTime
1059+ :: Expression outer grp commons schemas params from (nullity 'PGtimetz)
1060+currentTime = UnsafeExpression "CURRENT_TIME"
1061+
1062+-- | >>> printSQL currentTimestamp
1063+-- CURRENT_TIMESTAMP
1064+currentTimestamp
1065+ :: Expression outer grp commons schemas params from (nullity 'PGtimestamptz)
1066+currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
1067+
1068+-- | >>> printSQL localTime
1069+-- LOCALTIME
1070+localTime
1071+ :: Expression outer grp commons schemas params from (nullity 'PGtime)
1072+localTime = UnsafeExpression "LOCALTIME"
1073+
1074+-- | >>> printSQL localTimestamp
1075+-- LOCALTIMESTAMP
1076+localTimestamp
1077+ :: Expression outer grp commons schemas params from (nullity 'PGtimestamp)
1078+localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
1079+
1080+{-----------------------------------------
1081+text
1082+-----------------------------------------}
1083+
1084+escape :: Char -> String
1085+escape = \case
1086+ '\NUL' -> "\\0"
1087+ '\'' -> "''"
1088+ '"' -> "\\\""
1089+ '\b' -> "\\b"
1090+ '\n' -> "\\n"
1091+ '\r' -> "\\r"
1092+ '\t' -> "\\t"
1093+ '\\' -> "\\\\"
1094+ c -> [c]
4381095
4391096instance IsString
440− (Expression outer commons grp schemas params from (null 'PGtext)) where
1097+ (Expression outer grp commons schemas params from (nullity 'PGtext)) where
4411098 fromString str = UnsafeExpression $
4421099 "E\'" <> fromString (escape =<< str) <> "\'"
4431100instance IsString
444− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
445− fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
1101+ (Expression outer grp commons schemas params from (nullity 'PGtsvector)) where
1102+ fromString str = cast tsvector . UnsafeExpression $
4461103 "E\'" <> fromString (escape =<< str) <> "\'"
4471104instance IsString
448− (Expression outer commons grp schemas params from (null 'PGtsquery)) where
449− fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
1105+ (Expression outer grp commons schemas params from (nullity 'PGtsquery)) where
1106+ fromString str = cast tsquery . UnsafeExpression $
4501107 "E\'" <> fromString (escape =<< str) <> "\'"
4511108
4521109instance 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
1110+ (Expression outer grp commons schemas params from (nullity 'PGtext)) where
4601111 (<>) = unsafeBinaryOp "||"
4611112instance Semigroup
462− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1113+ (Expression outer grp commons schemas params from (nullity 'PGtsvector)) where
4631114 (<>) = unsafeBinaryOp "||"
4641115
4651116instance Monoid
466− (Expression outer commons grp schemas params from (null 'PGtext)) where
1117+ (Expression outer grp commons schemas params from (nullity 'PGtext)) where
4671118 mempty = fromString ""
4681119 mappend = (<>)
4691120instance Monoid
470− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1121+ (Expression outer grp commons schemas params from (nullity 'PGtsvector)) where
4711122 mempty = fromString ""
4721123 mappend = (<>)
1124+
1125+-- | >>> printSQL $ lower "ARRRGGG"
1126+-- lower(E'ARRRGGG')
1127+lower
1128+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1129+ -- ^ string to lower case
1130+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1131+lower = unsafeFunction "lower"
1132+
1133+-- | >>> printSQL $ upper "eeee"
1134+-- upper(E'eeee')
1135+upper
1136+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1137+ -- ^ string to upper case
1138+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1139+upper = unsafeFunction "upper"
1140+
1141+-- | >>> printSQL $ charLength "four"
1142+-- char_length(E'four')
1143+charLength
1144+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1145+ -- ^ string to measure
1146+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1147+charLength = unsafeFunction "char_length"
1148+
1149+-- | The `like` expression returns true if the @string@ matches
1150+-- the supplied @pattern@. If @pattern@ does not contain percent signs
1151+-- or underscores, then the pattern only represents the string itself;
1152+-- in that case `like` acts like the equals operator. An underscore (_)
1153+-- in pattern stands for (matches) any single character; a percent sign (%)
1154+-- matches any sequence of zero or more characters.
1155+--
1156+-- >>> printSQL $ "abc" `like` "a%"
1157+-- (E'abc' LIKE E'a%')
1158+like :: Operator (nullity 'PGtext) (nullity 'PGtext) ('Null 'PGbool)
1159+like = unsafeBinaryOp "LIKE"
1160+
1161+-- | The key word ILIKE can be used instead of LIKE to make the
1162+-- match case-insensitive according to the active locale.
1163+--
1164+-- >>> printSQL $ "abc" `ilike` "a%"
1165+-- (E'abc' ILIKE E'a%')
1166+ilike :: Operator (nullity 'PGtext) (nullity 'PGtext) ('Null 'PGbool)
1167+ilike = unsafeBinaryOp "ILIKE"
1168+
1169+{-----------------------------------------
1170+ -- json and jsonb support
1171+
1172+See https://www.postgresql.org/docs/10/static/functions-json.html -- most
1173+comments lifted directly from this page.
1174+
1175+Table 9.44: json and jsonb operators
1176+-----------------------------------------}
1177+
1178+-- | Get JSON value (object field or array element) at a key.
1179+(.->)
1180+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1181+ => Operator (nullity json) (nullity key) ('Null json)
1182+infixl 8 .->
1183+(.->) = unsafeBinaryOp "->"
1184+
1185+-- | Get JSON value (object field or array element) at a key, as text.
1186+(.->>)
1187+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1188+ => Operator (nullity json) (nullity key) ('Null 'PGtext)
1189+infixl 8 .->>
1190+(.->>) = unsafeBinaryOp "->>"
1191+
1192+-- | Get JSON value at a specified path.
1193+(.#>)
1194+ :: (json `In` PGJsonType, PGTextArray "(.#>)" path)
1195+ => Operator (nullity json) (nullity path) ('Null json)
1196+infixl 8 .#>
1197+(.#>) = unsafeBinaryOp "#>"
1198+
1199+-- | Get JSON value at a specified path as text.
1200+(.#>>)
1201+ :: (json `In` PGJsonType, PGTextArray "(.#>>)" path)
1202+ => Operator (nullity json) (nullity path) ('Null 'PGtext)
1203+infixl 8 .#>>
1204+(.#>>) = unsafeBinaryOp "#>>"
1205+
1206+-- Additional jsonb operators
1207+
1208+-- | Does the left JSON value contain the right JSON path/value entries at the
1209+-- top level?
1210+(.@>)
1211+ :: Operator (nullity 'PGjsonb) (nullity 'PGjsonb) ('Null 'PGbool)
1212+infixl 9 .@>
1213+(.@>) = unsafeBinaryOp "@>"
1214+
1215+-- | Are the left JSON path/value entries contained at the top level within the
1216+-- right JSON value?
1217+(.<@) :: Operator (nullity 'PGjsonb) (nullity 'PGjsonb) ('Null 'PGbool)
1218+infixl 9 .<@
1219+(.<@) = unsafeBinaryOp "<@"
1220+
1221+-- | Does the string exist as a top-level key within the JSON value?
1222+(.?) :: Operator (nullity 'PGjsonb) (nullity 'PGtext) ('Null 'PGbool)
1223+infixl 9 .?
1224+(.?) = unsafeBinaryOp "?"
1225+
1226+-- | Do any of these array strings exist as top-level keys?
1227+(.?|) :: Operator
1228+ (nullity 'PGjsonb)
1229+ (nullity ('PGvararray ('NotNull 'PGtext)))
1230+ ('Null 'PGbool)
1231+infixl 9 .?|
1232+(.?|) = unsafeBinaryOp "?|"
1233+
1234+-- | Do all of these array strings exist as top-level keys?
1235+(.?&) :: Operator
1236+ (nullity 'PGjsonb)
1237+ (nullity ('PGvararray ('NotNull 'PGtext)))
1238+ ('Null 'PGbool)
1239+infixl 9 .?&
1240+(.?&) = unsafeBinaryOp "?&"
1241+
1242+-- | Concatenate two jsonb values into a new jsonb value.
1243+instance Semigroup
1244+ (Expression outer grp commons schemas params from (nullity 'PGjsonb)) where
1245+ (<>) = unsafeBinaryOp "||"
1246+
1247+-- | Delete a key or keys from a JSON object, or remove an array element.
1248+--
1249+-- If the right operand is..
1250+--
1251+-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1252+-- are matched based on their key value.
1253+--
1254+-- @ text[] @: Delete multiple key/value pairs or string elements
1255+-- from left operand. Key/value pairs are matched based on their key value.
1256+--
1257+-- @ integer @: Delete the array element with specified index (Negative integers
1258+-- count from the end). Throws an error if top level container is not an array.
1259+(.-.)
1260+ :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1261+ => Operator (nullity 'PGjsonb) (nullity key) (nullity 'PGjsonb)
1262+infixl 6 .-.
1263+(.-.) = unsafeBinaryOp "-"
1264+
1265+-- | Delete the field or element with specified path (for JSON arrays, negative
1266+-- integers count from the end)
1267+(#-.)
1268+ :: PGTextArray "(#-.)" arrayty
1269+ => Operator (nullity 'PGjsonb) (nullity arrayty)(nullity 'PGjsonb)
1270+infixl 6 #-.
1271+(#-.) = unsafeBinaryOp "#-"
1272+
1273+{-----------------------------------------
1274+Table 9.45: JSON creation functions
1275+-----------------------------------------}
1276+
1277+-- | Literal binary JSON
1278+jsonbLit
1279+ :: JSON.ToJSON x
1280+ => x -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1281+jsonbLit = cast jsonb . UnsafeExpression
1282+ . singleQuotedUtf8 . toStrict . JSON.encode
1283+
1284+-- | Literal JSON
1285+jsonLit
1286+ :: JSON.ToJSON x
1287+ => x -> Expression outer grp commons schemas params from (nullity 'PGjson)
1288+jsonLit = cast json . UnsafeExpression
1289+ . singleQuotedUtf8 . toStrict . JSON.encode
1290+
1291+-- | Returns the value as json. Arrays and composites are converted
1292+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1293+-- type to json, the cast function will be used to perform the conversion;
1294+-- otherwise, a scalar value is produced. For any scalar type other than a
1295+-- number, a Boolean, or a null value, the text representation will be used, in
1296+-- such a fashion that it is a valid json value.
1297+toJson
1298+ :: Expression outer grp commons schemas params from (nullity ty)
1299+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1300+toJson = unsafeFunction "to_json"
1301+
1302+-- | Returns the value as jsonb. Arrays and composites are converted
1303+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1304+-- type to json, the cast function will be used to perform the conversion;
1305+-- otherwise, a scalar value is produced. For any scalar type other than a
1306+-- number, a Boolean, or a null value, the text representation will be used, in
1307+-- such a fashion that it is a valid jsonb value.
1308+toJsonb
1309+ :: Expression outer grp commons schemas params from (nullity ty)
1310+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1311+toJsonb = unsafeFunction "to_jsonb"
1312+
1313+-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1314+-- becomes a JSON array of arrays.
1315+arrayToJson
1316+ :: PGArray "arrayToJson" arr
1317+ => Expression outer grp commons schemas params from (nullity arr)
1318+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1319+arrayToJson = unsafeFunction "array_to_json"
1320+
1321+-- | Returns the row as a JSON object.
1322+rowToJson
1323+ :: Expression outer grp commons schemas params from (nullity ('PGcomposite ty))
1324+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1325+rowToJson = unsafeFunction "row_to_json"
1326+
1327+-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1328+-- argument list.
1329+jsonBuildArray
1330+ :: SListI elems
1331+ => NP (Expression outer grp commons schemas params from) elems
1332+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1333+jsonBuildArray = unsafeVariadicFunction "json_build_array"
1334+
1335+-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1336+-- variadic argument list.
1337+jsonbBuildArray
1338+ :: SListI elems
1339+ => NP (Expression outer grp commons schemas params from) elems
1340+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1341+jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1342+
1343+unsafeRowFunction
1344+ :: SOP.SListI elems
1345+ => NP (Aliased (Expression outer grp commons schemas params from)) elems
1346+ -> [ByteString]
1347+unsafeRowFunction =
1348+ (`appEndo` []) . hcfoldMap (Proxy :: SOP.Proxy SOP.Top)
1349+ (\(col `As` name) -> Endo $ \xs ->
1350+ renderAliasString name : renderSQL col : xs)
1351+ where
1352+ renderAliasString :: KnownSymbol alias => Alias alias -> ByteString
1353+ renderAliasString = singleQuotedText . fromString . symbolVal
1354+
1355+-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1356+-- argument list. The elements of the argument list must alternate between text
1357+-- and values.
1358+jsonBuildObject
1359+ :: SOP.SListI elems
1360+ => NP (Aliased (Expression outer grp commons schemas params from)) elems
1361+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1362+jsonBuildObject
1363+ = unsafeFunction "json_build_object"
1364+ . UnsafeExpression
1365+ . commaSeparated
1366+ . unsafeRowFunction
1367+
1368+-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1369+-- variadic argument list. The elements of the argument list must alternate
1370+-- between text and values.
1371+jsonbBuildObject
1372+ :: SOP.SListI elems
1373+ => NP (Aliased (Expression outer grp commons schemas params from)) elems
1374+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1375+jsonbBuildObject
1376+ = unsafeFunction "jsonb_build_object"
1377+ . UnsafeExpression
1378+ . commaSeparated
1379+ . unsafeRowFunction
1380+
1381+-- | Builds a JSON object out of a text array. The array must have either
1382+-- exactly one dimension with an even number of members, in which case they are
1383+-- taken as alternating key/value pairs, or two dimensions such that each inner
1384+-- array has exactly two elements, which are taken as a key/value pair.
1385+jsonObject
1386+ :: PGArrayOf "jsonObject" arr ('NotNull 'PGtext)
1387+ => Expression outer grp commons schemas params from (nullity arr)
1388+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1389+jsonObject = unsafeFunction "json_object"
1390+
1391+-- | Builds a binary JSON object out of a text array. The array must have either
1392+-- exactly one dimension with an even number of members, in which case they are
1393+-- taken as alternating key/value pairs, or two dimensions such that each inner
1394+-- array has exactly two elements, which are taken as a key/value pair.
1395+jsonbObject
1396+ :: PGArrayOf "jsonbObject" arr ('NotNull 'PGtext)
1397+ => Expression outer grp commons schemas params from (nullity arr)
1398+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1399+jsonbObject = unsafeFunction "jsonb_object"
1400+
1401+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1402+-- keys and one for values, that are zipped pairwise to create a JSON object.
1403+jsonZipObject
1404+ :: ( PGArrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1405+ , PGArrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
1406+ => Expression outer grp commons schemas params from (nullity keysArray)
1407+ -> Expression outer grp commons schemas params from (nullity valuesArray)
1408+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1409+jsonZipObject ks vs =
1410+ unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1411+
1412+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1413+-- keys and one for values, that are zipped pairwise to create a binary JSON
1414+-- object.
1415+jsonbZipObject
1416+ :: ( PGArrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1417+ , PGArrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
1418+ => Expression outer grp commons schemas params from (nullity keysArray)
1419+ -> Expression outer grp commons schemas params from (nullity valuesArray)
1420+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1421+jsonbZipObject ks vs =
1422+ unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1423+
1424+{-----------------------------------------
1425+Table 9.46: JSON processing functions
1426+-----------------------------------------}
1427+
1428+-- | Returns the number of elements in the outermost JSON array.
1429+jsonArrayLength
1430+ :: Expression outer grp commons schemas params from (nullity 'PGjson)
1431+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1432+jsonArrayLength = unsafeFunction "json_array_length"
1433+
1434+-- | Returns the number of elements in the outermost binary JSON array.
1435+jsonbArrayLength
1436+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1437+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1438+jsonbArrayLength = unsafeFunction "jsonb_array_length"
1439+
1440+-- | Returns JSON value pointed to by the given path (equivalent to #>
1441+-- operator).
1442+jsonExtractPath
1443+ :: SListI elems
1444+ => Expression outer grp commons schemas params from (nullity 'PGjson)
1445+ -> NP (Expression outer grp commons schemas params from) elems
1446+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1447+jsonExtractPath x xs =
1448+ unsafeVariadicFunction "json_extract_path" (x :* xs)
1449+
1450+-- | Returns JSON value pointed to by the given path (equivalent to #>
1451+-- operator).
1452+jsonbExtractPath
1453+ :: SListI elems
1454+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1455+ -> NP (Expression outer grp commons schemas params from) elems
1456+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1457+jsonbExtractPath x xs =
1458+ unsafeVariadicFunction "jsonb_extract_path" (x :* xs)
1459+
1460+-- | Returns JSON value pointed to by the given path (equivalent to #>
1461+-- operator), as text.
1462+jsonExtractPathAsText
1463+ :: SListI elems
1464+ => Expression outer grp commons schemas params from (nullity 'PGjson)
1465+ -> NP (Expression outer grp commons schemas params from) elems
1466+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1467+jsonExtractPathAsText x xs =
1468+ unsafeVariadicFunction "json_extract_path_text" (x :* xs)
1469+
1470+-- | Returns JSON value pointed to by the given path (equivalent to #>
1471+-- operator), as text.
1472+jsonbExtractPathAsText
1473+ :: SListI elems
1474+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1475+ -> NP (Expression outer grp commons schemas params from) elems
1476+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1477+jsonbExtractPathAsText x xs =
1478+ unsafeVariadicFunction "jsonb_extract_path_text" (x :* xs)
1479+
1480+-- | Returns the type of the outermost JSON value as a text string. Possible
1481+-- types are object, array, string, number, boolean, and null.
1482+jsonTypeof
1483+ :: Expression outer grp commons schemas params from (nullity 'PGjson)
1484+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1485+jsonTypeof = unsafeFunction "json_typeof"
1486+
1487+-- | Returns the type of the outermost binary JSON value as a text string.
1488+-- Possible types are object, array, string, number, boolean, and null.
1489+jsonbTypeof
1490+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1491+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1492+jsonbTypeof = unsafeFunction "jsonb_typeof"
1493+
1494+-- | Returns its argument with all object fields that have null values omitted.
1495+-- Other null values are untouched.
1496+jsonStripNulls
1497+ :: Expression outer grp commons schemas params from (nullity 'PGjson)
1498+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1499+jsonStripNulls = unsafeFunction "json_strip_nulls"
1500+
1501+-- | Returns its argument with all object fields that have null values omitted.
1502+-- Other null values are untouched.
1503+jsonbStripNulls
1504+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1505+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1506+jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1507+
1508+-- | @ jsonbSet target path new_value create_missing @
1509+--
1510+-- Returns target with the section designated by path replaced by new_value,
1511+-- or with new_value added if create_missing is true ( default is true) and the
1512+-- item designated by path does not exist. As with the path orientated
1513+-- operators, negative integers that appear in path count from the end of JSON
1514+-- arrays.
1515+jsonbSet
1516+ :: PGTextArray "jsonbSet" arr
1517+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1518+ -> Expression outer grp commons schemas params from (nullity arr)
1519+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1520+ -> Maybe (Expression outer grp commons schemas params from (nullity 'PGbool))
1521+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1522+jsonbSet tgt path val createMissing = case createMissing of
1523+ Just m -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* m :* Nil)
1524+ Nothing -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* Nil)
1525+
1526+-- | @ jsonbInsert target path new_value insert_after @
1527+--
1528+-- Returns target with new_value inserted. If target section designated by
1529+-- path is in a JSONB array, new_value will be inserted before target or after
1530+-- if insert_after is true (default is false). If target section designated by
1531+-- path is in JSONB object, new_value will be inserted only if target does not
1532+-- exist. As with the path orientated operators, negative integers that appear
1533+-- in path count from the end of JSON arrays.
1534+jsonbInsert
1535+ :: PGTextArray "jsonbInsert" arr
1536+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1537+ -> Expression outer grp commons schemas params from (nullity arr)
1538+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1539+ -> Maybe (Expression outer grp commons schemas params from (nullity 'PGbool))
1540+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1541+jsonbInsert tgt path val insertAfter = case insertAfter of
1542+ Just i -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1543+ Nothing -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* Nil)
1544+
1545+-- | Returns its argument as indented JSON text.
1546+jsonbPretty
1547+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1548+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1549+jsonbPretty = unsafeFunction "jsonb_pretty"
1550+
1551+(@@) :: Operator (nullity 'PGtsvector) (nullity 'PGtsquery) ('Null 'PGbool)
1552+(@@) = unsafeBinaryOp "@@"
1553+
1554+(.&) :: Operator (nullity 'PGtsquery) (nullity 'PGtsquery) (nullity 'PGtsquery)
1555+(.&) = unsafeBinaryOp "&&"
1556+
1557+(.|) :: Operator (nullity 'PGtsquery) (nullity 'PGtsquery) (nullity 'PGtsquery)
1558+(.|) = unsafeBinaryOp "||"
1559+
1560+(.!)
1561+ :: Expression outer grp commons schemas params from (nullity 'PGtsquery)
1562+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1563+(.!) = unsafeUnaryOp "!!"
1564+
1565+(<->) :: Operator (nullity 'PGtsquery) (nullity 'PGtsquery) (nullity 'PGtsquery)
1566+(<->) = unsafeBinaryOp "<->"
1567+
1568+arrayToTSvector
1569+ :: Expression outer grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1570+ -> Expression outer grp commons schemas params from (nullity 'PGtsvector)
1571+arrayToTSvector = unsafeFunction "array_to_tsvector"
1572+
1573+tsvectorLength
1574+ :: Expression outer grp commons schemas params from (nullity 'PGtsvector)
1575+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1576+tsvectorLength = unsafeFunction "length"
1577+
1578+numnode
1579+ :: Expression outer grp commons schemas params from (nullity 'PGtsquery)
1580+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1581+numnode = unsafeFunction "numnode"
1582+
1583+plainToTSquery
1584+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1585+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1586+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1587+plainToTSquery = unsafeFunction2 "plainto_tsquery"
1588+
1589+phraseToTSquery
1590+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1591+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1592+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1593+phraseToTSquery = unsafeFunction2 "phraseto_tsquery"
1594+
1595+websearchToTSquery
1596+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1597+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1598+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1599+websearchToTSquery = unsafeFunction2 "websearch_to_tsquery"
1600+
1601+queryTree
1602+ :: Expression outer grp commons schemas params from (nullity 'PGtsquery)
1603+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1604+queryTree = unsafeFunction "query_tree"
1605+
1606+toTSquery
1607+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1608+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1609+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1610+toTSquery = unsafeFunction2 "to_tsquery"
1611+
1612+toTSvector
1613+ :: ty `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1614+ => Expression outer grp commons schemas params from (nullity 'PGtext)
1615+ -> Expression outer grp commons schemas params from (nullity ty)
1616+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1617+toTSvector = unsafeFunction2 "to_tsvector"
1618+
1619+{-----------------------------------------
1620+aggregation
1621+-----------------------------------------}
1622+
1623+{- |
1624+`Aggregate` functions compute a single result from a set of input values.
1625+`Aggregate` functions can be used as `GroupedBy` `Expression`s as well
1626+as `WindowFunction`s.
1627+-}
1628+class Aggregate expr1 expr2 aggr
1629+ | aggr -> expr1, aggr -> expr2 where
1630+
1631+ -- | A special aggregation that does not require an input
1632+ --
1633+ -- >>> :{
1634+ -- let
1635+ -- expression :: Expression '[] ('Grouped bys) commons schemas params from ('NotNull 'PGint8)
1636+ -- expression = countStar
1637+ -- in printSQL expression
1638+ -- :}
1639+ -- count(*)
1640+ countStar :: aggr ('NotNull 'PGint8)
1641+
1642+ -- | >>> :{
1643+ -- let
1644+ -- expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1645+ -- expression = count (All #col)
1646+ -- in printSQL expression
1647+ -- :}
1648+ -- count(ALL "col")
1649+ count
1650+ :: expr1 ty
1651+ -- ^ what to count
1652+ -> aggr ('NotNull 'PGint8)
1653+
1654+ -- | >>> :{
1655+ -- let
1656+ -- expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('NotNull 'PGnumeric)
1657+ -- expression = sum_ (Distinct #col)
1658+ -- in printSQL expression
1659+ -- :}
1660+ -- sum(DISTINCT "col")
1661+ sum_
1662+ :: ty `In` PGNum
1663+ => expr1 (nullity ty)
1664+ -> aggr ('NotNull ty)
1665+
1666+ -- | input values, including nulls, concatenated into an array
1667+ arrayAgg
1668+ :: expr1 ty
1669+ -> aggr ('Null ('PGvararray ty))
1670+
1671+ -- | aggregates values as a JSON array
1672+ jsonAgg
1673+ :: expr1 ty
1674+ -> aggr ('Null 'PGjson)
1675+
1676+ -- | aggregates values as a JSON array
1677+ jsonbAgg
1678+ :: expr1 ty
1679+ -> aggr ('Null 'PGjsonb)
1680+
1681+ {- |
1682+ the bitwise AND of all non-null input values, or null if none
1683+ >>> :{
1684+ let
1685+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] ('Null 'PGint4)
1686+ expression = bitAnd (Distinct #col)
1687+ in printSQL expression
1688+ :}
1689+ bit_and(DISTINCT "col")
1690+ -}
1691+ bitAnd
1692+ :: int `In` PGIntegral
1693+ => expr1 (nullity int)
1694+ -- ^ what to aggregate
1695+ -> aggr ('Null int)
1696+
1697+ {- |
1698+ the bitwise OR of all non-null input values, or null if none
1699+
1700+ >>> :{
1701+ let
1702+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] ('Null 'PGint4)
1703+ expression = bitOr (All #col)
1704+ in printSQL expression
1705+ :}
1706+ bit_or(ALL "col")
1707+ -}
1708+ bitOr
1709+ :: int `In` PGIntegral
1710+ => expr1 (nullity int)
1711+ -- ^ what to aggregate
1712+ -> aggr ('Null int)
1713+
1714+ {- |
1715+ true if all input values are true, otherwise false
1716+
1717+ >>> :{
1718+ let
1719+ winFun :: WindowFunction '[] 'Ungrouped commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] ('Null 'PGbool)
1720+ winFun = boolAnd #col
1721+ in printSQL winFun
1722+ :}
1723+ bool_and("col")
1724+ -}
1725+ boolAnd
1726+ :: expr1 (nullity 'PGbool)
1727+ -- ^ what to aggregate
1728+ -> aggr ('Null 'PGbool)
1729+
1730+ {- |
1731+ true if at least one input value is true, otherwise false
1732+
1733+ >>> :{
1734+ let
1735+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] ('Null 'PGbool)
1736+ expression = boolOr (All #col)
1737+ in printSQL expression
1738+ :}
1739+ bool_or(ALL "col")
1740+ -}
1741+ boolOr
1742+ :: expr1(nullity 'PGbool)
1743+ -- ^ what to aggregate
1744+ -> aggr ('Null 'PGbool)
1745+
1746+ {- |
1747+ equivalent to `boolAnd`
1748+
1749+ >>> :{
1750+ let
1751+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] ('Null 'PGbool)
1752+ expression = every (Distinct #col)
1753+ in printSQL expression
1754+ :}
1755+ every(DISTINCT "col")
1756+ -}
1757+ every
1758+ :: expr1 (nullity 'PGbool)
1759+ -- ^ what to aggregate
1760+ -> aggr ('Null 'PGbool)
1761+
1762+ {- |maximum value of expression across all input values-}
1763+ max_
1764+ :: expr1 (nullity ty)
1765+ -- ^ what to maximize
1766+ -> aggr ('Null ty)
1767+
1768+ -- | minimum value of expression across all input values
1769+ min_
1770+ :: expr1 (nullity ty)
1771+ -- ^ what to minimize
1772+ -> aggr ('Null ty)
1773+
1774+ -- | the average (arithmetic mean) of all input values
1775+ avg
1776+ :: expr1 (nullity ty)
1777+ -- ^ what to average
1778+ -> aggr ('Null (PGAvg ty))
1779+
1780+ {- | correlation coefficient
1781+ >>> :{
1782+ let
1783+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1784+ expression = corr (All (#y :*: #x))
1785+ in printSQL expression
1786+ :}
1787+ corr(ALL "y", "x")
1788+ -}
1789+ corr
1790+ :: expr2 (nullity 'PGfloat8)
1791+ -> aggr ('Null 'PGfloat8)
1792+
1793+ {- | population covariance
1794+ >>> :{
1795+ let
1796+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1797+ expression = covarPop (All (#y :*: #x))
1798+ in printSQL expression
1799+ :}
1800+ covar_pop(ALL "y", "x")
1801+ -}
1802+ covarPop
1803+ :: expr2 (nullity 'PGfloat8)
1804+ -> aggr ('Null 'PGfloat8)
1805+
1806+ {- | sample covariance
1807+ >>> :{
1808+ let
1809+ winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1810+ winFun = covarSamp (#y :*: #x)
1811+ in printSQL winFun
1812+ :}
1813+ covar_samp("y", "x")
1814+ -}
1815+ covarSamp
1816+ :: expr2 (nullity 'PGfloat8)
1817+ -> aggr ('Null 'PGfloat8)
1818+
1819+ {- | average of the independent variable (sum(X)/N)
1820+ >>> :{
1821+ let
1822+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1823+ expression = regrAvgX (All (#y :*: #x))
1824+ in printSQL expression
1825+ :}
1826+ regr_avgx(ALL "y", "x")
1827+ -}
1828+ regrAvgX
1829+ :: expr2 (nullity 'PGfloat8)
1830+ -> aggr ('Null 'PGfloat8)
1831+
1832+ {- | average of the dependent variable (sum(Y)/N)
1833+ >>> :{
1834+ let
1835+ winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1836+ winFun = regrAvgY (#y :*: #x)
1837+ in printSQL winFun
1838+ :}
1839+ regr_avgy("y", "x")
1840+ -}
1841+ regrAvgY
1842+ :: expr2 (nullity 'PGfloat8)
1843+ -> aggr ('Null 'PGfloat8)
1844+
1845+ {- | number of input rows in which both expressions are nonnull
1846+ >>> :{
1847+ let
1848+ winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGint8)
1849+ winFun = regrCount (#y :*: #x)
1850+ in printSQL winFun
1851+ :}
1852+ regr_count("y", "x")
1853+ -}
1854+ regrCount
1855+ :: expr2 (nullity 'PGfloat8)
1856+ -> aggr ('Null 'PGint8)
1857+
1858+ {- | y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs
1859+ >>> :{
1860+ let
1861+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1862+ expression = regrIntercept (All (#y :*: #x))
1863+ in printSQL expression
1864+ :}
1865+ regr_intercept(ALL "y", "x")
1866+ -}
1867+ regrIntercept
1868+ :: expr2 (nullity 'PGfloat8)
1869+ -> aggr ('Null 'PGfloat8)
1870+
1871+ -- | @regr_r2(Y, X)@, square of the correlation coefficient
1872+ regrR2
1873+ :: expr2 (nullity 'PGfloat8)
1874+ -> aggr ('Null 'PGfloat8)
1875+
1876+ -- | @regr_slope(Y, X)@, slope of the least-squares-fit linear equation
1877+ -- determined by the (X, Y) pairs
1878+ regrSlope
1879+ :: expr2 (nullity 'PGfloat8)
1880+ -> aggr ('Null 'PGfloat8)
1881+
1882+ -- | @regr_sxx(Y, X)@, sum(X^2) - sum(X)^2/N
1883+ -- (“sum of squares” of the independent variable)
1884+ regrSxx
1885+ :: expr2 (nullity 'PGfloat8)
1886+ -> aggr ('Null 'PGfloat8)
1887+
1888+ -- | @regr_sxy(Y, X)@, sum(X*Y) - sum(X) * sum(Y)/N
1889+ -- (“sum of products” of independent times dependent variable)
1890+ regrSxy
1891+ :: expr2 (nullity 'PGfloat8)
1892+ -> aggr ('Null 'PGfloat8)
1893+
1894+ -- | @regr_syy(Y, X)@, sum(Y^2) - sum(Y)^2/N
1895+ -- (“sum of squares” of the dependent variable)
1896+ regrSyy
1897+ :: expr2 (nullity 'PGfloat8)
1898+ -> aggr ('Null 'PGfloat8)
1899+
1900+ -- | historical alias for `stddevSamp`
1901+ stddev
1902+ :: expr1 (nullity ty)
1903+ -> aggr ('Null (PGAvg ty))
1904+
1905+ -- | population standard deviation of the input values
1906+ stddevPop
1907+ :: expr1 (nullity ty)
1908+ -> aggr ('Null (PGAvg ty))
1909+
1910+ -- | sample standard deviation of the input values
1911+ stddevSamp
1912+ :: expr1 (nullity ty)
1913+ -> aggr ('Null (PGAvg ty))
1914+
1915+ -- | historical alias for `varSamp`
1916+ variance
1917+ :: expr1 (nullity ty)
1918+ -> aggr ('Null (PGAvg ty))
1919+
1920+ -- | population variance of the input values
1921+ -- (square of the population standard deviation)
1922+ varPop
1923+ :: expr1 (nullity ty)
1924+ -> aggr ('Null (PGAvg ty))
1925+
1926+ -- | sample variance of the input values
1927+ -- (square of the sample standard deviation)
1928+ varSamp
1929+ :: expr1 (nullity ty)
1930+ -> aggr ('Null (PGAvg ty))
1931+
1932+{- |
1933+`Distinction`s are used for the input of `Aggregate` `Expression`s.
1934+`All` invokes the aggregate once for each input row.
1935+`Distinct` invokes the aggregate once for each distinct value of the expression
1936+(or distinct set of values, for multiple expressions) found in the input
1937+-}
1938+data Distinction expr ty
1939+ = All (expr ty)
1940+ | Distinct (expr ty)
1941+ deriving (GHC.Generic,Show,Eq,Ord)
1942+instance NFData (Distinction (Expression outer grp commons schemas params from) ty)
1943+instance RenderSQL (Distinction (Expression outer grp commons schemas params from) ty) where
1944+ renderSQL = \case
1945+ All x -> "ALL" <+> renderSQL x
1946+ Distinct x -> "DISTINCT" <+> renderSQL x
1947+instance RenderSQL
1948+ (Distinction
1949+ ( Expression outer grp commons schemas params from
1950+ :*:
1951+ Expression outer grp commons schemas params from) xty ) where
1952+ renderSQL = \case
1953+ All (x :*: x') ->
1954+ "ALL" <+> renderSQL x <> ", " <> renderSQL x'
1955+ Distinct (x :*: x') ->
1956+ "DISTINCT" <+> renderSQL x <> ", " <> renderSQL x'
1957+
1958+instance Aggregate
1959+ (Distinction (Expression outer 'Ungrouped commons schemas params from))
1960+ (Distinction (Expression outer 'Ungrouped commons schemas params from :*: Expression outer 'Ungrouped commons schemas params from))
1961+ (Expression outer ('Grouped bys) commons schemas params from) where
1962+ countStar = UnsafeExpression "count(*)"
1963+ count = unsafeAggregate1 "count"
1964+ sum_ = unsafeAggregate1 "sum"
1965+ arrayAgg = unsafeAggregate1 "array_agg"
1966+ jsonAgg = unsafeAggregate1 "json_agg"
1967+ jsonbAgg = unsafeAggregate1 "jsonb_agg"
1968+ bitAnd = unsafeAggregate1 "bit_and"
1969+ bitOr = unsafeAggregate1 "bit_or"
1970+ boolAnd = unsafeAggregate1 "bool_and"
1971+ boolOr = unsafeAggregate1 "bool_or"
1972+ every = unsafeAggregate1 "every"
1973+ max_ = unsafeAggregate1 "max"
1974+ min_ = unsafeAggregate1 "min"
1975+ avg = unsafeAggregate1 "avg"
1976+ corr = unsafeAggregate2 "corr"
1977+ covarPop = unsafeAggregate2 "covar_pop"
1978+ covarSamp = unsafeAggregate2 "covar_samp"
1979+ regrAvgX = unsafeAggregate2 "regr_avgx"
1980+ regrAvgY = unsafeAggregate2 "regr_avgy"
1981+ regrCount = unsafeAggregate2 "regr_count"
1982+ regrIntercept = unsafeAggregate2 "regr_intercept"
1983+ regrR2 = unsafeAggregate2 "regr_r2"
1984+ regrSlope = unsafeAggregate2 "regr_slope"
1985+ regrSxx = unsafeAggregate2 "regr_sxx"
1986+ regrSxy = unsafeAggregate2 "regr_sxy"
1987+ regrSyy = unsafeAggregate2 "regr_syy"
1988+ stddev = unsafeAggregate1 "stddev"
1989+ stddevPop = unsafeAggregate1 "stddev_pop"
1990+ stddevSamp = unsafeAggregate1 "stddev_samp"
1991+ variance = unsafeAggregate1 "variance"
1992+ varPop = unsafeAggregate1 "var_pop"
1993+ varSamp = unsafeAggregate1 "var_samp"
1994+instance Aggregate
1995+ (Expression outer grp commons schemas params from)
1996+ (Expression outer grp commons schemas params from :*: Expression outer grp commons schemas params from)
1997+ (WindowFunction outer grp commons schemas params from) where
1998+ countStar = UnsafeWindowFunction "count(*)"
1999+ count = unsafeWindowFunction1 "count"
2000+ sum_ = unsafeWindowFunction1 "sum"
2001+ arrayAgg = unsafeWindowFunction1 "array_agg"
2002+ jsonAgg = unsafeWindowFunction1 "json_agg"
2003+ jsonbAgg = unsafeWindowFunction1 "jsonb_agg"
2004+ bitAnd = unsafeWindowFunction1 "bit_and"
2005+ bitOr = unsafeWindowFunction1 "bit_or"
2006+ boolAnd = unsafeWindowFunction1 "bool_and"
2007+ boolOr = unsafeWindowFunction1 "bool_or"
2008+ every = unsafeWindowFunction1 "every"
2009+ max_ = unsafeWindowFunction1 "max"
2010+ min_ = unsafeWindowFunction1 "min"
2011+ avg = unsafeWindowFunction1 "avg"
2012+ corr = unsafeWindowFunction2 "corr"
2013+ covarPop = unsafeWindowFunction2 "covar_pop"
2014+ covarSamp = unsafeWindowFunction2 "covar_samp"
2015+ regrAvgX = unsafeWindowFunction2 "regr_avgx"
2016+ regrAvgY = unsafeWindowFunction2 "regr_avgy"
2017+ regrCount = unsafeWindowFunction2 "regr_count"
2018+ regrIntercept = unsafeWindowFunction2 "regr_intercept"
2019+ regrR2 = unsafeWindowFunction2 "regr_r2"
2020+ regrSlope = unsafeWindowFunction2 "regr_slope"
2021+ regrSxx = unsafeWindowFunction2 "regr_sxx"
2022+ regrSxy = unsafeWindowFunction2 "regr_sxy"
2023+ regrSyy = unsafeWindowFunction2 "regr_syy"
2024+ stddev = unsafeWindowFunction1 "stddev"
2025+ stddevPop = unsafeWindowFunction1 "stddev_pop"
2026+ stddevSamp = unsafeWindowFunction1 "stddev_samp"
2027+ variance = unsafeWindowFunction1 "variance"
2028+ varPop = unsafeWindowFunction1 "var_pop"
2029+ varSamp = unsafeWindowFunction1 "var_samp"
2030+
2031+-- | escape hatch to define aggregate functions
2032+unsafeAggregate1
2033+ :: ByteString -- ^ aggregate function
2034+ -> Distinction (Expression outer 'Ungrouped commons schemas params from) xty
2035+ -> Expression outer ('Grouped bys) commons schemas params from yty
2036+unsafeAggregate1 fun x = UnsafeExpression $ mconcat
2037+ [fun, "(", renderSQL x, ")"]
2038+
2039+-- | escape hatch to define aggregate binary functions
2040+unsafeAggregate2
2041+ :: ByteString -- ^ aggregate function
2042+ -> Distinction (Expression outer 'Ungrouped commons schemas params from :*: Expression outer 'Ungrouped commons schemas params from) xty
2043+ -> Expression outer ('Grouped bys) commons schemas params from yty
2044+unsafeAggregate2 fun xx = UnsafeExpression $ mconcat
2045+ [fun, "(", renderSQL xx, ")"]
2046+
2047+-- | A type family that calculates `PGAvg` type of a `PGType`.
2048+type family PGAvg ty where
2049+ PGAvg 'PGint2 = 'PGnumeric
2050+ PGAvg 'PGint4 = 'PGnumeric
2051+ PGAvg 'PGint8 = 'PGnumeric
2052+ PGAvg 'PGnumeric = 'PGnumeric
2053+ PGAvg 'PGfloat4 = 'PGfloat8
2054+ PGAvg 'PGfloat8 = 'PGfloat8
2055+ PGAvg 'PGinterval = 'PGinterval
2056+ PGAvg pg = TypeError
2057+ ('Text "Squeal type error: No average for " ':<>: 'ShowType pg)
2058+
2059+{-----------------------------------------
2060+type expressions
2061+-----------------------------------------}
2062+
2063+-- | `TypeExpression`s are used in `cast`s and
2064+-- `Squeal.PostgreSQL.Definition.createTable` commands.
2065+newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
2066+ = UnsafeTypeExpression { renderTypeExpression :: ByteString }
2067+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
2068+instance RenderSQL (TypeExpression schemas ty) where
2069+ renderSQL = renderTypeExpression
2070+
2071+-- | The enum or composite type in a `Typedef` can be expressed by its alias.
2072+typedef
2073+ :: (Has sch schemas schema, Has td schema ('Typedef ty))
2074+ => QualifiedAlias sch td
2075+ -> TypeExpression schemas (nullity ty)
2076+typedef = UnsafeTypeExpression . renderSQL
2077+
2078+-- | The composite type corresponding to a `Table` definition can be expressed
2079+-- by its alias.
2080+typetable
2081+ :: (Has sch schemas schema, Has tab schema ('Table table))
2082+ => QualifiedAlias sch tab
2083+ -> TypeExpression schemas (nullity ('PGcomposite (TableToRow table)))
2084+typetable = UnsafeTypeExpression . renderSQL
2085+
2086+-- | The composite type corresponding to a `View` definition can be expressed
2087+-- by its alias.
2088+typeview
2089+ :: (Has sch schemas schema, Has vw schema ('View view))
2090+ => QualifiedAlias sch vw
2091+ -> TypeExpression schemas (nullity ('PGcomposite view))
2092+typeview = UnsafeTypeExpression . renderSQL
2093+
2094+-- | logical Boolean (true/false)
2095+bool :: TypeExpression schemas (nullity 'PGbool)
2096+bool = UnsafeTypeExpression "bool"
2097+-- | signed two-byte integer
2098+int2, smallint :: TypeExpression schemas (nullity 'PGint2)
2099+int2 = UnsafeTypeExpression "int2"
2100+smallint = UnsafeTypeExpression "smallint"
2101+-- | signed four-byte integer
2102+int4, int, integer :: TypeExpression schemas (nullity 'PGint4)
2103+int4 = UnsafeTypeExpression "int4"
2104+int = UnsafeTypeExpression "int"
2105+integer = UnsafeTypeExpression "integer"
2106+-- | signed eight-byte integer
2107+int8, bigint :: TypeExpression schemas (nullity 'PGint8)
2108+int8 = UnsafeTypeExpression "int8"
2109+bigint = UnsafeTypeExpression "bigint"
2110+-- | arbitrary precision numeric type
2111+numeric :: TypeExpression schemas (nullity 'PGnumeric)
2112+numeric = UnsafeTypeExpression "numeric"
2113+-- | single precision floating-point number (4 bytes)
2114+float4, real :: TypeExpression schemas (nullity 'PGfloat4)
2115+float4 = UnsafeTypeExpression "float4"
2116+real = UnsafeTypeExpression "real"
2117+-- | double precision floating-point number (8 bytes)
2118+float8, doublePrecision :: TypeExpression schemas (nullity 'PGfloat8)
2119+float8 = UnsafeTypeExpression "float8"
2120+doublePrecision = UnsafeTypeExpression "double precision"
2121+-- | currency amount
2122+money :: TypeExpression schema (nullity 'PGmoney)
2123+money = UnsafeTypeExpression "money"
2124+-- | variable-length character string
2125+text :: TypeExpression schemas (nullity 'PGtext)
2126+text = UnsafeTypeExpression "text"
2127+-- | fixed-length character string
2128+char, character
2129+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
2130+ => TypeExpression schemas (nullity ('PGchar n))
2131+char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
2132+character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
2133+-- | variable-length character string
2134+varchar, characterVarying
2135+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
2136+ => TypeExpression schemas (nullity ('PGvarchar n))
2137+varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
2138+characterVarying = UnsafeTypeExpression $
2139+ "character varying(" <> renderNat @n <> ")"
2140+-- | binary data ("byte array")
2141+bytea :: TypeExpression schemas (nullity 'PGbytea)
2142+bytea = UnsafeTypeExpression "bytea"
2143+-- | date and time (no time zone)
2144+timestamp :: TypeExpression schemas (nullity 'PGtimestamp)
2145+timestamp = UnsafeTypeExpression "timestamp"
2146+-- | date and time, including time zone
2147+timestampWithTimeZone :: TypeExpression schemas (nullity 'PGtimestamptz)
2148+timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
2149+-- | calendar date (year, month, day)
2150+date :: TypeExpression schemas (nullity 'PGdate)
2151+date = UnsafeTypeExpression "date"
2152+-- | time of day (no time zone)
2153+time :: TypeExpression schemas (nullity 'PGtime)
2154+time = UnsafeTypeExpression "time"
2155+-- | time of day, including time zone
2156+timeWithTimeZone :: TypeExpression schemas (nullity 'PGtimetz)
2157+timeWithTimeZone = UnsafeTypeExpression "time with time zone"
2158+-- | time span
2159+interval :: TypeExpression schemas (nullity 'PGinterval)
2160+interval = UnsafeTypeExpression "interval"
2161+-- | universally unique identifier
2162+uuid :: TypeExpression schemas (nullity 'PGuuid)
2163+uuid = UnsafeTypeExpression "uuid"
2164+-- | IPv4 or IPv6 host address
2165+inet :: TypeExpression schemas (nullity 'PGinet)
2166+inet = UnsafeTypeExpression "inet"
2167+-- | textual JSON data
2168+json :: TypeExpression schemas (nullity 'PGjson)
2169+json = UnsafeTypeExpression "json"
2170+-- | binary JSON data, decomposed
2171+jsonb :: TypeExpression schemas (nullity 'PGjsonb)
2172+jsonb = UnsafeTypeExpression "jsonb"
2173+-- | variable length array
2174+vararray
2175+ :: TypeExpression schemas pg
2176+ -> TypeExpression schemas (nullity ('PGvararray pg))
2177+vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
2178+-- | fixed length array
2179+--
2180+-- >>> renderSQL (fixarray @'[2] json)
2181+-- "json[2]"
2182+fixarray
2183+ :: forall dims schemas nullity pg. SOP.All KnownNat dims
2184+ => TypeExpression schemas pg
2185+ -> TypeExpression schemas (nullity ('PGfixarray dims pg))
2186+fixarray ty = UnsafeTypeExpression $
2187+ renderSQL ty <> renderDims @dims
2188+ where
2189+ renderDims :: forall ns. SOP.All KnownNat ns => ByteString
2190+ renderDims =
2191+ ("[" <>)
2192+ . (<> "]")
2193+ . ByteString.intercalate "]["
2194+ . hcollapse
2195+ $ hcmap (SOP.Proxy @KnownNat)
2196+ (K . fromString . show . natVal)
2197+ (hpure SOP.Proxy :: NP SOP.Proxy ns)
2198+tsvector :: TypeExpression schemas (nullity 'PGtsvector)
2199+tsvector = UnsafeTypeExpression "tsvector"
2200+tsquery :: TypeExpression schemas (nullity 'PGtsquery)
2201+tsquery = UnsafeTypeExpression "tsquery"
2202+
2203+-- | `pgtype` is a demoted version of a `PGType`
2204+class PGTyped schemas (ty :: NullityType) where
2205+ pgtype :: TypeExpression schemas ty
2206+instance PGTyped schemas (nullity 'PGbool) where pgtype = bool
2207+instance PGTyped schemas (nullity 'PGint2) where pgtype = int2
2208+instance PGTyped schemas (nullity 'PGint4) where pgtype = int4
2209+instance PGTyped schemas (nullity 'PGint8) where pgtype = int8
2210+instance PGTyped schemas (nullity 'PGnumeric) where pgtype = numeric
2211+instance PGTyped schemas (nullity 'PGfloat4) where pgtype = float4
2212+instance PGTyped schemas (nullity 'PGfloat8) where pgtype = float8
2213+instance PGTyped schemas (nullity 'PGmoney) where pgtype = money
2214+instance PGTyped schemas (nullity 'PGtext) where pgtype = text
2215+instance (KnownNat n, 1 <= n)
2216+ => PGTyped schemas (nullity ('PGchar n)) where pgtype = char @n
2217+instance (KnownNat n, 1 <= n)
2218+ => PGTyped schemas (nullity ('PGvarchar n)) where pgtype = varchar @n
2219+instance PGTyped schemas (nullity 'PGbytea) where pgtype = bytea
2220+instance PGTyped schemas (nullity 'PGtimestamp) where pgtype = timestamp
2221+instance PGTyped schemas (nullity 'PGtimestamptz) where pgtype = timestampWithTimeZone
2222+instance PGTyped schemas (nullity 'PGdate) where pgtype = date
2223+instance PGTyped schemas (nullity 'PGtime) where pgtype = time
2224+instance PGTyped schemas (nullity 'PGtimetz) where pgtype = timeWithTimeZone
2225+instance PGTyped schemas (nullity 'PGinterval) where pgtype = interval
2226+instance PGTyped schemas (nullity 'PGuuid) where pgtype = uuid
2227+instance PGTyped schemas (nullity 'PGjson) where pgtype = json
2228+instance PGTyped schemas (nullity 'PGjsonb) where pgtype = jsonb
2229+instance PGTyped schemas ty
2230+ => PGTyped schemas (nullity ('PGvararray ty)) where
2231+ pgtype = vararray (pgtype @schemas @ty)
2232+instance (SOP.All KnownNat dims, PGTyped schemas ty)
2233+ => PGTyped schemas (nullity ('PGfixarray dims ty)) where
2234+ pgtype = fixarray @dims (pgtype @schemas @ty)
2235+instance PGTyped schemas (nullity 'PGtsvector) where pgtype = tsvector
2236+instance PGTyped schemas (nullity 'PGtsquery) where pgtype = tsquery
2237+
2238+{-----------------------------------------
2239+Sorting
2240+-----------------------------------------}
2241+
2242+-- | `SortExpression`s are used by `orderBy` to optionally sort the results
2243+-- of a `Squeal.PostgreSQL.Query.Query`. `Asc` or `Desc`
2244+-- set the sort direction of a `NotNull` result
2245+-- column to ascending or descending. Ascending order puts smaller values
2246+-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
2247+-- descending order is determined with the `.>` operator. `AscNullsFirst`,
2248+-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
2249+-- determine whether nulls appear before or after non-null values in the sort
2250+-- ordering of a `Null` result column.
2251+data SortExpression outer grp commons schemas params from where
2252+ Asc
2253+ :: Expression outer grp commons schemas params from ('NotNull ty)
2254+ -> SortExpression outer grp commons schemas params from
2255+ Desc
2256+ :: Expression outer grp commons schemas params from ('NotNull ty)
2257+ -> SortExpression outer grp commons schemas params from
2258+ AscNullsFirst
2259+ :: Expression outer grp commons schemas params from ('Null ty)
2260+ -> SortExpression outer grp commons schemas params from
2261+ AscNullsLast
2262+ :: Expression outer grp commons schemas params from ('Null ty)
2263+ -> SortExpression outer grp commons schemas params from
2264+ DescNullsFirst
2265+ :: Expression outer grp commons schemas params from ('Null ty)
2266+ -> SortExpression outer grp commons schemas params from
2267+ DescNullsLast
2268+ :: Expression outer grp commons schemas params from ('Null ty)
2269+ -> SortExpression outer grp commons schemas params from
2270+deriving instance Show (SortExpression outer grp commons schemas params from)
2271+
2272+{- |
2273+The `orderBy` clause causes the result rows of a `Squeal.PostgreSQL.Query.TableExpression`
2274+to be sorted according to the specified `SortExpression`(s).
2275+If two rows are equal according to the leftmost expression,
2276+they are compared according to the next expression and so on.
2277+If they are equal according to all specified expressions,
2278+they are returned in an implementation-dependent order.
2279+
2280+You can also control the order in which rows are processed by window functions
2281+using `orderBy` within `Squeal.PostgreSQL.Query.Over`.
2282+-}
2283+class OrderBy expr where
2284+ orderBy
2285+ :: [SortExpression outer grp commons schemas params from]
2286+ -> expr outer grp commons schemas params from
2287+ -> expr outer grp commons schemas params from
2288+
2289+-- | Render a `SortExpression`.
2290+instance RenderSQL (SortExpression outer grp commons schemas params from) where
2291+ renderSQL = \case
2292+ Asc expression -> renderSQL expression <+> "ASC"
2293+ Desc expression -> renderSQL expression <+> "DESC"
2294+ AscNullsFirst expression -> renderSQL expression
2295+ <+> "ASC NULLS FIRST"
2296+ DescNullsFirst expression -> renderSQL expression
2297+ <+> "DESC NULLS FIRST"
2298+ AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
2299+ DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
2300+
2301+-- | A `WindowDefinition` is a set of table rows that are somehow related
2302+-- to the current row
2303+data WindowDefinition outer grp commons schemas params from where
2304+ WindowDefinition
2305+ :: SListI bys
2306+ => NP (Expression outer grp commons schemas params from) bys
2307+ -> [SortExpression outer grp commons schemas params from]
2308+ -> WindowDefinition outer grp commons schemas params from
2309+
2310+instance OrderBy WindowDefinition where
2311+ orderBy sortsR (WindowDefinition parts sortsL)
2312+ = WindowDefinition parts (sortsL ++ sortsR)
2313+
2314+instance RenderSQL (WindowDefinition outer commons schemas from grp params) where
2315+ renderSQL (WindowDefinition part ord) =
2316+ renderPartitionByClause part <> renderOrderByClause ord
2317+ where
2318+ renderPartitionByClause = \case
2319+ Nil -> ""
2320+ parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
2321+ renderOrderByClause = \case
2322+ [] -> ""
2323+ srts -> " ORDER" <+> "BY"
2324+ <+> commaSeparated (renderSQL <$> srts)
2325+
2326+{- |
2327+The `partitionBy` clause within `Squeal.PostgreSQL.Query.Over` divides the rows into groups,
2328+or partitions, that share the same values of the `partitionBy` `Expression`(s).
2329+For each row, the window function is computed across the rows that fall into
2330+the same partition as the current row.
2331+-}
2332+partitionBy
2333+ :: SListI bys
2334+ => NP (Expression outer grp commons schemas params from) bys
2335+ -> WindowDefinition outer grp commons schemas params from
2336+partitionBy bys = WindowDefinition bys []
2337+
2338+{- |
2339+A window function performs a calculation across a set of table rows
2340+that are somehow related to the current row. This is comparable to the type
2341+of calculation that can be done with an aggregate function.
2342+However, window functions do not cause rows to become grouped into a single
2343+output row like non-window aggregate calls would.
2344+Instead, the rows retain their separate identities.
2345+Behind the scenes, the window function is able to access more than
2346+just the current row of the query result.
2347+-}
2348+newtype WindowFunction
2349+ (outer :: FromType)
2350+ (grp :: Grouping)
2351+ (commons :: FromType)
2352+ (schemas :: SchemasType)
2353+ (params :: [NullityType])
2354+ (from :: FromType)
2355+ (ty :: NullityType)
2356+ = UnsafeWindowFunction { renderWindowFunction :: ByteString }
2357+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
2358+
2359+instance RenderSQL (WindowFunction outer grp commons schemas params from ty) where
2360+ renderSQL = renderWindowFunction
2361+
2362+unsafeWindowFunction1
2363+ :: ByteString
2364+ -> Expression outer grp commons schemas params from ty0
2365+ -> WindowFunction outer grp commons schemas params from ty1
2366+unsafeWindowFunction1 fun x
2367+ = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x)
2368+
2369+unsafeWindowFunction2
2370+ :: ByteString
2371+ -> (Expression outer grp commons schemas params from :*: Expression outer grp commons schemas params from) ty0
2372+ -> WindowFunction outer grp commons schemas params from ty1
2373+unsafeWindowFunction2 fun (x :*: x')
2374+ = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x <> ", " <> renderSQL x')
2375+
2376+{- | rank of the current row with gaps; same as `rowNumber` of its first peer
2377+>>> printSQL rank
2378+rank()
2379+-}
2380+rank :: WindowFunction outer grp commons schemas params from ('NotNull 'PGint8)
2381+rank = UnsafeWindowFunction "rank()"
2382+
2383+{- | number of the current row within its partition, counting from 1
2384+>>> printSQL rowNumber
2385+row_number()
2386+-}
2387+rowNumber :: WindowFunction outer grp commons schemas params from ('NotNull 'PGint8)
2388+rowNumber = UnsafeWindowFunction "row_number()"
2389+
2390+{- | rank of the current row without gaps; this function counts peer groups
2391+>>> printSQL denseRank
2392+dense_rank()
2393+-}
2394+denseRank :: WindowFunction outer grp commons schemas params from ('NotNull 'PGint8)
2395+denseRank = UnsafeWindowFunction "dense_rank()"
2396+
2397+{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
2398+>>> printSQL percentRank
2399+percent_rank()
2400+-}
2401+percentRank :: WindowFunction outer grp commons schemas params from ('NotNull 'PGfloat8)
2402+percentRank = UnsafeWindowFunction "percent_rank()"
2403+
2404+{- | cumulative distribution: (number of partition rows
2405+preceding or peer with current row) / total partition rows
2406+>>> printSQL cumeDist
2407+cume_dist()
2408+-}
2409+cumeDist :: WindowFunction outer grp commons schemas params from ('NotNull 'PGfloat8)
2410+cumeDist = UnsafeWindowFunction "cume_dist()"
2411+
2412+{- | integer ranging from 1 to the argument value,
2413+dividing the partition as equally as possible
2414+-}
2415+ntile
2416+ :: Expression outer grp commons schemas params from ('NotNull 'PGint4)
2417+ -- ^ num buckets
2418+ -> WindowFunction outer grp commons schemas params from ('NotNull 'PGint4)
2419+ntile = unsafeWindowFunction1 "ntile"
2420+
2421+{- | returns value evaluated at the row that is offset rows before the current
2422+row within the partition; if there is no such row, instead return default
2423+(which must be of the same type as value). Both offset and default are
2424+evaluated with respect to the current row.
2425+-}
2426+lag
2427+ :: Expression outer grp commons schemas params from ty
2428+ -- ^ value
2429+ -> Expression outer grp commons schemas params from ('NotNull 'PGint4)
2430+ -- ^ offset
2431+ -> Expression outer grp commons schemas params from ty
2432+ -- ^ default
2433+ -> WindowFunction outer grp commons schemas params from ty
2434+lag value offset def = UnsafeWindowFunction $ "lag"
2435+ <> parenthesized
2436+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
2437+
2438+{- | returns value evaluated at the row that is offset rows after the current
2439+row within the partition; if there is no such row, instead return default
2440+(which must be of the same type as value). Both offset and default are
2441+evaluated with respect to the current row.
2442+-}
2443+lead
2444+ :: Expression outer grp commons schemas params from ty
2445+ -- ^ value
2446+ -> Expression outer grp commons schemas params from ('NotNull 'PGint4)
2447+ -- ^ offset
2448+ -> Expression outer grp commons schemas params from ty
2449+ -- ^ default
2450+ -> WindowFunction outer grp commons schemas params from ty
2451+lead value offset def = UnsafeWindowFunction $ "lag"
2452+ <> parenthesized
2453+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
2454+
2455+{- | returns value evaluated at the row that is the
2456+first row of the window frame
2457+-}
2458+firstValue
2459+ :: Expression outer grp commons schemas params from ty
2460+ -- ^ value
2461+ -> WindowFunction outer grp commons schemas params from ty
2462+firstValue = unsafeWindowFunction1 "first_value"
2463+
2464+{- | returns value evaluated at the row that is the
2465+last row of the window frame
2466+-}
2467+lastValue
2468+ :: Expression outer grp commons schemas params from ty
2469+ -- ^ value
2470+ -> WindowFunction outer grp commons schemas params from ty
2471+lastValue = unsafeWindowFunction1 "last_value"
2472+
2473+{- | returns value evaluated at the row that is the nth
2474+row of the window frame (counting from 1); null if no such row
2475+-}
2476+nthValue
2477+ :: Expression outer grp commons schemas params from (nullity ty)
2478+ -- ^ value
2479+ -> Expression outer grp commons schemas params from ('NotNull 'PGint4)
2480+ -- ^ nth
2481+ -> WindowFunction outer grp commons schemas params from ('Null ty)
2482+nthValue value nth = UnsafeWindowFunction $ "nth_value"
2483+ <> parenthesized (commaSeparated [renderSQL value, renderSQL nth])
2484+
2485+{-|
2486+Create date from year, month and day fields
2487+
2488+>>> printSQL (makeDate 1984 7 3)
2489+make_date(1984, 7, 3)
2490+-}
2491+makeDate
2492+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2493+ -- ^ year
2494+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2495+ -- ^ month
2496+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2497+ -- ^ day
2498+ -> Expression outer grp commons schemas params from (nullity 'PGdate)
2499+makeDate y m d = UnsafeExpression $ "make_date" <>
2500+ parenthesized (renderCommaSeparated renderSQL (y :* m :* d :* Nil))
2501+
2502+{-|
2503+Create time from hour, minute and seconds fields
2504+
2505+>>> printSQL (makeTime 8 15 23.5)
2506+make_time(8, 15, 23.5)
2507+-}
2508+makeTime
2509+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2510+ -- ^ hour
2511+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2512+ -- ^ min
2513+ -> Expression outer grp commons schemas params from (nullity 'PGfloat8)
2514+ -- ^ sec
2515+ -> Expression outer grp commons schemas params from (nullity 'PGtime)
2516+makeTime h m s = UnsafeExpression $ "make_time" <>
2517+ parenthesized (renderCommaSeparated renderSQL (h :* m :* s :* Nil))
2518+
2519+{-|
2520+Create timestamp from year, month, day, hour, minute and seconds fields
2521+
2522+>>> printSQL (makeTimestamp 2013 7 15 8 15 23.5)
2523+make_timestamp(2013, 7, 15, 8, 15, 23.5)
2524+-}
2525+makeTimestamp
2526+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2527+ -- ^ year
2528+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2529+ -- ^ month
2530+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2531+ -- ^ day
2532+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2533+ -- ^ hour
2534+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2535+ -- ^ min
2536+ -> Expression outer grp commons schemas params from (nullity 'PGfloat8)
2537+ -- ^ sec
2538+ -> Expression outer grp commons schemas params from (nullity 'PGtimestamp)
2539+makeTimestamp y mon d h m s =
2540+ UnsafeExpression $ "make_timestamp" <> parenthesized
2541+ (renderCommaSeparated renderSQL (y :* mon :* d :* h :* m :* s :* Nil))
2542+
2543+{-|
2544+Create timestamp with time zone from
2545+year, month, day, hour, minute and seconds fields;
2546+the current time zone is used
2547+
2548+>>> printSQL (makeTimestamptz 2013 7 15 8 15 23.5)
2549+make_timestamptz(2013, 7, 15, 8, 15, 23.5)
2550+-}
2551+makeTimestamptz
2552+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2553+ -- ^ year
2554+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2555+ -- ^ month
2556+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2557+ -- ^ day
2558+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2559+ -- ^ hour
2560+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2561+ -- ^ min
2562+ -> Expression outer grp commons schemas params from (nullity 'PGfloat8)
2563+ -- ^ sec
2564+ -> Expression outer grp commons schemas params from (nullity 'PGtimestamptz)
2565+makeTimestamptz y mon d h m s =
2566+ UnsafeExpression $ "make_timestamptz" <> parenthesized
2567+ (renderCommaSeparated renderSQL (y :* mon :* d :* h :* m :* s :* Nil))
2568+
2569+{-|
2570+Affine space operations on time types.
2571+-}
2572+class TimeOp time diff | time -> diff where
2573+ {-|
2574+ >>> printSQL (makeDate 1984 7 3 !+ 365)
2575+ (make_date(1984, 7, 3) + 365)
2576+ -}
2577+ (!+) :: Operator (nullity time) (nullity diff) (nullity time)
2578+ (!+) = unsafeBinaryOp "+"
2579+ {-|
2580+ >>> printSQL (365 +! makeDate 1984 7 3)
2581+ (365 + make_date(1984, 7, 3))
2582+ -}
2583+ (+!) :: Operator (nullity diff) (nullity time) (nullity time)
2584+ (+!) = unsafeBinaryOp "+"
2585+ {-|
2586+ >>> printSQL (makeDate 1984 7 3 !- 365)
2587+ (make_date(1984, 7, 3) - 365)
2588+ -}
2589+ (!-) :: Operator (nullity time) (nullity diff) (nullity time)
2590+ (!-) = unsafeBinaryOp "-"
2591+ {-|
2592+ >>> printSQL (makeDate 1984 7 3 !-! currentDate)
2593+ (make_date(1984, 7, 3) - CURRENT_DATE)
2594+ -}
2595+ (!-!) :: Operator (nullity time) (nullity time) (nullity diff)
2596+ (!-!) = unsafeBinaryOp "-"
2597+instance TimeOp 'PGtimestamp 'PGinterval
2598+instance TimeOp 'PGtimestamptz 'PGinterval
2599+instance TimeOp 'PGtime 'PGinterval
2600+instance TimeOp 'PGtimetz 'PGinterval
2601+instance TimeOp 'PGinterval 'PGinterval
2602+instance TimeOp 'PGdate 'PGint4
2603+infixl 6 !+
2604+infixl 6 +!
2605+infixl 6 !-
2606+infixl 6 !-!