@@ -1,13 +1,14 @@
11{-|
2−Module: Squeal.PostgreSQL.Expression
2+Module: Squeal.PostgreSQL.Query
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
@@ -15,13 +16,11 @@ Squeal expressions are the atoms used to build statements.
1516 , FlexibleContexts
1617 , FlexibleInstances
1718 , FunctionalDependencies
18− , GADTs
1919 , GeneralizedNewtypeDeriving
2020 , LambdaCase
2121 , MagicHash
2222 , OverloadedStrings
2323 , ScopedTypeVariables
24− , StandaloneDeriving
2524 , TypeApplications
2625 , TypeFamilies
2726 , TypeInType
@@ -32,351 +31,513 @@ Squeal expressions are the atoms used to build statements.
3231
3332module Squeal.PostgreSQL.Expression
3433 ( -- * Expression
35− Expression (..)
36− , Expr
37− , type (-->)
38− , FunctionDB
39− , unsafeFunction
40− , function
41− , unsafeLeftOp
42− , leftOp
43− , unsafeRightOp
44− , rightOp
45− , Operator
46− , OperatorDB
34+ Expression (UnsafeExpression, renderExpression)
35+ , HasParameter (parameter)
36+ , param
37+ -- ** Null
38+ , null_
39+ , notNull
40+ , coalesce
41+ , fromNull
42+ , isNull
43+ , isNotNull
44+ , matchNull
45+ , nullIf
46+ -- ** Collections
47+ , array
48+ , row
49+ -- ** Functions
4750 , unsafeBinaryOp
48− , binaryOp
49− , FunctionVar
50− , unsafeFunctionVar
51− , type (--->)
52− , FunctionNDB
53− , unsafeFunctionN
54− , functionN
55− , PGSubset (..)
56− , PGIntersect (..)
51+ , unsafeUnaryOp
52+ , unsafeFunction
53+ , unsafeVariadicFunction
54+ , atan2_
55+ , cast
56+ , quot_
57+ , rem_
58+ , trunc
59+ , round_
60+ , ceiling_
61+ , greatest
62+ , least
63+ -- ** Conditions
64+ , Condition
65+ , true
66+ , false
67+ , not_
68+ , (.&&)
69+ , (.||)
70+ , caseWhenThenElse
71+ , ifThenElse
72+ , (.==)
73+ , (./=)
74+ , (.>=)
75+ , (.<)
76+ , (.<=)
77+ , (.>)
78+ -- ** Time
79+ , currentDate
80+ , currentTime
81+ , currentTimestamp
82+ , localTime
83+ , localTimestamp
84+ -- ** Text
85+ , lower
86+ , upper
87+ , charLength
88+ , like
89+ -- ** json or jsonb operators
90+ , PGarray
91+ , PGarrayOf
92+ , PGjsonKey
93+ , PGjson_
94+ , PGobjectpairs
95+ , (.->)
96+ , (.->>)
97+ , (.#>)
98+ , (.#>>)
99+ -- *** jsonb only operators
100+ , (.@>)
101+ , (.<@)
102+ , (.?)
103+ , (.?|)
104+ , (.?&)
105+ , (.||.)
106+ , (.-.)
107+ , (#-.)
108+ -- *** Functions
109+ , toJson
110+ , toJsonb
111+ , arrayToJson
112+ , rowToJson
113+ , jsonBuildArray
114+ , jsonbBuildArray
115+ , jsonBuildObject
116+ , jsonbBuildObject
117+ , jsonObject
118+ , jsonbObject
119+ , jsonZipObject
120+ , jsonbZipObject
121+ , jsonArrayLength
122+ , jsonbArrayLength
123+ , jsonExtractPath
124+ , jsonbExtractPath
125+ , jsonExtractPathAsText
126+ , jsonbExtractPathAsText
127+ , jsonObjectKeys
128+ , jsonbObjectKeys
129+ , jsonTypeof
130+ , jsonbTypeof
131+ , jsonStripNulls
132+ , jsonbStripNulls
133+ , jsonbSet
134+ , jsonbInsert
135+ , jsonbPretty
136+ -- ** Aggregation
137+ , unsafeAggregate, unsafeAggregateDistinct
138+ , sum_, sumDistinct
139+ , PGAvg (avg, avgDistinct)
140+ , bitAnd, bitOr, boolAnd, boolOr
141+ , bitAndDistinct, bitOrDistinct, boolAndDistinct, boolOrDistinct
142+ , countStar
143+ , count, countDistinct
144+ , every, everyDistinct
145+ , max_, maxDistinct, min_, minDistinct
146+ -- * Types
147+ , TypeExpression (UnsafeTypeExpression, renderTypeExpression)
148+ , PGTyped (pgtype)
149+ , bool
150+ , int2
151+ , smallint
152+ , int4
153+ , int
154+ , integer
155+ , int8
156+ , bigint
157+ , numeric
158+ , float4
159+ , real
160+ , float8
161+ , doublePrecision
162+ , text
163+ , char
164+ , character
165+ , varchar
166+ , characterVarying
167+ , bytea
168+ , timestamp
169+ , timestampWithTimeZone
170+ , date
171+ , time
172+ , timeWithTimeZone
173+ , interval
174+ , uuid
175+ , inet
176+ , json
177+ , jsonb
178+ , vararray
179+ , fixarray
57180 -- * Re-export
58181 , (&)
59− , K (..)
60− , unK
182+ , NP ((:*), Nil)
61183 ) where
62184
63185import Control.Category
64186import Control.DeepSeq
65187import Data.ByteString (ByteString)
66188import Data.Function ((&))
67−import Data.Semigroup hiding (All)
189+import Data.Semigroup
190+import Data.Ratio
68191import Data.String
69−import Generics.SOP hiding (All, from)
192+import Generics.SOP hiding (from)
70193import GHC.OverloadedLabels
71194import GHC.TypeLits
72−import Numeric
73195import Prelude hiding (id, (.))
74196
75197import qualified GHC.Generics as GHC
76198
77−import Squeal.PostgreSQL.Alias
78−import Squeal.PostgreSQL.List
79199import Squeal.PostgreSQL.Render
80200import Squeal.PostgreSQL.Schema
81201
82−-- $setup
83−-- >>> import Squeal.PostgreSQL
84−
85202{-----------------------------------------
86203column expressions
87204-----------------------------------------}
88205
89206{- | `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,
207+such as in the target list of the `Squeal.PostgreSQL.Query.select` command,
92208as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
93209`Squeal.PostgreSQL.Manipulation.update`,
94−or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
210+or in search `Condition`s in a number of commands.
95211
96212The expression syntax allows the calculation of
97213values from primitive expression using arithmetic, logical,
98214and 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`.
113215-}
114216newtype Expression
115− (outer :: FromType)
116− (commons :: FromType)
117− (grp :: Grouping)
118− (schemas :: SchemasType)
217+ (schema :: SchemaType)
218+ (relations :: RelationsType)
219+ (grouping :: Grouping)
119220 (params :: [NullityType])
120− (from :: FromType)
121221 (ty :: NullityType)
122222 = UnsafeExpression { renderExpression :: ByteString }
123223 deriving (GHC.Generic,Show,Eq,Ord,NFData)
124−instance RenderSQL (Expression outer commons grp schemas params from ty) where
224+
225+instance RenderSQL (Expression schema relations grouping params ty) where
125226 renderSQL = renderExpression
126227
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.
228+{- | A `HasParameter` constraint is used to indicate a value that is
229+supplied externally to a SQL statement.
230+`Squeal.PostgreSQL.PQ.manipulateParams`,
231+`Squeal.PostgreSQL.PQ.queryParams` and
232+`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
233+separately from the SQL command string, in which case `param`s are used to
234+refer to the out-of-line data values.
198235-}
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)
214−
215−instance (HasUnique tab (Join outer from) row, Has col row ty)
216− => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
217− fromLabel = UnsafeExpression $ renderSQL (Alias @col)
218−instance (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
220− fromLabel = fromLabel @col :* Nil
221−instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
222− => IsLabel col
223− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
224− fromLabel = fromLabel @col `As` Alias
225−instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
226− => IsLabel col
227− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
228− fromLabel = fromLabel @col :* Nil
229−
230−instance (Has tab (Join outer from) row, Has col row ty)
231− => IsQualified tab col (Expression outer commons 'Ungrouped schemas params from ty) where
232− tab ! col = UnsafeExpression $
233− renderSQL tab <> "." <> renderSQL col
234−instance (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
236− tab ! col = tab ! col :* Nil
237−instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
238− => IsQualified tab col
239− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
240− tab ! col = tab ! col `As` col
241−instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
242− => IsQualified tab col
243− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
244− tab ! col = tab ! col :* Nil
236+class KnownNat n => HasParameter
237+ (n :: Nat)
238+ (schema :: SchemaType)
239+ (params :: [NullityType])
240+ (ty :: NullityType)
241+ | n params -> ty where
242+ -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
243+ --
244+ -- >>> let expr = parameter @1 int4 :: Expression sch rels grp '[ 'Null 'PGint4] ('Null 'PGint4)
245+ -- >>> printSQL expr
246+ -- ($1 :: int4)
247+ parameter
248+ :: TypeExpression schema (PGTypeOf ty)
249+ -> Expression schema relations grouping params ty
250+ parameter ty = UnsafeExpression $ parenthesized $
251+ "$" <> renderNat (Proxy @n) <+> "::"
252+ <+> renderTypeExpression ty
253+instance {-# OVERLAPPING #-} HasParameter 1 schema (ty1:tys) ty1
254+instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) schema params ty)
255+ => HasParameter n schema (ty' : params) ty
256+
257+-- | `param` takes a `Nat` using type application and for basic types,
258+-- infers a `TypeExpression`.
259+--
260+-- >>> let expr = param @1 :: Expression sch rels grp '[ 'Null 'PGint4] ('Null 'PGint4)
261+-- >>> printSQL expr
262+-- ($1 :: int4)
263+param
264+ :: forall n schema params relations grouping ty
265+ . (PGTyped schema (PGTypeOf ty), HasParameter n schema params ty)
266+ => Expression schema relations grouping params ty -- ^ param
267+param = parameter @n pgtype
268+
269+instance (HasUnique relation relations columns, Has column columns ty)
270+ => IsLabel column (Expression schema relations 'Ungrouped params ty) where
271+ fromLabel = UnsafeExpression $ renderAlias (Alias @column)
272+instance (HasUnique relation relations columns, Has column columns ty)
273+ => IsLabel column
274+ (Aliased (Expression schema relations 'Ungrouped params) (column ::: ty)) where
275+ fromLabel = fromLabel @column `As` Alias @column
276+instance (HasUnique relation relations columns, Has column columns ty)
277+ => IsLabel column
278+ (NP (Aliased (Expression schema relations 'Ungrouped params)) '[column ::: ty]) where
279+ fromLabel = fromLabel @column :* Nil
280+
281+instance (Has relation relations columns, Has column columns ty)
282+ => IsQualified relation column (Expression schema relations 'Ungrouped params ty) where
283+ relation ! column = UnsafeExpression $
284+ renderAlias relation <> "." <> renderAlias column
285+instance (Has relation relations columns, Has column columns ty)
286+ => IsQualified relation column
287+ (Aliased (Expression schema relations 'Ungrouped params) (column ::: ty)) where
288+ relation ! column = relation ! column `As` column
289+instance (Has relation relations columns, Has column columns ty)
290+ => IsQualified relation column
291+ (NP (Aliased (Expression schema relations 'Ungrouped params)) '[column ::: ty]) where
292+ relation ! column = relation ! column :* Nil
245293
246294instance
247− ( HasUnique tab (Join outer from) row
248− , Has col row ty
249− , GroupedBy tab col bys
250− ) => IsLabel col
251− (Expression outer commons ('Grouped bys) schemas params from ty) where
252− fromLabel = UnsafeExpression $ renderSQL (Alias @col)
253−instance
254− ( HasUnique tab (Join outer from) row
255− , Has col row ty
256− , GroupedBy tab col bys
257− , tys ~ '[ty]
258− ) => IsLabel col
259− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
260− fromLabel = fromLabel @col :* Nil
295+ ( HasUnique relation relations columns
296+ , Has column columns ty
297+ , GroupedBy relation column bys
298+ ) => IsLabel column
299+ (Expression schema relations ('Grouped bys) params ty) where
300+ fromLabel = UnsafeExpression $ renderAlias (Alias @column)
261301instance
262− ( HasUnique tab (Join outer from) row
263− , Has col row ty
264− , GroupedBy tab col bys
265− , column ~ (col ::: ty)
266− ) => IsLabel col
267− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
268− fromLabel = fromLabel @col `As` Alias
302+ ( HasUnique relation relations columns
303+ , Has column columns ty
304+ , GroupedBy relation column bys
305+ ) => IsLabel column
306+ ( Aliased (Expression schema relations ('Grouped bys) params)
307+ (column ::: ty) ) where
308+ fromLabel = fromLabel @column `As` Alias @column
269309instance
270− ( HasUnique tab (Join outer from) row
271− , Has col row ty
272− , GroupedBy tab col bys
273− , columns ~ '[col ::: ty]
274− ) => IsLabel col
275− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
276− fromLabel = fromLabel @col :* Nil
310+ ( HasUnique relation relations columns
311+ , Has column columns ty
312+ , GroupedBy relation column bys
313+ ) => IsLabel column
314+ ( NP (Aliased (Expression schema relations ('Grouped bys) params))
315+ '[column ::: ty] ) where
316+ fromLabel = fromLabel @column :* Nil
277317
278318instance
279− ( Has tab (Join outer from) row
280− , Has col row ty
281− , GroupedBy tab col bys
282− ) => IsQualified tab col
283− (Expression outer commons ('Grouped bys) schemas params from ty) where
284− tab ! col = UnsafeExpression $
285− renderSQL tab <> "." <> renderSQL col
286−instance
287− ( Has tab (Join outer from) row
288− , Has col row ty
289− , GroupedBy tab col bys
290− , tys ~ '[ty]
291− ) => IsQualified tab col
292− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
293− tab ! col = tab ! col :* Nil
319+ ( Has relation relations columns
320+ , Has column columns ty
321+ , GroupedBy relation column bys
322+ ) => IsQualified relation column
323+ (Expression schema relations ('Grouped bys) params ty) where
324+ relation ! column = UnsafeExpression $
325+ renderAlias relation <> "." <> renderAlias column
294326instance
295− ( Has tab (Join outer from) row
296− , Has col row ty
297− , GroupedBy tab col bys
298− , column ~ (col ::: ty)
299− ) => IsQualified tab col
300− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
301− tab ! col = tab ! col `As` col
327+ ( Has relation relations columns
328+ , Has column columns ty
329+ , GroupedBy relation column bys
330+ ) => IsQualified relation column
331+ (Aliased (Expression schema relations ('Grouped bys) params)
332+ (column ::: ty)) where
333+ relation ! column = relation ! column `As` column
302334instance
303− ( Has tab (Join outer from) row
304− , Has col row ty
305− , GroupedBy tab col bys
306− , columns ~ '[col ::: ty]
307− ) => IsQualified tab col
308− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
309− tab ! col = tab ! col :* Nil
335+ ( Has relation relations columns
336+ , Has column columns ty
337+ , GroupedBy relation column bys
338+ ) => IsQualified relation column
339+ ( NP (Aliased (Expression schema relations ('Grouped bys) params))
340+ '[column ::: ty]) where
341+ relation ! column = relation ! column :* Nil
342+
343+-- | analagous to `Nothing`
344+--
345+-- >>> printSQL null_
346+-- NULL
347+null_ :: Expression schema rels grouping params ('Null ty)
348+null_ = UnsafeExpression "NULL"
349+
350+-- | analagous to `Just`
351+--
352+-- >>> printSQL $ notNull true
353+-- TRUE
354+notNull
355+ :: Expression schema rels grouping params ('NotNull ty)
356+ -> Expression schema rels grouping params ('Null ty)
357+notNull = UnsafeExpression . renderExpression
358+
359+-- | return the leftmost value which is not NULL
360+--
361+-- >>> printSQL $ coalesce [null_, notNull true] false
362+-- COALESCE(NULL, TRUE, FALSE)
363+coalesce
364+ :: [Expression schema relations grouping params ('Null ty)]
365+ -- ^ @NULL@s may be present
366+ -> Expression schema relations grouping params ('NotNull ty)
367+ -- ^ @NULL@ is absent
368+ -> Expression schema relations grouping params ('NotNull ty)
369+coalesce nullxs notNullx = UnsafeExpression $
370+ "COALESCE" <> parenthesized (commaSeparated
371+ ((renderExpression <$> nullxs) <> [renderExpression notNullx]))
372+
373+-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
374+--
375+-- >>> printSQL $ fromNull true null_
376+-- COALESCE(NULL, TRUE)
377+fromNull
378+ :: Expression schema relations grouping params ('NotNull ty)
379+ -- ^ what to convert @NULL@ to
380+ -> Expression schema relations grouping params ('Null ty)
381+ -> Expression schema relations grouping params ('NotNull ty)
382+fromNull notNullx nullx = coalesce [nullx] notNullx
383+
384+-- | >>> printSQL $ null_ & isNull
385+-- NULL IS NULL
386+isNull
387+ :: Expression schema relations grouping params ('Null ty)
388+ -- ^ possibly @NULL@
389+ -> Condition schema relations grouping params
390+isNull x = UnsafeExpression $ renderExpression x <+> "IS NULL"
391+
392+-- | >>> printSQL $ null_ & isNotNull
393+-- NULL IS NOT NULL
394+isNotNull
395+ :: Expression schema relations grouping params ('Null ty)
396+ -- ^ possibly @NULL@
397+ -> Condition schema relations grouping params
398+isNotNull x = UnsafeExpression $ renderExpression x <+> "IS NOT NULL"
399+
400+-- | analagous to `maybe` using @IS NULL@
401+--
402+-- >>> printSQL $ matchNull true not_ null_
403+-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
404+matchNull
405+ :: Expression schema relations grouping params (nullty)
406+ -- ^ what to convert @NULL@ to
407+ -> ( Expression schema relations grouping params ('NotNull ty)
408+ -> Expression schema relations grouping params (nullty) )
409+ -- ^ function to perform when @NULL@ is absent
410+ -> Expression schema relations grouping params ('Null ty)
411+ -> Expression schema relations grouping params (nullty)
412+matchNull y f x = ifThenElse (isNull x) y
413+ (f (UnsafeExpression (renderExpression x)))
414+
415+{-| right inverse to `fromNull`, if its arguments are equal then
416+`nullIf` gives @NULL@.
417+
418+>>> :set -XTypeApplications -XDataKinds
419+>>> let expr = nullIf false (param @1) :: Expression schema rels grp '[ 'NotNull 'PGbool] ('Null 'PGbool)
420+>>> printSQL expr
421+NULL IF (FALSE, ($1 :: bool))
422+-}
423+nullIf
424+ :: Expression schema relations grouping params ('NotNull ty)
425+ -- ^ @NULL@ is absent
426+ -> Expression schema relations grouping params ('NotNull ty)
427+ -- ^ @NULL@ is absent
428+ -> Expression schema relations grouping params ('Null ty)
429+nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
430+ (renderExpression x <> ", " <> renderExpression y)
431+
432+-- | >>> printSQL $ array [null_, notNull false, notNull true]
433+-- ARRAY[NULL, FALSE, TRUE]
434+array
435+ :: [Expression schema relations grouping params ('Null ty)]
436+ -- ^ array elements
437+ -> Expression schema relations grouping params (nullity ('PGvararray ty))
438+array xs = UnsafeExpression $
439+ "ARRAY[" <> commaSeparated (renderExpression <$> xs) <> "]"
310440
311441instance (KnownSymbol label, label `In` labels) => IsPGlabel label
312− (Expression outer commons grp schemas params from (null ('PGenum labels))) where
313− label = UnsafeExpression $ renderSQL (PGlabel @label)
442+ (Expression schema relations grouping params (nullity ('PGenum labels))) where
443+ label = UnsafeExpression $ renderLabel (PGlabel @label)
444+
445+-- | A row constructor is an expression that builds a row value
446+-- (also called a composite value) using values for its member fields.
447+--
448+-- >>> type Complex = PGcomposite '["real" ::: 'PGfloat8, "imaginary" ::: 'PGfloat8]
449+-- >>> let i = row (0 `As` #real :* 1 `As` #imaginary :* Nil) :: Expression '[] '[] 'Ungrouped '[] ('NotNull Complex)
450+-- >>> printSQL i
451+-- ROW(0, 1)
452+row
453+ :: SListI (Nulls fields)
454+ => NP (Aliased (Expression schema relations grouping params)) (Nulls fields)
455+ -- ^ zero or more expressions for the row field values
456+ -> Expression schema relations grouping params (nullity ('PGcomposite fields))
457+row exprs = UnsafeExpression $ "ROW" <> parenthesized
458+ (renderCommaSeparated (\ (expr `As` _) -> renderExpression expr) exprs)
459+
460+instance Has field fields ty => IsLabel field
461+ ( Expression schema relation grouping params (nullity ('PGcomposite fields))
462+ -> Expression schema relation grouping params ('Null ty) ) where
463+ fromLabel expr = UnsafeExpression $
464+ parenthesized (renderExpression expr) <> "." <>
465+ fromString (symbolVal (Proxy @field))
466+
467+instance Semigroup
468+ (Expression schema relations grouping params (nullity ('PGvararray ty))) where
469+ (<>) = unsafeBinaryOp "||"
470+
471+instance Monoid
472+ (Expression schema relations grouping params (nullity ('PGvararray ty))) where
473+ mempty = array []
474+ mappend = (<>)
475+
476+-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression sch rels grp '[ 'NotNull 'PGtimestamptz] ('NotNull 'PGtimestamptz)
477+-- >>> printSQL expr
478+-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
479+greatest
480+ :: Expression schema relations grouping params (nullty)
481+ -- ^ needs at least 1 argument
482+ -> [Expression schema relations grouping params (nullty)]
483+ -- ^ or more
484+ -> Expression schema relations grouping params (nullty)
485+greatest x xs = UnsafeExpression $ "GREATEST("
486+ <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
487+
488+-- | >>> printSQL $ least currentTimestamp [null_]
489+-- LEAST(CURRENT_TIMESTAMP, NULL)
490+least
491+ :: Expression schema relations grouping params (nullty)
492+ -- ^ needs at least 1 argument
493+ -> [Expression schema relations grouping params (nullty)]
494+ -- ^ or more
495+ -> Expression schema relations grouping params (nullty)
496+least x xs = UnsafeExpression $ "LEAST("
497+ <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
314498
315499-- | >>> printSQL $ unsafeBinaryOp "OR" true false
316500-- (TRUE OR FALSE)
317−unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
501+unsafeBinaryOp
502+ :: ByteString
503+ -- ^ operator
504+ -> Expression schema relations grouping params (ty0)
505+ -> Expression schema relations grouping params (ty1)
506+ -> Expression schema relations grouping params (ty2)
318507unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
319− renderSQL x <+> op <+> renderSQL y
508+ renderExpression x <+> op <+> renderExpression y
320509
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
510+-- | >>> printSQL $ unsafeUnaryOp "NOT" true
329511-- (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
512+unsafeUnaryOp
513+ :: ByteString
514+ -- ^ operator
515+ -> Expression schema relations grouping params (ty0)
516+ -> Expression schema relations grouping params (ty1)
517+unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
518+ op <+> renderExpression x
351519
352520-- | >>> printSQL $ unsafeFunction "f" true
353521-- f(TRUE)
354−unsafeFunction :: ByteString -> x --> y
522+unsafeFunction
523+ :: ByteString
524+ -- ^ function
525+ -> Expression schema relations grouping params (xty)
526+ -> Expression schema relations grouping params (yty)
355527unsafeFunction fun x = UnsafeExpression $
356− fun <> parenthesized (renderSQL x)
357−
358−function
359− :: (Has sch schemas schema, Has fun schema ('Function ('[x] :=> 'Returns y)))
360− => QualifiedAlias sch fun
361− -> FunctionDB schemas x y
362−function = unsafeFunction . renderSQL
363−
364−-- | >>> printSQL $ unsafeFunctionN "f" (currentTime :* localTimestamp :* false *: literal 'a')
365−-- f(CURRENT_TIME, LOCALTIMESTAMP, FALSE, E'a')
366−unsafeFunctionN :: SListI xs => ByteString -> xs ---> y
367−unsafeFunctionN fun xs = UnsafeExpression $
368− fun <> parenthesized (renderCommaSeparated renderSQL xs)
369−
370−functionN
371− :: ( Has sch schemas schema
372− , Has fun schema ('Function (xs :=> 'Returns y))
373− , SListI xs )
374− => QualifiedAlias sch fun
375− -> FunctionNDB schemas xs y
376−functionN = unsafeFunctionN . renderSQL
377−
378−instance ty `In` PGNum
379− => Num (Expression outer commons grp schemas params from (null ty)) where
528+ fun <> parenthesized (renderExpression x)
529+
530+unsafeVariadicFunction
531+ :: SListI elems
532+ => ByteString
533+ -- ^ function
534+ -> NP (Expression schema relations grouping params) elems
535+ -> Expression schema relations grouping params ret
536+unsafeVariadicFunction fun x = UnsafeExpression $
537+ fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderExpression) x)))
538+
539+instance PGNum ty
540+ => Num (Expression schema relations grouping params (nullity ty)) where
380541 (+) = unsafeBinaryOp "+"
381542 (-) = unsafeBinaryOp "-"
382543 (*) = unsafeBinaryOp "*"
@@ -387,24 +548,19 @@ instance ty `In` PGNum
387548 . fromString
388549 . show
389550
390−instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
391− (Expression outer commons grp schemas params from (null ty)) where
551+instance (PGNum ty, PGFloating ty) => Fractional
552+ (Expression schema relations grouping params (nullity ty)) where
392553 (/) = unsafeBinaryOp "/"
393− fromRational
394− = UnsafeExpression
395− . fromString
396− . ($ "")
397− . showFFloat Nothing
398− . fromRat @Double
554+ fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
399555
400−instance (ty `In` PGNum, ty `In` PGFloating) => Floating
401− (Expression outer commons grp schemas params from (null ty)) where
556+instance (PGNum ty, PGFloating ty) => Floating
557+ (Expression schema relations grouping params (nullity ty)) where
402558 pi = UnsafeExpression "pi()"
403559 exp = unsafeFunction "exp"
404560 log = unsafeFunction "ln"
405561 sqrt = unsafeFunction "sqrt"
406562 b ** x = UnsafeExpression $
407− "power(" <> renderSQL b <> ", " <> renderSQL x <> ")"
563+ "power(" <> renderExpression b <> ", " <> renderExpression x <> ")"
408564 logBase b y = log y / log b
409565 sin = unsafeFunction "sin"
410566 cos = unsafeFunction "cos"
@@ -419,54 +575,1106 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
419575 acosh x = log (x + sqrt (x*x - 1))
420576 atanh x = log ((1 + x) / (1 - x)) / 2
421577
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)
578+-- | >>> :{
579+-- let
580+-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
581+-- expression = atan2_ pi 2
582+-- in printSQL expression
583+-- :}
584+-- atan2(pi(), 2)
585+atan2_
586+ :: PGFloating float
587+ => Expression schema relations grouping params (nullity float)
588+ -- ^ numerator
589+ -> Expression schema relations grouping params (nullity float)
590+ -- ^ denominator
591+ -> Expression schema relations grouping params (nullity float)
592+atan2_ y x = UnsafeExpression $
593+ "atan2(" <> renderExpression y <> ", " <> renderExpression x <> ")"
594+
595+-- When a `cast` is applied to an `Expression` of a known type, it
596+-- represents a run-time type conversion. The cast will succeed only if a
597+-- suitable type conversion operation has been defined.
598+--
599+-- | >>> printSQL $ true & cast int4
600+-- (TRUE :: int4)
601+cast
602+ :: TypeExpression schema ty1
603+ -- ^ type to cast as
604+ -> Expression schema relations grouping params (nullity ty0)
605+ -- ^ value to convert
606+ -> Expression schema relations grouping params (nullity ty1)
607+cast ty x = UnsafeExpression $ parenthesized $
608+ renderExpression x <+> "::" <+> renderTypeExpression ty
609+
610+-- | integer division, truncates the result
611+--
612+-- >>> :{
613+-- let
614+-- expression :: Expression schema relations grouping params (nullity 'PGint2)
615+-- expression = 5 `quot_` 2
616+-- in printSQL expression
617+-- :}
618+-- (5 / 2)
619+quot_
620+ :: PGIntegral int
621+ => Expression schema relations grouping params (nullity int)
622+ -- ^ numerator
623+ -> Expression schema relations grouping params (nullity int)
624+ -- ^ denominator
625+ -> Expression schema relations grouping params (nullity int)
626+quot_ = unsafeBinaryOp "/"
627+
628+-- | remainder upon integer division
629+--
630+-- >>> :{
631+-- let
632+-- expression :: Expression schema relations grouping params (nullity 'PGint2)
633+-- expression = 5 `rem_` 2
634+-- in printSQL expression
635+-- :}
636+-- (5 % 2)
637+rem_
638+ :: PGIntegral int
639+ => Expression schema relations grouping params (nullity int)
640+ -- ^ numerator
641+ -> Expression schema relations grouping params (nullity int)
642+ -- ^ denominator
643+ -> Expression schema relations grouping params (nullity int)
644+rem_ = unsafeBinaryOp "%"
645+
646+-- | >>> :{
647+-- let
648+-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
649+-- expression = trunc pi
650+-- in printSQL expression
651+-- :}
652+-- trunc(pi())
653+trunc
654+ :: PGFloating frac
655+ => Expression schema relations grouping params (nullity frac)
656+ -- ^ fractional number
657+ -> Expression schema relations grouping params (nullity frac)
658+trunc = unsafeFunction "trunc"
659+
660+-- | >>> :{
661+-- let
662+-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
663+-- expression = round_ pi
664+-- in printSQL expression
665+-- :}
666+-- round(pi())
667+round_
668+ :: PGFloating frac
669+ => Expression schema relations grouping params (nullity frac)
670+ -- ^ fractional number
671+ -> Expression schema relations grouping params (nullity frac)
672+round_ = unsafeFunction "round"
673+
674+-- | >>> :{
675+-- let
676+-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
677+-- expression = ceiling_ pi
678+-- in printSQL expression
679+-- :}
680+-- ceiling(pi())
681+ceiling_
682+ :: PGFloating frac
683+ => Expression schema relations grouping params (nullity frac)
684+ -- ^ fractional number
685+ -> Expression schema relations grouping params (nullity frac)
686+ceiling_ = unsafeFunction "ceiling"
687+
688+-- | A `Condition` is a boolean valued `Expression`. While SQL allows
689+-- conditions to have @NULL@, Squeal instead chooses to disallow @NULL@,
690+-- forcing one to handle the case of @NULL@ explicitly to produce
691+-- a `Condition`.
692+type Condition schema relations grouping params =
693+ Expression schema relations grouping params ('NotNull 'PGbool)
694+
695+-- | >>> printSQL true
696+-- TRUE
697+true :: Condition schema relations grouping params
698+true = UnsafeExpression "TRUE"
699+
700+-- | >>> printSQL false
701+-- FALSE
702+false :: Condition schema relations grouping params
703+false = UnsafeExpression "FALSE"
704+
705+-- | >>> printSQL $ not_ true
706+-- (NOT TRUE)
707+not_
708+ :: Condition schema relations grouping params
709+ -> Condition schema relations grouping params
710+not_ = unsafeUnaryOp "NOT"
711+
712+-- | >>> printSQL $ true .&& false
713+-- (TRUE AND FALSE)
714+(.&&)
715+ :: Condition schema relations grouping params
716+ -> Condition schema relations grouping params
717+ -> Condition schema relations grouping params
718+(.&&) = unsafeBinaryOp "AND"
719+
720+-- | >>> printSQL $ true .|| false
721+-- (TRUE OR FALSE)
722+(.||)
723+ :: Condition schema relations grouping params
724+ -> Condition schema relations grouping params
725+ -> Condition schema relations grouping params
726+(.||) = unsafeBinaryOp "OR"
727+
728+-- | >>> :{
729+-- let
730+-- expression :: Expression schema relations grouping params (nullity 'PGint2)
731+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
732+-- in printSQL expression
733+-- :}
734+-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
735+caseWhenThenElse
736+ :: [ ( Condition schema relations grouping params
737+ , Expression schema relations grouping params (ty)
738+ ) ]
739+ -- ^ whens and thens
740+ -> Expression schema relations grouping params (ty)
741+ -- ^ else
742+ -> Expression schema relations grouping params (ty)
743+caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
744+ [ "CASE"
745+ , mconcat
746+ [ mconcat
747+ [ " WHEN ", renderExpression when_
748+ , " THEN ", renderExpression then_
749+ ]
750+ | (when_,then_) <- whenThens
751+ ]
752+ , " ELSE ", renderExpression else_
753+ , " END"
754+ ]
755+
756+-- | >>> :{
757+-- let
758+-- expression :: Expression schema relations grouping params (nullity 'PGint2)
759+-- expression = ifThenElse true 1 0
760+-- in printSQL expression
761+-- :}
762+-- CASE WHEN TRUE THEN 1 ELSE 0 END
763+ifThenElse
764+ :: Condition schema relations grouping params
765+ -> Expression schema relations grouping params (ty) -- ^ then
766+ -> Expression schema relations grouping params (ty) -- ^ else
767+ -> Expression schema relations grouping params (ty)
768+ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
769+
770+-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
771+-- will produce @NULL@s if one of their arguments is @NULL@.
772+--
773+-- >>> printSQL $ notNull true .== null_
774+-- (TRUE = NULL)
775+(.==)
776+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
777+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
778+ -> Expression schema relations grouping params (nullity 'PGbool)
779+(.==) = unsafeBinaryOp "="
780+infix 4 .==
781+
782+-- | >>> printSQL $ notNull true ./= null_
783+-- (TRUE <> NULL)
784+(./=)
785+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
786+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
787+ -> Expression schema relations grouping params (nullity 'PGbool)
788+(./=) = unsafeBinaryOp "<>"
789+infix 4 ./=
790+
791+-- | >>> printSQL $ notNull true .>= null_
792+-- (TRUE >= NULL)
793+(.>=)
794+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
795+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
796+ -> Expression schema relations grouping params (nullity 'PGbool)
797+(.>=) = unsafeBinaryOp ">="
798+infix 4 .>=
799+
800+-- | >>> printSQL $ notNull true .< null_
801+-- (TRUE < NULL)
802+(.<)
803+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
804+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
805+ -> Expression schema relations grouping params (nullity 'PGbool)
806+(.<) = unsafeBinaryOp "<"
807+infix 4 .<
808+
809+-- | >>> printSQL $ notNull true .<= null_
810+-- (TRUE <= NULL)
811+(.<=)
812+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
813+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
814+ -> Expression schema relations grouping params (nullity 'PGbool)
815+(.<=) = unsafeBinaryOp "<="
816+infix 4 .<=
817+
818+-- | >>> printSQL $ notNull true .> null_
819+-- (TRUE > NULL)
820+(.>)
821+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
822+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
823+ -> Expression schema relations grouping params (nullity 'PGbool)
824+(.>) = unsafeBinaryOp ">"
825+infix 4 .>
826+
827+-- | >>> printSQL currentDate
828+-- CURRENT_DATE
829+currentDate
830+ :: Expression schema relations grouping params (nullity 'PGdate)
831+currentDate = UnsafeExpression "CURRENT_DATE"
832+
833+-- | >>> printSQL currentTime
834+-- CURRENT_TIME
835+currentTime
836+ :: Expression schema relations grouping params (nullity 'PGtimetz)
837+currentTime = UnsafeExpression "CURRENT_TIME"
838+
839+-- | >>> printSQL currentTimestamp
840+-- CURRENT_TIMESTAMP
841+currentTimestamp
842+ :: Expression schema relations grouping params (nullity 'PGtimestamptz)
843+currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
844+
845+-- | >>> printSQL localTime
846+-- LOCALTIME
847+localTime
848+ :: Expression schema relations grouping params (nullity 'PGtime)
849+localTime = UnsafeExpression "LOCALTIME"
850+
851+-- | >>> printSQL localTimestamp
852+-- LOCALTIMESTAMP
853+localTimestamp
854+ :: Expression schema relations grouping params (nullity 'PGtimestamp)
855+localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
856+
857+{-----------------------------------------
858+text
859+-----------------------------------------}
438860
439861instance IsString
440− (Expression outer commons grp schemas params from (null 'PGtext)) where
862+ (Expression schema relations grouping params (nullity 'PGtext)) where
441863 fromString str = UnsafeExpression $
442864 "E\'" <> fromString (escape =<< str) <> "\'"
443−instance IsString
444− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
445− fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
446− "E\'" <> fromString (escape =<< str) <> "\'"
447−instance IsString
448− (Expression outer commons grp schemas params from (null 'PGtsquery)) where
449− fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
450− "E\'" <> fromString (escape =<< str) <> "\'"
865+ where
866+ escape = \case
867+ '\NUL' -> "\\0"
868+ '\'' -> "''"
869+ '"' -> "\\\""
870+ '\b' -> "\\b"
871+ '\n' -> "\\n"
872+ '\r' -> "\\r"
873+ '\t' -> "\\t"
874+ '\\' -> "\\\\"
875+ c -> [c]
451876
452877instance Semigroup
453− (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
454− (<>) = unsafeBinaryOp "||"
455−instance Semigroup
456− (Expression outer commons grp schemas params from (null 'PGjsonb)) where
457− (<>) = unsafeBinaryOp "||"
458−instance Semigroup
459− (Expression outer commons grp schemas params from (null 'PGtext)) where
460− (<>) = unsafeBinaryOp "||"
461−instance Semigroup
462− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
878+ (Expression schema relations grouping params (nullity 'PGtext)) where
463879 (<>) = unsafeBinaryOp "||"
464880
465881instance Monoid
466− (Expression outer commons grp schemas params from (null 'PGtext)) where
467− mempty = fromString ""
468− mappend = (<>)
469−instance Monoid
470− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
882+ (Expression schema relations grouping params (nullity 'PGtext)) where
471883 mempty = fromString ""
472884 mappend = (<>)
885+
886+-- | >>> printSQL $ lower "ARRRGGG"
887+-- lower(E'ARRRGGG')
888+lower
889+ :: Expression schema relations grouping params (nullity 'PGtext)
890+ -- ^ string to lower case
891+ -> Expression schema relations grouping params (nullity 'PGtext)
892+lower = unsafeFunction "lower"
893+
894+-- | >>> printSQL $ upper "eeee"
895+-- upper(E'eeee')
896+upper
897+ :: Expression schema relations grouping params (nullity 'PGtext)
898+ -- ^ string to upper case
899+ -> Expression schema relations grouping params (nullity 'PGtext)
900+upper = unsafeFunction "upper"
901+
902+-- | >>> printSQL $ charLength "four"
903+-- char_length(E'four')
904+charLength
905+ :: Expression schema relations grouping params (nullity 'PGtext)
906+ -- ^ string to measure
907+ -> Expression schema relations grouping params (nullity 'PGint4)
908+charLength = unsafeFunction "char_length"
909+
910+-- | The `like` expression returns true if the @string@ matches
911+-- the supplied @pattern@. If @pattern@ does not contain percent signs
912+-- or underscores, then the pattern only represents the string itself;
913+-- in that case `like` acts like the equals operator. An underscore (_)
914+-- in pattern stands for (matches) any single character; a percent sign (%)
915+-- matches any sequence of zero or more characters.
916+--
917+-- >>> printSQL $ "abc" `like` "a%"
918+-- (E'abc' LIKE E'a%')
919+like
920+ :: Expression schema relations grouping params (nullity 'PGtext)
921+ -- ^ string
922+ -> Expression schema relations grouping params (nullity 'PGtext)
923+ -- ^ pattern
924+ -> Expression schema relations grouping params (nullity 'PGbool)
925+like = unsafeBinaryOp "LIKE"
926+
927+{-----------------------------------------
928+ -- json and jsonb support
929+
930+See https://www.postgresql.org/docs/10/static/functions-json.html -- most
931+comments lifted directly from this page.
932+
933+Table 9.44: json and jsonb operators
934+-----------------------------------------}
935+
936+-- | Get JSON value (object field or array element) at a key.
937+(.->)
938+ :: (PGjson_ json, PGjsonKey key)
939+ => Expression schema relations grouping params (nullity json)
940+ -> Expression schema relations grouping params (nullity key)
941+ -> Expression schema relations grouping params ('Null json)
942+(.->) = unsafeBinaryOp "->"
943+
944+-- | Get JSON value (object field or array element) at a key, as text.
945+(.->>)
946+ :: (PGjson_ json, PGjsonKey key)
947+ => Expression schema relations grouping params (nullity json)
948+ -> Expression schema relations grouping params (nullity key)
949+ -> Expression schema relations grouping params ('Null 'PGtext)
950+(.->>) = unsafeBinaryOp "->>"
951+
952+-- | Get JSON value at a specified path.
953+(.#>)
954+ :: (PGjson_ json, PGtextArray "(.#>)" path)
955+ => Expression schema relations grouping params (nullity json)
956+ -> Expression schema relations grouping params (nullity path)
957+ -> Expression schema relations grouping params ('Null json)
958+(.#>) = unsafeBinaryOp "#>"
959+
960+-- | Get JSON value at a specified path as text.
961+(.#>>)
962+ :: (PGjson_ json, PGtextArray "(.#>>)" path)
963+ => Expression schema relations grouping params (nullity json)
964+ -> Expression schema relations grouping params (nullity path)
965+ -> Expression schema relations grouping params ('Null 'PGtext)
966+(.#>>) = unsafeBinaryOp "#>>"
967+
968+-- Additional jsonb operators
969+
970+-- | Does the left JSON value contain the right JSON path/value entries at the
971+-- top level?
972+(.@>)
973+ :: Expression schema relations grouping params (nullity 'PGjsonb)
974+ -> Expression schema relations grouping params (nullity 'PGjsonb)
975+ -> Expression schema relations grouping params ('NotNull 'PGbool)
976+(.@>) = unsafeBinaryOp "@>"
977+
978+-- | Are the left JSON path/value entries contained at the top level within the
979+-- right JSON value?
980+(.<@)
981+ :: Expression schema relations grouping params (nullity 'PGjsonb)
982+ -> Expression schema relations grouping params (nullity 'PGjsonb)
983+ -> Expression schema relations grouping params ('NotNull 'PGbool)
984+(.<@) = unsafeBinaryOp "<@"
985+
986+-- | Does the string exist as a top-level key within the JSON value?
987+(.?)
988+ :: Expression schema relations grouping params (nullity 'PGjsonb)
989+ -> Expression schema relations grouping params (nullity 'PGtext)
990+ -> Expression schema relations grouping params ('NotNull 'PGbool)
991+(.?) = unsafeBinaryOp "?"
992+
993+-- | Do any of these array strings exist as top-level keys?
994+(.?|)
995+ :: Expression schema relations grouping params (nullity 'PGjsonb)
996+ -> Expression schema relations grouping params (nullity ('PGvararray 'PGtext))
997+ -> Expression schema relations grouping params ('NotNull 'PGbool)
998+(.?|) = unsafeBinaryOp "?|"
999+
1000+-- | Do all of these array strings exist as top-level keys?
1001+(.?&)
1002+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1003+ -> Expression schema relations grouping params (nullity ('PGvararray 'PGtext))
1004+ -> Expression schema relations grouping params ('NotNull 'PGbool)
1005+(.?&) = unsafeBinaryOp "?&"
1006+
1007+-- | Concatenate two jsonb values into a new jsonb value.
1008+(.||.)
1009+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1010+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1011+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1012+(.||.) = unsafeBinaryOp "||"
1013+
1014+-- | Delete a key or keys from a JSON object, or remove an array element.
1015+--
1016+-- If the right operand is..
1017+--
1018+-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1019+-- are matched based on their key value.
1020+--
1021+-- @ text[] @: Delete multiple key/value pairs or string elements
1022+-- from left operand. Key/value pairs are matched based on their key value.
1023+--
1024+-- @ integer @: Delete the array element with specified index (Negative integers
1025+-- count from the end). Throws an error if top level container is not an array.
1026+(.-.)
1027+ :: (key `In` '[ 'PGtext, 'PGvararray 'PGtext, 'PGint4, 'PGint2 ]) -- hlint error without parens here
1028+ => Expression schema relations grouping params (nullity 'PGjsonb)
1029+ -> Expression schema relations grouping params (nullity key)
1030+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1031+(.-.) = unsafeBinaryOp "-"
1032+
1033+-- | Delete the field or element with specified path (for JSON arrays, negative
1034+-- integers count from the end)
1035+(#-.)
1036+ :: PGtextArray "(#-.)" arrayty
1037+ => Expression schema relations grouping params (nullity 'PGjsonb)
1038+ -> Expression schema relations grouping params (nullity arrayty)
1039+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1040+(#-.) = unsafeBinaryOp "#-"
1041+
1042+{-----------------------------------------
1043+Table 9.45: JSON creation functions
1044+-----------------------------------------}
1045+
1046+-- | Returns the value as json. Arrays and composites are converted
1047+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1048+-- type to json, the cast function will be used to perform the conversion;
1049+-- otherwise, a scalar value is produced. For any scalar type other than a
1050+-- number, a Boolean, or a null value, the text representation will be used, in
1051+-- such a fashion that it is a valid json value.
1052+toJson
1053+ :: Expression schema relations grouping params (nullity ty)
1054+ -> Expression schema relations grouping params (nullity 'PGjson)
1055+toJson = unsafeFunction "to_json"
1056+
1057+-- | Returns the value as jsonb. Arrays and composites are converted
1058+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1059+-- type to json, the cast function will be used to perform the conversion;
1060+-- otherwise, a scalar value is produced. For any scalar type other than a
1061+-- number, a Boolean, or a null value, the text representation will be used, in
1062+-- such a fashion that it is a valid jsonb value.
1063+toJsonb
1064+ :: Expression schema relations grouping params (nullity ty)
1065+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1066+toJsonb = unsafeUnaryOp "to_jsonb"
1067+
1068+-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1069+-- becomes a JSON array of arrays. Line feeds will be added between dimension-1
1070+-- elements if pretty_bool is true.
1071+arrayToJson
1072+ :: PGarray "arrayToJson" arr
1073+ => Expression schema relations grouping params (nullity arr)
1074+ -> Expression schema relations grouping params (nullity 'PGjson)
1075+arrayToJson = unsafeFunction "array_to_json"
1076+
1077+-- | Returns the row as a JSON object. Line feeds will be added between level-1
1078+-- elements if pretty_bool is true.
1079+rowToJson
1080+ :: Expression schema relations grouping params (nullity ('PGcomposite ty))
1081+ -> Expression schema relations grouping params (nullity 'PGjson)
1082+rowToJson = unsafeFunction "row_to_json"
1083+
1084+-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1085+-- argument list.
1086+jsonBuildArray
1087+ :: SListI elems
1088+ => NP (Expression schema relations grouping params) elems
1089+ -> Expression schema relations grouping params (nullity 'PGjson)
1090+jsonBuildArray = unsafeVariadicFunction "json_build_array"
1091+
1092+-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1093+-- variadic argument list.
1094+jsonbBuildArray
1095+ :: SListI elems
1096+ => NP (Expression schema relations grouping params) elems
1097+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1098+jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1099+
1100+-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1101+-- argument list. The elements of the argument list must alternate between text
1102+-- and values.
1103+jsonBuildObject
1104+ :: (PGobjectpairs "jsonBuildObject" elems, SListI elems)
1105+ => NP (Expression schema relations grouping params) elems
1106+ -> Expression schema relations grouping params (nullity 'PGjson)
1107+jsonBuildObject = unsafeVariadicFunction "json_build_object"
1108+
1109+-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1110+-- variadic argument list. The elements of the argument list must alternate
1111+-- between text and values.
1112+jsonbBuildObject
1113+ :: (PGobjectpairs "jsonbBuildObject" elems, SListI elems)
1114+ => NP (Expression schema relations grouping params) elems
1115+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1116+jsonbBuildObject = unsafeVariadicFunction "jsonb_build_object"
1117+
1118+-- | Builds a JSON object out of a text array. The array must have either
1119+-- exactly one dimension with an even number of members, in which case they are
1120+-- taken as alternating key/value pairs, or two dimensions such that each inner
1121+-- array has exactly two elements, which are taken as a key/value pair.
1122+jsonObject
1123+ :: PGarrayOf "jsonObject" arr 'PGtext
1124+ => Expression schema relations grouping params (nullity arr)
1125+ -> Expression schema relations grouping params (nullity 'PGjson)
1126+jsonObject = unsafeFunction "json_object"
1127+
1128+-- | Builds a binary JSON object out of a text array. The array must have either
1129+-- exactly one dimension with an even number of members, in which case they are
1130+-- taken as alternating key/value pairs, or two dimensions such that each inner
1131+-- array has exactly two elements, which are taken as a key/value pair.
1132+jsonbObject
1133+ :: PGarrayOf "jsonbObject" arr 'PGtext
1134+ => Expression schema relations grouping params (nullity arr)
1135+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1136+jsonbObject = unsafeFunction "jsonb_object"
1137+
1138+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1139+-- keys and one for values, that are zipped pairwise to create a JSON object.
1140+jsonZipObject
1141+ :: ( PGarrayOf "jsonZipObject" keysArray 'PGtext
1142+ , PGarrayOf "jsonZipObject" valuesArray 'PGtext)
1143+ => Expression schema relations grouping params (nullity keysArray)
1144+ -> Expression schema relations grouping params (nullity valuesArray)
1145+ -> Expression schema relations grouping params (nullity 'PGjson)
1146+jsonZipObject ks vs =
1147+ unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1148+
1149+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1150+-- keys and one for values, that are zipped pairwise to create a binary JSON
1151+-- object.
1152+jsonbZipObject
1153+ :: ( PGarrayOf "jsonbZipObject" keysArray 'PGtext
1154+ , PGarrayOf "jsonbZipObject" valuesArray 'PGtext)
1155+ => Expression schema relations grouping params (nullity keysArray)
1156+ -> Expression schema relations grouping params (nullity valuesArray)
1157+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1158+jsonbZipObject ks vs =
1159+ unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1160+
1161+{-----------------------------------------
1162+Table 9.46: JSON processing functions
1163+-----------------------------------------}
1164+
1165+-- | Returns the number of elements in the outermost JSON array.
1166+jsonArrayLength
1167+ :: Expression schema relations grouping params (nullity 'PGjson)
1168+ -> Expression schema relations grouping params (nullity 'PGint4)
1169+jsonArrayLength = unsafeFunction "json_array_length"
1170+
1171+-- | Returns the number of elements in the outermost binary JSON array.
1172+jsonbArrayLength
1173+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1174+ -> Expression schema relations grouping params (nullity 'PGint4)
1175+jsonbArrayLength = unsafeFunction "jsonb_array_length"
1176+
1177+-- | Returns JSON value pointed to by path_elems (equivalent to #> operator).
1178+jsonExtractPath
1179+ :: SListI elems
1180+ => Expression schema relations grouping params (nullity 'PGjson)
1181+ -> NP (Expression schema relations grouping params) elems
1182+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1183+jsonExtractPath x xs =
1184+ unsafeVariadicFunction "json_extract_path" (x :* xs)
1185+
1186+-- | Returns JSON value pointed to by path_elems (equivalent to #> operator).
1187+jsonbExtractPath
1188+ :: SListI elems
1189+ => Expression schema relations grouping params (nullity 'PGjsonb)
1190+ -> NP (Expression schema relations grouping params) elems
1191+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1192+jsonbExtractPath x xs =
1193+ unsafeVariadicFunction "jsonb_extract_path" (x :* xs)
1194+
1195+-- | Returns JSON value pointed to by path_elems (equivalent to #> operator),
1196+-- as text.
1197+jsonExtractPathAsText
1198+ :: SListI elems
1199+ => Expression schema relations grouping params (nullity 'PGjson)
1200+ -> NP (Expression schema relations grouping params) elems
1201+ -> Expression schema relations grouping params (nullity 'PGjson)
1202+jsonExtractPathAsText x xs =
1203+ unsafeVariadicFunction "json_extract_path_text" (x :* xs)
1204+
1205+-- | Returns JSON value pointed to by path_elems (equivalent to #> operator),
1206+-- as text.
1207+jsonbExtractPathAsText
1208+ :: SListI elems
1209+ => Expression schema relations grouping params (nullity 'PGjsonb)
1210+ -> NP (Expression schema relations grouping params) elems
1211+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1212+jsonbExtractPathAsText x xs =
1213+ unsafeVariadicFunction "jsonb_extract_path_text" (x :* xs)
1214+
1215+-- | Returns set of keys in the outermost JSON object.
1216+jsonObjectKeys
1217+ :: Expression schema relations grouping params (nullity 'PGjson)
1218+ -> Expression schema relations grouping params (nullity 'PGtext)
1219+jsonObjectKeys = unsafeFunction "json_object_keys"
1220+
1221+-- | Returns set of keys in the outermost JSON object.
1222+jsonbObjectKeys
1223+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1224+ -> Expression schema relations grouping params (nullity 'PGtext)
1225+jsonbObjectKeys = unsafeFunction "jsonb_object_keys"
1226+
1227+-- | Returns the type of the outermost JSON value as a text string. Possible
1228+-- types are object, array, string, number, boolean, and null.
1229+jsonTypeof
1230+ :: Expression schema relations grouping params (nullity 'PGjson)
1231+ -> Expression schema relations grouping params (nullity 'PGtext)
1232+jsonTypeof = unsafeFunction "json_typeof"
1233+
1234+-- | Returns the type of the outermost binary JSON value as a text string.
1235+-- Possible types are object, array, string, number, boolean, and null.
1236+jsonbTypeof
1237+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1238+ -> Expression schema relations grouping params (nullity 'PGtext)
1239+jsonbTypeof = unsafeFunction "jsonb_typeof"
1240+
1241+-- | Returns its argument with all object fields that have null values omitted.
1242+-- Other null values are untouched.
1243+jsonStripNulls
1244+ :: Expression schema relations grouping params (nullity 'PGjson)
1245+ -> Expression schema relations grouping params (nullity 'PGjson)
1246+jsonStripNulls = unsafeFunction "json_strip_nulls"
1247+
1248+-- | Returns its argument with all object fields that have null values omitted.
1249+-- Other null values are untouched.
1250+jsonbStripNulls
1251+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1252+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1253+jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1254+
1255+-- | @ jsonbSet target path new_value create_missing @
1256+--
1257+-- Returns target with the section designated by path replaced by new_value,
1258+-- or with new_value added if create_missing is true ( default is true) and the
1259+-- item designated by path does not exist. As with the path orientated
1260+-- operators, negative integers that appear in path count from the end of JSON
1261+-- arrays.
1262+jsonbSet
1263+ :: PGtextArray "jsonbSet" arr
1264+ => Expression schema relations grouping params (nullity 'PGjsonb)
1265+ -> Expression schema relations grouping params (nullity arr)
1266+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1267+ -> Maybe (Expression schema relations grouping params (nullity 'PGbool))
1268+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1269+jsonbSet tgt path val createMissing = case createMissing of
1270+ Just m -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* m :* Nil)
1271+ Nothing -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* Nil)
1272+
1273+-- | @ jsonbInsert target path new_value insert_after @
1274+--
1275+-- Returns target with new_value inserted. If target section designated by
1276+-- path is in a JSONB array, new_value will be inserted before target or after
1277+-- if insert_after is true (default is false). If target section designated by
1278+-- path is in JSONB object, new_value will be inserted only if target does not
1279+-- exist. As with the path orientated operators, negative integers that appear
1280+-- in path count from the end of JSON arrays.
1281+jsonbInsert
1282+ :: PGtextArray "jsonbInsert" arr
1283+ => Expression schema relations grouping params (nullity 'PGjsonb)
1284+ -> Expression schema relations grouping params (nullity arr)
1285+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1286+ -> Maybe (Expression schema relations grouping params (nullity 'PGbool))
1287+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1288+jsonbInsert tgt path val insertAfter = case insertAfter of
1289+ Just i -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1290+ Nothing -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* Nil)
1291+
1292+-- | Returns its argument as indented JSON text.
1293+jsonbPretty
1294+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1295+ -> Expression schema relations grouping params (nullity 'PGtext)
1296+jsonbPretty = unsafeFunction "jsonb_pretty"
1297+
1298+{-----------------------------------------
1299+aggregation
1300+-----------------------------------------}
1301+
1302+-- | escape hatch to define aggregate functions
1303+unsafeAggregate
1304+ :: ByteString -- ^ aggregate function
1305+ -> Expression schema relations 'Ungrouped params (xty)
1306+ -> Expression schema relations ('Grouped bys) params (yty)
1307+unsafeAggregate fun x = UnsafeExpression $ mconcat
1308+ [fun, "(", renderExpression x, ")"]
1309+
1310+-- | escape hatch to define aggregate functions over distinct values
1311+unsafeAggregateDistinct
1312+ :: ByteString -- ^ aggregate function
1313+ -> Expression schema relations 'Ungrouped params (xty)
1314+ -> Expression schema relations ('Grouped bys) params (yty)
1315+unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
1316+ [fun, "(DISTINCT ", renderExpression x, ")"]
1317+
1318+-- | >>> :{
1319+-- let
1320+-- expression :: Expression schema '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Grouped bys) params ('Null 'PGnumeric)
1321+-- expression = sum_ #col
1322+-- in printSQL expression
1323+-- :}
1324+-- sum("col")
1325+sum_
1326+ :: PGNum ty
1327+ => Expression schema relations 'Ungrouped params (nullity ty)
1328+ -- ^ what to sum
1329+ -> Expression schema relations ('Grouped bys) params (nullity ty)
1330+sum_ = unsafeAggregate "sum"
1331+
1332+-- | >>> :{
1333+-- let
1334+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGnumeric]] ('Grouped bys) params (nullity 'PGnumeric)
1335+-- expression = sumDistinct #col
1336+-- in printSQL expression
1337+-- :}
1338+-- sum(DISTINCT "col")
1339+sumDistinct
1340+ :: PGNum ty
1341+ => Expression schema relations 'Ungrouped params (nullity ty)
1342+ -- ^ what to sum
1343+ -> Expression schema relations ('Grouped bys) params (nullity ty)
1344+sumDistinct = unsafeAggregateDistinct "sum"
1345+
1346+-- | A constraint for `PGType`s that you can take averages of and the resulting
1347+-- `PGType`.
1348+class PGAvg ty avg | ty -> avg where
1349+ avg, avgDistinct
1350+ :: Expression schema relations 'Ungrouped params (nullity ty)
1351+ -- ^ what to average
1352+ -> Expression schema relations ('Grouped bys) params (nullity avg)
1353+ avg = unsafeAggregate "avg"
1354+ avgDistinct = unsafeAggregateDistinct "avg"
1355+instance PGAvg 'PGint2 'PGnumeric
1356+instance PGAvg 'PGint4 'PGnumeric
1357+instance PGAvg 'PGint8 'PGnumeric
1358+instance PGAvg 'PGnumeric 'PGnumeric
1359+instance PGAvg 'PGfloat4 'PGfloat8
1360+instance PGAvg 'PGfloat8 'PGfloat8
1361+instance PGAvg 'PGinterval 'PGinterval
1362+
1363+-- | >>> :{
1364+-- let
1365+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1366+-- expression = bitAnd #col
1367+-- in printSQL expression
1368+-- :}
1369+-- bit_and("col")
1370+bitAnd
1371+ :: PGIntegral int
1372+ => Expression schema relations 'Ungrouped params (nullity int)
1373+ -- ^ what to aggregate
1374+ -> Expression schema relations ('Grouped bys) params (nullity int)
1375+bitAnd = unsafeAggregate "bit_and"
1376+
1377+-- | >>> :{
1378+-- let
1379+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1380+-- expression = bitOr #col
1381+-- in printSQL expression
1382+-- :}
1383+-- bit_or("col")
1384+bitOr
1385+ :: PGIntegral int
1386+ => Expression schema relations 'Ungrouped params (nullity int)
1387+ -- ^ what to aggregate
1388+ -> Expression schema relations ('Grouped bys) params (nullity int)
1389+bitOr = unsafeAggregate "bit_or"
1390+
1391+-- | >>> :{
1392+-- let
1393+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1394+-- expression = bitAndDistinct #col
1395+-- in printSQL expression
1396+-- :}
1397+-- bit_and(DISTINCT "col")
1398+bitAndDistinct
1399+ :: PGIntegral int
1400+ => Expression schema relations 'Ungrouped params (nullity int)
1401+ -- ^ what to aggregate
1402+ -> Expression schema relations ('Grouped bys) params (nullity int)
1403+bitAndDistinct = unsafeAggregateDistinct "bit_and"
1404+
1405+-- | >>> :{
1406+-- let
1407+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1408+-- expression = bitOrDistinct #col
1409+-- in printSQL expression
1410+-- :}
1411+-- bit_or(DISTINCT "col")
1412+bitOrDistinct
1413+ :: PGIntegral int
1414+ => Expression schema relations 'Ungrouped params (nullity int)
1415+ -- ^ what to aggregate
1416+ -> Expression schema relations ('Grouped bys) params (nullity int)
1417+bitOrDistinct = unsafeAggregateDistinct "bit_or"
1418+
1419+-- | >>> :{
1420+-- let
1421+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1422+-- expression = boolAnd #col
1423+-- in printSQL expression
1424+-- :}
1425+-- bool_and("col")
1426+boolAnd
1427+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1428+ -- ^ what to aggregate
1429+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1430+boolAnd = unsafeAggregate "bool_and"
1431+
1432+-- | >>> :{
1433+-- let
1434+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1435+-- expression = boolOr #col
1436+-- in printSQL expression
1437+-- :}
1438+-- bool_or("col")
1439+boolOr
1440+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1441+ -- ^ what to aggregate
1442+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1443+boolOr = unsafeAggregate "bool_or"
1444+
1445+-- | >>> :{
1446+-- let
1447+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1448+-- expression = boolAndDistinct #col
1449+-- in printSQL expression
1450+-- :}
1451+-- bool_and(DISTINCT "col")
1452+boolAndDistinct
1453+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1454+ -- ^ what to aggregate
1455+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1456+boolAndDistinct = unsafeAggregateDistinct "bool_and"
1457+
1458+-- | >>> :{
1459+-- let
1460+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1461+-- expression = boolOrDistinct #col
1462+-- in printSQL expression
1463+-- :}
1464+-- bool_or(DISTINCT "col")
1465+boolOrDistinct
1466+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1467+ -- ^ what to aggregate
1468+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1469+boolOrDistinct = unsafeAggregateDistinct "bool_or"
1470+
1471+-- | A special aggregation that does not require an input
1472+--
1473+-- >>> printSQL countStar
1474+-- count(*)
1475+countStar
1476+ :: Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1477+countStar = UnsafeExpression $ "count(*)"
1478+
1479+-- | >>> :{
1480+-- let
1481+-- expression :: Expression schema '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
1482+-- expression = count #col
1483+-- in printSQL expression
1484+-- :}
1485+-- count("col")
1486+count
1487+ :: Expression schema relations 'Ungrouped params ty
1488+ -- ^ what to count
1489+ -> Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1490+count = unsafeAggregate "count"
1491+
1492+-- | >>> :{
1493+-- let
1494+-- expression :: Expression schema '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
1495+-- expression = countDistinct #col
1496+-- in printSQL expression
1497+-- :}
1498+-- count(DISTINCT "col")
1499+countDistinct
1500+ :: Expression schema relations 'Ungrouped params ty
1501+ -- ^ what to count
1502+ -> Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1503+countDistinct = unsafeAggregateDistinct "count"
1504+
1505+-- | synonym for `boolAnd`
1506+--
1507+-- >>> :{
1508+-- let
1509+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1510+-- expression = every #col
1511+-- in printSQL expression
1512+-- :}
1513+-- every("col")
1514+every
1515+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1516+ -- ^ what to aggregate
1517+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1518+every = unsafeAggregate "every"
1519+
1520+-- | synonym for `boolAndDistinct`
1521+--
1522+-- >>> :{
1523+-- let
1524+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1525+-- expression = everyDistinct #col
1526+-- in printSQL expression
1527+-- :}
1528+-- every(DISTINCT "col")
1529+everyDistinct
1530+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1531+ -- ^ what to aggregate
1532+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1533+everyDistinct = unsafeAggregateDistinct "every"
1534+
1535+-- | minimum and maximum aggregation
1536+max_, min_, maxDistinct, minDistinct
1537+ :: Expression schema relations 'Ungrouped params (nullity ty)
1538+ -- ^ what to aggregate
1539+ -> Expression schema relations ('Grouped bys) params (nullity ty)
1540+max_ = unsafeAggregate "max"
1541+min_ = unsafeAggregate "min"
1542+maxDistinct = unsafeAggregateDistinct "max"
1543+minDistinct = unsafeAggregateDistinct "min"
1544+
1545+{-----------------------------------------
1546+type expressions
1547+-----------------------------------------}
1548+
1549+-- | `TypeExpression`s are used in `cast`s and `createTable` commands.
1550+newtype TypeExpression (schema :: SchemaType) (ty :: PGType)
1551+ = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1552+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
1553+
1554+instance (Has alias schema ('Typedef ty))
1555+ => IsLabel alias (TypeExpression schema ty) where
1556+ fromLabel = UnsafeTypeExpression (renderAlias (fromLabel @alias))
1557+
1558+-- | logical Boolean (true/false)
1559+bool :: TypeExpression schema 'PGbool
1560+bool = UnsafeTypeExpression "bool"
1561+-- | signed two-byte integer
1562+int2, smallint :: TypeExpression schema 'PGint2
1563+int2 = UnsafeTypeExpression "int2"
1564+smallint = UnsafeTypeExpression "smallint"
1565+-- | signed four-byte integer
1566+int4, int, integer :: TypeExpression schema 'PGint4
1567+int4 = UnsafeTypeExpression "int4"
1568+int = UnsafeTypeExpression "int"
1569+integer = UnsafeTypeExpression "integer"
1570+-- | signed eight-byte integer
1571+int8, bigint :: TypeExpression schema 'PGint8
1572+int8 = UnsafeTypeExpression "int8"
1573+bigint = UnsafeTypeExpression "bigint"
1574+-- | arbitrary precision numeric type
1575+numeric :: TypeExpression schema 'PGnumeric
1576+numeric = UnsafeTypeExpression "numeric"
1577+-- | single precision floating-point number (4 bytes)
1578+float4, real :: TypeExpression schema 'PGfloat4
1579+float4 = UnsafeTypeExpression "float4"
1580+real = UnsafeTypeExpression "real"
1581+-- | double precision floating-point number (8 bytes)
1582+float8, doublePrecision :: TypeExpression schema 'PGfloat8
1583+float8 = UnsafeTypeExpression "float8"
1584+doublePrecision = UnsafeTypeExpression "double precision"
1585+-- | variable-length character string
1586+text :: TypeExpression schema 'PGtext
1587+text = UnsafeTypeExpression "text"
1588+-- | fixed-length character string
1589+char, character
1590+ :: (KnownNat n, 1 <= n)
1591+ => proxy n
1592+ -> TypeExpression schema ('PGchar n)
1593+char p = UnsafeTypeExpression $ "char(" <> renderNat p <> ")"
1594+character p = UnsafeTypeExpression $ "character(" <> renderNat p <> ")"
1595+-- | variable-length character string
1596+varchar, characterVarying
1597+ :: (KnownNat n, 1 <= n)
1598+ => proxy n
1599+ -> TypeExpression schema ('PGvarchar n)
1600+varchar p = UnsafeTypeExpression $ "varchar(" <> renderNat p <> ")"
1601+characterVarying p = UnsafeTypeExpression $
1602+ "character varying(" <> renderNat p <> ")"
1603+-- | binary data ("byte array")
1604+bytea :: TypeExpression schema 'PGbytea
1605+bytea = UnsafeTypeExpression "bytea"
1606+-- | date and time (no time zone)
1607+timestamp :: TypeExpression schema 'PGtimestamp
1608+timestamp = UnsafeTypeExpression "timestamp"
1609+-- | date and time, including time zone
1610+timestampWithTimeZone :: TypeExpression schema 'PGtimestamptz
1611+timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1612+-- | calendar date (year, month, day)
1613+date :: TypeExpression schema 'PGdate
1614+date = UnsafeTypeExpression "date"
1615+-- | time of day (no time zone)
1616+time :: TypeExpression schema 'PGtime
1617+time = UnsafeTypeExpression "time"
1618+-- | time of day, including time zone
1619+timeWithTimeZone :: TypeExpression schema 'PGtimetz
1620+timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1621+-- | time span
1622+interval :: TypeExpression schema 'PGinterval
1623+interval = UnsafeTypeExpression "interval"
1624+-- | universally unique identifier
1625+uuid :: TypeExpression schema 'PGuuid
1626+uuid = UnsafeTypeExpression "uuid"
1627+-- | IPv4 or IPv6 host address
1628+inet :: TypeExpression schema 'PGinet
1629+inet = UnsafeTypeExpression "inet"
1630+-- | textual JSON data
1631+json :: TypeExpression schema 'PGjson
1632+json = UnsafeTypeExpression "json"
1633+-- | binary JSON data, decomposed
1634+jsonb :: TypeExpression schema 'PGjsonb
1635+jsonb = UnsafeTypeExpression "jsonb"
1636+-- | variable length array
1637+vararray
1638+ :: TypeExpression schema pg
1639+ -> TypeExpression schema ('PGvararray pg)
1640+vararray ty = UnsafeTypeExpression $ renderTypeExpression ty <> "[]"
1641+-- | fixed length array
1642+--
1643+-- >>> renderTypeExpression (fixarray (Proxy @2) json)
1644+-- "json[2]"
1645+fixarray
1646+ :: KnownNat n
1647+ => proxy n
1648+ -> TypeExpression schema pg
1649+ -> TypeExpression schema ('PGfixarray n pg)
1650+fixarray p ty = UnsafeTypeExpression $
1651+ renderTypeExpression ty <> "[" <> renderNat p <> "]"
1652+
1653+-- | `pgtype` is a demoted version of a `PGType`
1654+class PGTyped schema (ty :: PGType) where pgtype :: TypeExpression schema ty
1655+instance PGTyped schema 'PGbool where pgtype = bool
1656+instance PGTyped schema 'PGint2 where pgtype = int2
1657+instance PGTyped schema 'PGint4 where pgtype = int4
1658+instance PGTyped schema 'PGint8 where pgtype = int8
1659+instance PGTyped schema 'PGnumeric where pgtype = numeric
1660+instance PGTyped schema 'PGfloat4 where pgtype = float4
1661+instance PGTyped schema 'PGfloat8 where pgtype = float8
1662+instance PGTyped schema 'PGtext where pgtype = text
1663+instance (KnownNat n, 1 <= n)
1664+ => PGTyped schema ('PGchar n) where pgtype = char (Proxy @n)
1665+instance (KnownNat n, 1 <= n)
1666+ => PGTyped schema ('PGvarchar n) where pgtype = varchar (Proxy @n)
1667+instance PGTyped schema 'PGbytea where pgtype = bytea
1668+instance PGTyped schema 'PGtimestamp where pgtype = timestamp
1669+instance PGTyped schema 'PGtimestamptz where pgtype = timestampWithTimeZone
1670+instance PGTyped schema 'PGdate where pgtype = date
1671+instance PGTyped schema 'PGtime where pgtype = time
1672+instance PGTyped schema 'PGtimetz where pgtype = timeWithTimeZone
1673+instance PGTyped schema 'PGinterval where pgtype = interval
1674+instance PGTyped schema 'PGuuid where pgtype = uuid
1675+instance PGTyped schema 'PGjson where pgtype = json
1676+instance PGTyped schema 'PGjsonb where pgtype = jsonb
1677+instance PGTyped schema ty => PGTyped schema ('PGvararray ty) where
1678+ pgtype = vararray (pgtype @schema @ty)
1679+instance (KnownNat n, PGTyped schema ty) => PGTyped schema ('PGfixarray n ty) where
1680+ pgtype = fixarray (Proxy @n) (pgtype @schema @ty)