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