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