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