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