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