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