@@ -1,13 +1,14 @@
2−Module: Squeal.PostgreSQL.Expression
2+Module: Squeal.PostgreSQL.Query
3Description: Squeal expressions
3Description: Squeal expressions
4−Copyright: (c) Eitan Chatav, 2019
4+Copyright: (c) Eitan Chatav, 2017
5Maintainer: eitan@morphism.tech
5Maintainer: eitan@morphism.tech
6Stability: experimental
6Stability: experimental
8Squeal expressions are the atoms used to build statements.
8Squeal expressions are the atoms used to build statements.
11+{-# OPTIONS_GHC -fno-warn-redundant-constraints -fno-warn-unticked-promoted-constructors #-}
11{-# LANGUAGE
12{-# LANGUAGE
12 AllowAmbiguousTypes
13 AllowAmbiguousTypes
13 , ConstraintKinds
14 , ConstraintKinds
@@ -15,13 +16,11 @@ Squeal expressions are the atoms used to build statements.
15 , FlexibleContexts
16 , FlexibleContexts
16 , FlexibleInstances
17 , FlexibleInstances
17 , FunctionalDependencies
18 , FunctionalDependencies
19 , GeneralizedNewtypeDeriving
19 , GeneralizedNewtypeDeriving
20 , LambdaCase
20 , LambdaCase
21 , MagicHash
21 , MagicHash
22 , OverloadedStrings
22 , OverloadedStrings
23 , ScopedTypeVariables
23 , ScopedTypeVariables
25 , TypeApplications
24 , TypeApplications
26 , TypeFamilies
25 , TypeFamilies
27 , TypeInType
26 , TypeInType
@@ -32,351 +31,497 @@ Squeal expressions are the atoms used to build statements.
33module Squeal.PostgreSQL.Expression
32module Squeal.PostgreSQL.Expression
34 ( -- * Expression
33 ( -- * Expression
35− Expression (..)
34+ Expression (UnsafeExpression, renderExpression)
36− , Expr
35+ , HasParameter (parameter)
37− , type (-->)
36+ , param
38− , FunctionDB
37+ -- ** Null
39− , unsafeFunction
38+ , null_
40− , function
39+ , notNull
41− , unsafeLeftOp
40+ , coalesce
42− , leftOp
41+ , fromNull
43− , unsafeRightOp
42+ , isNull
44− , rightOp
43+ , isNotNull
45− , Operator
44+ , matchNull
46− , OperatorDB
45+ , nullIf
47 , unsafeBinaryOp
50 , unsafeBinaryOp
48− , binaryOp
51+ , unsafeUnaryOp
49− , FunctionVar
52+ , unsafeFunction
50− , unsafeFunctionVar
53+ , unsafeVariadicFunction
51− , type (--->)
54+ , atan2_
52− , FunctionNDB
55+ , cast
53− , unsafeFunctionN
56+ , quot_
54− , functionN
57+ , rem_
55− , PGSubset (..)
58+ , trunc
56− , PGIntersect (..)
59+ , round_
89+ -- ** json or jsonb operators
99+ -- *** jsonb only operators
120+ , unsafeAggregate, unsafeAggregateDistinct
122+ , PGAvg (avg, avgDistinct)
123+ , bitAnd, bitOr, boolAnd, boolOr
124+ , bitAndDistinct, bitOrDistinct, boolAndDistinct, boolOrDistinct
126+ , count, countDistinct
127+ , every, everyDistinct
128+ , max_, maxDistinct, min_, minDistinct
130+ , TypeExpression (UnsafeTypeExpression, renderTypeExpression)
152+ , timestampWithTimeZone
57 -- * Re-export
163 -- * Re-export
59− , K (..)
165+ , NP ((:*), Nil)
63import Control.Category
168import Control.Category
64import Control.DeepSeq
169import Control.DeepSeq
65import Data.ByteString (ByteString)
170import Data.ByteString (ByteString)
66import Data.Function ((&))
171import Data.Function ((&))
67−import Data.Semigroup hiding (All)
172+import Data.Semigroup
68import Data.String
174import Data.String
69−import Generics.SOP hiding (All, from)
175+import Generics.SOP hiding (from)
176+import GHC.Exts (Constraint)
70import GHC.OverloadedLabels
177import GHC.OverloadedLabels
71import GHC.TypeLits
178import GHC.TypeLits
73import Prelude hiding (id, (.))
179import Prelude hiding (id, (.))
75import qualified GHC.Generics as GHC
181import qualified GHC.Generics as GHC
77−import Squeal.PostgreSQL.Alias
78−import Squeal.PostgreSQL.List
79import Squeal.PostgreSQL.Render
183import Squeal.PostgreSQL.Render
80import Squeal.PostgreSQL.Schema
184import Squeal.PostgreSQL.Schema
83−-- >>> import Squeal.PostgreSQL
85{-----------------------------------------
186{-----------------------------------------
86column expressions
187column expressions
87-----------------------------------------}
188-----------------------------------------}
89{- | `Expression`s are used in a variety of contexts,
190{- | `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,
191+such as in the target list of the `Squeal.PostgreSQL.Query.select` command,
92as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
192as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
93`Squeal.PostgreSQL.Manipulation.update`,
193`Squeal.PostgreSQL.Manipulation.update`,
94−or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
194+or in search `Condition`s in a number of commands.
96The expression syntax allows the calculation of
196The expression syntax allows the calculation of
97values from primitive expression using arithmetic, logical,
197values from primitive expression using arithmetic, logical,
98and other operations.
198and other operations.
100−The type parameters of `Expression` are
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`.
114newtype Expression
200newtype Expression
115− (outer :: FromType)
201+ (schema :: SchemaType)
116− (commons :: FromType)
202+ (relations :: RelationsType)
117− (grp :: Grouping)
203+ (grouping :: Grouping)
118− (schemas :: SchemasType)
119 (params :: [NullityType])
204 (params :: [NullityType])
121 (ty :: NullityType)
205 (ty :: NullityType)
122 = UnsafeExpression { renderExpression :: ByteString }
206 = UnsafeExpression { renderExpression :: ByteString }
123 deriving (GHC.Generic,Show,Eq,Ord,NFData)
207 deriving (GHC.Generic,Show,Eq,Ord,NFData)
124−instance RenderSQL (Expression outer commons grp schemas params from ty) where
209+instance RenderSQL (Expression schema relations grouping params ty) where
125 renderSQL = renderExpression
210 renderSQL = renderExpression
127−-- | An `Expr` is a closed `Expression`.
212+{- | A `HasParameter` constraint is used to indicate a value that is
128−-- It is a F@RankNType@ but don't be scared.
213+supplied externally to a SQL statement.
129−-- Think of it as an expression which sees no
214+`Squeal.PostgreSQL.PQ.manipulateParams`,
130−-- namespaces, so you can't use parameters
215+`Squeal.PostgreSQL.PQ.queryParams` and
131−-- or alias references. It can be used as
216+`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
132−-- a simple piece of more complex `Expression`s.
217+separately from the SQL command string, in which case `param`s are used to
133−type Expr x
218+refer to the out-of-line data values.
134− = forall outer commons grp schemas params from
135− . Expression outer commons grp schemas params from x
136− -- ^ cannot reference aliases
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
143− -> Expression outer commons grp schemas params from x2
145− -> Expression outer commons grp schemas params from y
148−type OperatorDB schemas x1 x2 y
149− = forall outer commons grp params from
150− . Expression outer commons grp schemas params from x1
152− -> Expression outer commons grp schemas params from x2
154− -> Expression outer commons grp schemas params from y
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`.
163− = forall outer commons grp schemas params from
164− . Expression outer commons grp schemas params from x
166− -> Expression outer commons grp schemas params from y
169−type FunctionDB schemas x y
170− = forall outer commons grp params from
171− . Expression outer commons grp schemas params from x
173− -> Expression outer commons grp schemas params from y
176−{- | A @RankNType@ for functions with a fixed-length list of heterogeneous arguments.
177−Use the `*:` operator to end your argument lists, like so.
179−>>> printSQL (unsafeFunctionN "fun" (true :* false :* localTime *: true))
180−fun(TRUE, FALSE, LOCALTIME, TRUE)
183− = forall outer commons grp schemas params from
184− . NP (Expression outer commons grp schemas params from) xs
186− -> Expression outer commons grp schemas params from y
189−type FunctionNDB schemas xs y
190− = forall outer commons grp params from
191− . NP (Expression outer commons grp schemas params from) xs
193− -> Expression outer commons grp schemas params from y
196−{- | A @RankNType@ for functions with a variable-length list of
197−homogeneous arguments and at least 1 more argument.
199−type FunctionVar x0 x1 y
220+class KnownNat n => HasParameter
200− = forall outer commons grp schemas params from
221+ (n :: Nat)
201− . [Expression outer commons grp schemas params from x0]
222+ (schema :: SchemaType)
202− -- ^ inputs
223+ (params :: [NullityType])
203− -> Expression outer commons grp schemas params from x1
224+ (ty :: NullityType)
204− -- ^ must have at least 1 input
225+ | n params -> ty where
205− -> Expression outer commons grp schemas params from y
226+ -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
207−
228+ -- >>> let expr = parameter @1 int4 :: Expression sch rels grp '[ 'Null 'PGint4] ('Null 'PGint4)
208−{- | >>> printSQL (unsafeFunctionVar "greatest" [true, null_] false)
229+ -- >>> printSQL expr
209−greatest(TRUE, NULL, FALSE)
230+ -- ($1 :: int4)
211−unsafeFunctionVar :: ByteString -> FunctionVar x0 x1 y
232+ :: TypeExpression schema (PGTypeOf ty)
233+ -> Expression schema relations grouping params ty
212−unsafeFunctionVar fun xs x = UnsafeExpression $ fun <> parenthesized
234+ parameter ty = UnsafeExpression $ parenthesized $
213− (commaSeparated (renderSQL <$> xs) <> ", " <> renderSQL x)
235+ "$" <> renderNat (Proxy @n) <+> "::"
214−
236+ <+> renderTypeExpression ty
215−instance (HasUnique tab (Join outer from) row, Has col row ty)
237+instance {-# OVERLAPPING #-} HasParameter 1 schema (ty1:tys) ty1
216− => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
238+instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) schema params ty)
217− fromLabel = UnsafeExpression $ renderSQL (Alias @col)
239+ => HasParameter n schema (ty' : params) ty
218−instance (HasUnique tab (Join outer from) row, Has col row ty, tys ~ '[ty])
240+
219− => IsLabel col (NP (Expression outer commons 'Ungrouped schemas params from) tys) where
241+-- | `param` takes a `Nat` using type application and for basic types,
220− fromLabel = fromLabel @col :* Nil
242+-- infers a `TypeExpression`.
244+-- >>> let expr = param @1 :: Expression sch rels grp '[ 'Null 'PGint4] ('Null 'PGint4)
248+ :: forall n schema params relations grouping ty
249+ . (PGTyped schema (PGTypeOf ty), HasParameter n schema params ty)
250+ => Expression schema relations grouping params ty -- ^ param
251+param = parameter @n pgtype
221−instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
253+instance (HasUnique relation relations columns, Has column columns ty)
223− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
254+ => IsLabel column (Expression schema relations 'Ungrouped params ty) where
224− fromLabel = fromLabel @col `As` Alias
255+ fromLabel = UnsafeExpression $ renderAlias (Alias @column)
225−instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
256+instance (HasUnique relation relations columns, Has column columns ty)
226− => IsLabel col
257+ => IsLabel column
227− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
258+ (Aliased (Expression schema relations 'Ungrouped params) (column ::: ty)) where
228− fromLabel = fromLabel @col :* Nil
259+ fromLabel = fromLabel @column `As` Alias @column
229−
260+instance (HasUnique relation relations columns, Has column columns ty)
230−instance (Has tab (Join outer from) row, Has col row ty)
261+ => IsLabel column
231− => IsQualified tab col (Expression outer commons 'Ungrouped schemas params from ty) where
262+ (NP (Aliased (Expression schema relations 'Ungrouped params)) '[column ::: ty]) where
232− tab ! col = UnsafeExpression $
263+ fromLabel = fromLabel @column :* Nil
233− renderSQL tab <> "." <> renderSQL col
264+
234−instance (Has tab (Join outer from) row, Has col row ty, tys ~ '[ty])
265+instance (Has relation relations columns, Has column columns ty)
235− => IsQualified tab col (NP (Expression outer commons 'Ungrouped schemas params from) tys) where
266+ => IsQualified relation column (Expression schema relations 'Ungrouped params ty) where
236− tab ! col = tab ! col :* Nil
267+ relation ! column = UnsafeExpression $
268+ renderAlias relation <> "." <> renderAlias column
237−instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
269+instance (Has relation relations columns, Has column columns ty)
238− => IsQualified tab col
270+ => IsQualified relation column
239− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
271+ (Aliased (Expression schema relations 'Ungrouped params) (column ::: ty)) where
240− tab ! col = tab ! col `As` col
272+ relation ! column = relation ! column `As` column
241−instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
273+instance (Has relation relations columns, Has column columns ty)
242− => IsQualified tab col
274+ => IsQualified relation column
243− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
275+ (NP (Aliased (Expression schema relations 'Ungrouped params)) '[column ::: ty]) where
244− tab ! col = tab ! col :* Nil
276+ relation ! column = relation ! column :* Nil
247− ( HasUnique tab (Join outer from) row
279+ ( HasUnique relation relations columns
248− , Has col row ty
280+ , Has column columns ty
249− , GroupedBy tab col bys
281+ , GroupedBy relation column bys
250− ) => IsLabel col
282+ ) => IsLabel column
251− (Expression outer commons ('Grouped bys) schemas params from ty) where
283+ (Expression schema relations ('Grouped bys) params ty) where
252− fromLabel = UnsafeExpression $ renderSQL (Alias @col)
284+ fromLabel = UnsafeExpression $ renderAlias (Alias @column)
254− ( HasUnique tab (Join outer from) row
256− , GroupedBy tab col bys
259− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
260− fromLabel = fromLabel @col :* Nil
262− ( HasUnique tab (Join outer from) row
286+ ( HasUnique relation relations columns
263− , Has col row ty
287+ , Has column columns ty
264− , GroupedBy tab col bys
288+ , GroupedBy relation column bys
265− , column ~ (col ::: ty)
266− ) => IsLabel col
289+ ) => IsLabel column
267− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
290+ ( Aliased (Expression schema relations ('Grouped bys) params)
291+ (column ::: ty) ) where
268− fromLabel = fromLabel @col `As` Alias
292+ fromLabel = fromLabel @column `As` Alias @column
270− ( HasUnique tab (Join outer from) row
294+ ( HasUnique relation relations columns
271− , Has col row ty
295+ , Has column columns ty
272− , GroupedBy tab col bys
296+ , GroupedBy relation column bys
273− , columns ~ '[col ::: ty]
274− ) => IsLabel col
297+ ) => IsLabel column
275− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
298+ ( NP (Aliased (Expression schema relations ('Grouped bys) params))
299+ '[column ::: ty] ) where
276− fromLabel = fromLabel @col :* Nil
300+ fromLabel = fromLabel @column :* Nil
279− ( Has tab (Join outer from) row
303+ ( Has relation relations columns
280− , Has col row ty
304+ , Has column columns ty
281− , GroupedBy tab col bys
305+ , GroupedBy relation column bys
282− ) => IsQualified tab col
306+ ) => IsQualified relation column
283− (Expression outer commons ('Grouped bys) schemas params from ty) where
307+ (Expression schema relations ('Grouped bys) params ty) where
284− tab ! col = UnsafeExpression $
308+ relation ! column = UnsafeExpression $
285− renderSQL tab <> "." <> renderSQL col
309+ renderAlias relation <> "." <> renderAlias column
287− ( Has tab (Join outer from) row
289− , GroupedBy tab col bys
291− ) => IsQualified tab col
292− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
293− tab ! col = tab ! col :* Nil
295− ( Has tab (Join outer from) row
311+ ( Has relation relations columns
296− , Has col row ty
312+ , Has column columns ty
297− , GroupedBy tab col bys
313+ , GroupedBy relation column bys
298− , column ~ (col ::: ty)
299− ) => IsQualified tab col
314+ ) => IsQualified relation column
300− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
315+ (Aliased (Expression schema relations ('Grouped bys) params)
301− tab ! col = tab ! col `As` col
316+ (column ::: ty)) where
317+ relation ! column = relation ! column `As` column
303− ( Has tab (Join outer from) row
319+ ( Has relation relations columns
304− , Has col row ty
320+ , Has column columns ty
305− , GroupedBy tab col bys
321+ , GroupedBy relation column bys
306− , columns ~ '[col ::: ty]
307− ) => IsQualified tab col
322+ ) => IsQualified relation column
308− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
323+ ( NP (Aliased (Expression schema relations ('Grouped bys) params))
309− tab ! col = tab ! col :* Nil
324+ '[column ::: ty]) where
325+ relation ! column = relation ! column :* Nil
327+-- | analagous to `Nothing`
329+-- >>> printSQL null_
331+null_ :: Expression schema rels grouping params ('Null ty)
332+null_ = UnsafeExpression "NULL"
334+-- | analagous to `Just`
336+-- >>> printSQL $ notNull true
339+ :: Expression schema rels grouping params ('NotNull ty)
340+ -> Expression schema rels grouping params ('Null ty)
341+notNull = UnsafeExpression . renderExpression
343+-- | return the leftmost value which is not NULL
345+-- >>> printSQL $ coalesce [null_, notNull true] false
346+-- COALESCE(NULL, TRUE, FALSE)
348+ :: [Expression schema relations grouping params ('Null ty)]
349+ -- ^ @NULL@s may be present
350+ -> Expression schema relations grouping params ('NotNull ty)
351+ -- ^ @NULL@ is absent
352+ -> Expression schema relations grouping params ('NotNull ty)
353+coalesce nullxs notNullx = UnsafeExpression $
354+ "COALESCE" <> parenthesized (commaSeparated
355+ ((renderExpression <$> nullxs) <> [renderExpression notNullx]))
357+-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
359+-- >>> printSQL $ fromNull true null_
360+-- COALESCE(NULL, TRUE)
362+ :: Expression schema relations grouping params ('NotNull ty)
363+ -- ^ what to convert @NULL@ to
364+ -> Expression schema relations grouping params ('Null ty)
365+ -> Expression schema relations grouping params ('NotNull ty)
366+fromNull notNullx nullx = coalesce [nullx] notNullx
368+-- | >>> printSQL $ null_ & isNull
371+ :: Expression schema relations grouping params ('Null ty)
372+ -- ^ possibly @NULL@
373+ -> Condition schema relations grouping params
374+isNull x = UnsafeExpression $ renderExpression x <+> "IS NULL"
376+-- | >>> printSQL $ null_ & isNotNull
379+ :: Expression schema relations grouping params ('Null ty)
380+ -- ^ possibly @NULL@
381+ -> Condition schema relations grouping params
382+isNotNull x = UnsafeExpression $ renderExpression x <+> "IS NOT NULL"
384+-- | analagous to `maybe` using @IS NULL@
386+-- >>> printSQL $ matchNull true not_ null_
387+-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
389+ :: Expression schema relations grouping params (nullty)
390+ -- ^ what to convert @NULL@ to
391+ -> ( Expression schema relations grouping params ('NotNull ty)
392+ -> Expression schema relations grouping params (nullty) )
393+ -- ^ function to perform when @NULL@ is absent
394+ -> Expression schema relations grouping params ('Null ty)
395+ -> Expression schema relations grouping params (nullty)
396+matchNull y f x = ifThenElse (isNull x) y
397+ (f (UnsafeExpression (renderExpression x)))
399+{-| right inverse to `fromNull`, if its arguments are equal then
400+`nullIf` gives @NULL@.
402+>>> :set -XTypeApplications -XDataKinds
403+>>> let expr = nullIf false (param @1) :: Expression schema rels grp '[ 'NotNull 'PGbool] ('Null 'PGbool)
405+NULL IF (FALSE, ($1 :: bool))
408+ :: Expression schema relations grouping params ('NotNull ty)
409+ -- ^ @NULL@ is absent
410+ -> Expression schema relations grouping params ('NotNull ty)
411+ -- ^ @NULL@ is absent
412+ -> Expression schema relations grouping params ('Null ty)
413+nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
414+ (renderExpression x <> ", " <> renderExpression y)
416+-- | >>> printSQL $ array [null_, notNull false, notNull true]
417+-- ARRAY[NULL, FALSE, TRUE]
419+ :: [Expression schema relations grouping params ('Null ty)]
421+ -> Expression schema relations grouping params (nullity ('PGvararray ty))
422+array xs = UnsafeExpression $
423+ "ARRAY[" <> commaSeparated (renderExpression <$> xs) <> "]"
311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
425instance (KnownSymbol label, label `In` labels) => IsPGlabel label
312− (Expression outer commons grp schemas params from (null ('PGenum labels))) where
426+ (Expression schema relations grouping params (nullity ('PGenum labels))) where
313− label = UnsafeExpression $ renderSQL (PGlabel @label)
427+ label = UnsafeExpression $ renderLabel (PGlabel @label)
429+-- | A row constructor is an expression that builds a row value
430+-- (also called a composite value) using values for its member fields.
432+-- >>> type Complex = PGcomposite '["real" ::: 'PGfloat8, "imaginary" ::: 'PGfloat8]
433+-- >>> let i = row (0 `As` #real :* 1 `As` #imaginary :* Nil) :: Expression '[] '[] 'Ungrouped '[] ('NotNull Complex)
437+ :: SListI (Nulls fields)
438+ => NP (Aliased (Expression schema relations grouping params)) (Nulls fields)
439+ -- ^ zero or more expressions for the row field values
440+ -> Expression schema relations grouping params (nullity ('PGcomposite fields))
441+row exprs = UnsafeExpression $ "ROW" <> parenthesized
442+ (renderCommaSeparated (\ (expr `As` _) -> renderExpression expr) exprs)
444+instance Has field fields ty => IsLabel field
445+ ( Expression schema relation grouping params (nullity ('PGcomposite fields))
446+ -> Expression schema relation grouping params ('Null ty) ) where
447+ fromLabel expr = UnsafeExpression $
448+ parenthesized (renderExpression expr) <> "." <>
449+ fromString (symbolVal (Proxy @field))
452+ (Expression schema relations grouping params (nullity ('PGvararray ty))) where
453+ (<>) = unsafeBinaryOp "||"
456+ (Expression schema relations grouping params (nullity ('PGvararray ty))) where
460+-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression sch rels grp '[ 'NotNull 'PGtimestamptz] ('NotNull 'PGtimestamptz)
462+-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
464+ :: Expression schema relations grouping params (nullty)
465+ -- ^ needs at least 1 argument
466+ -> [Expression schema relations grouping params (nullty)]
468+ -> Expression schema relations grouping params (nullty)
469+greatest x xs = UnsafeExpression $ "GREATEST("
470+ <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
472+-- | >>> printSQL $ least currentTimestamp [null_]
473+-- LEAST(CURRENT_TIMESTAMP, NULL)
475+ :: Expression schema relations grouping params (nullty)
476+ -- ^ needs at least 1 argument
477+ -> [Expression schema relations grouping params (nullty)]
479+ -> Expression schema relations grouping params (nullty)
480+least x xs = UnsafeExpression $ "LEAST("
481+ <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
483-- | >>> printSQL $ unsafeBinaryOp "OR" true false
316-- (TRUE OR FALSE)
484-- (TRUE OR FALSE)
317−unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
485+unsafeBinaryOp
488+ -> Expression schema relations grouping params (ty0)
489+ -> Expression schema relations grouping params (ty1)
490+ -> Expression schema relations grouping params (ty2)
318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
491unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
319− renderSQL x <+> op <+> renderSQL y
492+ renderExpression x <+> op <+> renderExpression y
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
328−-- | >>> printSQL $ unsafeLeftOp "NOT" true
494+-- | >>> printSQL $ unsafeUnaryOp "NOT" true
329-- (NOT TRUE)
495-- (NOT TRUE)
330−unsafeLeftOp :: ByteString -> x --> y
497+ :: ByteString
331−unsafeLeftOp op x = UnsafeExpression $ parenthesized $ op <+> renderSQL x
498+ -- ^ operator
332−
499+ -> Expression schema relations grouping params (ty0)
333−leftOp
500+ -> Expression schema relations grouping params (ty1)
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
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
501+unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
344−
502+ op <+> renderExpression x
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
352-- | >>> printSQL $ unsafeFunction "f" true
504-- | >>> printSQL $ unsafeFunction "f" true
353-- f(TRUE)
505-- f(TRUE)
354−unsafeFunction :: ByteString -> x --> y
506+unsafeFunction
509+ -> Expression schema relations grouping params (xty)
510+ -> Expression schema relations grouping params (yty)
355unsafeFunction fun x = UnsafeExpression $
511unsafeFunction fun x = UnsafeExpression $
356− fun <> parenthesized (renderSQL x)
512+ fun <> parenthesized (renderExpression x)
358−function
514+unsafeVariadicFunction
359− :: (Has sch schemas schema, Has fun schema ('Function ('[x] :=> 'Returns y)))
515+ :: SListI elems
360− => QualifiedAlias sch fun
361− -> FunctionDB schemas x y
362−function = unsafeFunction . renderSQL
364−-- | >>> printSQL $ unsafeFunctionN "f" (currentTime :* localTimestamp :* false *: literal 'a')
365−-- f(CURRENT_TIME, LOCALTIMESTAMP, FALSE, E'a')
366−unsafeFunctionN :: SListI xs => ByteString -> xs ---> y
516+ => ByteString
518+ -> NP (Expression schema relations grouping params) elems
519+ -> Expression schema relations grouping params ret
367−unsafeFunctionN fun xs = UnsafeExpression $
520+unsafeVariadicFunction fun x = UnsafeExpression $
368− fun <> parenthesized (renderCommaSeparated renderSQL xs)
521+ fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderExpression) x)))
371− :: ( Has sch schemas schema
372− , Has fun schema ('Function (xs :=> 'Returns y))
374− => QualifiedAlias sch fun
375− -> FunctionNDB schemas xs y
376−functionN = unsafeFunctionN . renderSQL
378−instance ty `In` PGNum
523+instance PGNum ty
379− => Num (Expression outer commons grp schemas params from (null ty)) where
524+ => Num (Expression schema relations grouping params (nullity ty)) where
380 (+) = unsafeBinaryOp "+"
525 (+) = unsafeBinaryOp "+"
381 (-) = unsafeBinaryOp "-"
526 (-) = unsafeBinaryOp "-"
382 (*) = unsafeBinaryOp "*"
527 (*) = unsafeBinaryOp "*"
@@ -387,24 +532,19 @@ instance ty `In` PGNum
387 . fromString
532 . fromString
390−instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
535+instance (PGNum ty, PGFloating ty) => Fractional
391− (Expression outer commons grp schemas params from (null ty)) where
536+ (Expression schema relations grouping params (nullity ty)) where
392 (/) = unsafeBinaryOp "/"
537 (/) = unsafeBinaryOp "/"
393− fromRational
538+ fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
397− . showFFloat Nothing
400−instance (ty `In` PGNum, ty `In` PGFloating) => Floating
540+instance (PGNum ty, PGFloating ty) => Floating
401− (Expression outer commons grp schemas params from (null ty)) where
541+ (Expression schema relations grouping params (nullity ty)) where
402 pi = UnsafeExpression "pi()"
542 pi = UnsafeExpression "pi()"
403 exp = unsafeFunction "exp"
543 exp = unsafeFunction "exp"
404 log = unsafeFunction "ln"
544 log = unsafeFunction "ln"
405 sqrt = unsafeFunction "sqrt"
545 sqrt = unsafeFunction "sqrt"
406 b ** x = UnsafeExpression $
546 b ** x = UnsafeExpression $
407− "power(" <> renderSQL b <> ", " <> renderSQL x <> ")"
547+ "power(" <> renderExpression b <> ", " <> renderExpression x <> ")"
408 logBase b y = log y / log b
548 logBase b y = log y / log b
409 sin = unsafeFunction "sin"
549 sin = unsafeFunction "sin"
410 cos = unsafeFunction "cos"
550 cos = unsafeFunction "cos"
@@ -419,54 +559,1032 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
419 acosh x = log (x + sqrt (x*x - 1))
559 acosh x = log (x + sqrt (x*x - 1))
420 atanh x = log ((1 + x) / (1 - x)) / 2
560 atanh x = log ((1 + x) / (1 - x)) / 2
422−-- | Contained by operators
562+-- | >>> :{
423−class PGSubset ty where
563+-- let
424− (@>) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
564+-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
425− (@>) = unsafeBinaryOp "@>"
565+-- expression = atan2_ pi 2
426− (<@) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
566+-- in printSQL expression
427− (<@) = unsafeBinaryOp "<@"
567+-- :}
428−instance PGSubset 'PGjsonb
568+-- atan2(pi(), 2)
429−instance PGSubset 'PGtsquery
569+atan2_
430−instance PGSubset ('PGvararray ty)
570+ :: PGFloating float
431−instance PGSubset ('PGrange ty)
571+ => Expression schema relations grouping params (nullity float)
433−class PGIntersect ty where
573+ -> Expression schema relations grouping params (nullity float)
434− (@&&) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
574+ -- ^ denominator
435− (@&&) = unsafeBinaryOp "&&"
575+ -> Expression schema relations grouping params (nullity float)
436−instance PGIntersect ('PGvararray ty)
576+atan2_ y x = UnsafeExpression $
437−instance PGIntersect ('PGrange ty)
577+ "atan2(" <> renderExpression y <> ", " <> renderExpression x <> ")"
579+-- When a `cast` is applied to an `Expression` of a known type, it
580+-- represents a run-time type conversion. The cast will succeed only if a
581+-- suitable type conversion operation has been defined.
583+-- | >>> printSQL $ true & cast int4
586+ :: TypeExpression schema ty1
587+ -- ^ type to cast as
588+ -> Expression schema relations grouping params (nullity ty0)
589+ -- ^ value to convert
590+ -> Expression schema relations grouping params (nullity ty1)
591+cast ty x = UnsafeExpression $ parenthesized $
592+ renderExpression x <+> "::" <+> renderTypeExpression ty
594+-- | integer division, truncates the result
598+-- expression :: Expression schema relations grouping params (nullity 'PGint2)
599+-- expression = 5 `quot_` 2
600+-- in printSQL expression
605+ => Expression schema relations grouping params (nullity int)
607+ -> Expression schema relations grouping params (nullity int)
609+ -> Expression schema relations grouping params (nullity int)
610+quot_ = unsafeBinaryOp "/"
612+-- | remainder upon integer division
616+-- expression :: Expression schema relations grouping params (nullity 'PGint2)
617+-- expression = 5 `rem_` 2
618+-- in printSQL expression
623+ => Expression schema relations grouping params (nullity int)
625+ -> Expression schema relations grouping params (nullity int)
627+ -> Expression schema relations grouping params (nullity int)
628+rem_ = unsafeBinaryOp "%"
632+-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
633+-- expression = trunc pi
634+-- in printSQL expression
639+ => Expression schema relations grouping params (nullity frac)
640+ -- ^ fractional number
641+ -> Expression schema relations grouping params (nullity frac)
642+trunc = unsafeFunction "trunc"
646+-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
647+-- expression = round_ pi
648+-- in printSQL expression
653+ => Expression schema relations grouping params (nullity frac)
654+ -- ^ fractional number
655+ -> Expression schema relations grouping params (nullity frac)
656+round_ = unsafeFunction "round"
660+-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
661+-- expression = ceiling_ pi
662+-- in printSQL expression
667+ => Expression schema relations grouping params (nullity frac)
668+ -- ^ fractional number
669+ -> Expression schema relations grouping params (nullity frac)
670+ceiling_ = unsafeFunction "ceiling"
672+-- | A `Condition` is a boolean valued `Expression`. While SQL allows
673+-- conditions to have @NULL@, Squeal instead chooses to disallow @NULL@,
674+-- forcing one to handle the case of @NULL@ explicitly to produce
676+type Condition schema relations grouping params =
677+ Expression schema relations grouping params ('NotNull 'PGbool)
679+-- | >>> printSQL true
681+true :: Condition schema relations grouping params
682+true = UnsafeExpression "TRUE"
684+-- | >>> printSQL false
686+false :: Condition schema relations grouping params
687+false = UnsafeExpression "FALSE"
689+-- | >>> printSQL $ not_ true
692+ :: Condition schema relations grouping params
693+ -> Condition schema relations grouping params
694+not_ = unsafeUnaryOp "NOT"
696+-- | >>> printSQL $ true .&& false
699+ :: Condition schema relations grouping params
700+ -> Condition schema relations grouping params
701+ -> Condition schema relations grouping params
702+(.&&) = unsafeBinaryOp "AND"
704+-- | >>> printSQL $ true .|| false
707+ :: Condition schema relations grouping params
708+ -> Condition schema relations grouping params
709+ -> Condition schema relations grouping params
710+(.||) = unsafeBinaryOp "OR"
714+-- expression :: Expression schema relations grouping params (nullity 'PGint2)
715+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
716+-- in printSQL expression
718+-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
720+ :: [ ( Condition schema relations grouping params
721+ , Expression schema relations grouping params (ty)
723+ -- ^ whens and thens
724+ -> Expression schema relations grouping params (ty)
726+ -> Expression schema relations grouping params (ty)
727+caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
731+ [ " WHEN ", renderExpression when_
732+ , " THEN ", renderExpression then_
734+ | (when_,then_) <- whenThens
736+ , " ELSE ", renderExpression else_
742+-- expression :: Expression schema relations grouping params (nullity 'PGint2)
743+-- expression = ifThenElse true 1 0
744+-- in printSQL expression
746+-- CASE WHEN TRUE THEN 1 ELSE 0 END
748+ :: Condition schema relations grouping params
749+ -> Expression schema relations grouping params (ty) -- ^ then
750+ -> Expression schema relations grouping params (ty) -- ^ else
751+ -> Expression schema relations grouping params (ty)
752+ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
754+-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
755+-- will produce @NULL@s if one of their arguments is @NULL@.
757+-- >>> printSQL $ notNull true .== null_
760+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
761+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
762+ -> Expression schema relations grouping params (nullity 'PGbool)
763+(.==) = unsafeBinaryOp "="
766+-- | >>> printSQL $ notNull true ./= null_
769+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
770+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
771+ -> Expression schema relations grouping params (nullity 'PGbool)
772+(./=) = unsafeBinaryOp "<>"
775+-- | >>> printSQL $ notNull true .>= null_
778+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
779+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
780+ -> Expression schema relations grouping params (nullity 'PGbool)
781+(.>=) = unsafeBinaryOp ">="
784+-- | >>> printSQL $ notNull true .< null_
787+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
788+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
789+ -> Expression schema relations grouping params (nullity 'PGbool)
790+(.<) = unsafeBinaryOp "<"
793+-- | >>> printSQL $ notNull true .<= null_
796+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
797+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
798+ -> Expression schema relations grouping params (nullity 'PGbool)
799+(.<=) = unsafeBinaryOp "<="
802+-- | >>> printSQL $ notNull true .> null_
805+ :: Expression schema relations grouping params (nullity ty) -- ^ lhs
806+ -> Expression schema relations grouping params (nullity ty) -- ^ rhs
807+ -> Expression schema relations grouping params (nullity 'PGbool)
808+(.>) = unsafeBinaryOp ">"
811+-- | >>> printSQL currentDate
814+ :: Expression schema relations grouping params (nullity 'PGdate)
815+currentDate = UnsafeExpression "CURRENT_DATE"
817+-- | >>> printSQL currentTime
820+ :: Expression schema relations grouping params (nullity 'PGtimetz)
821+currentTime = UnsafeExpression "CURRENT_TIME"
823+-- | >>> printSQL currentTimestamp
826+ :: Expression schema relations grouping params (nullity 'PGtimestamptz)
827+currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
829+-- | >>> printSQL localTime
832+ :: Expression schema relations grouping params (nullity 'PGtime)
833+localTime = UnsafeExpression "LOCALTIME"
835+-- | >>> printSQL localTimestamp
838+ :: Expression schema relations grouping params (nullity 'PGtimestamp)
839+localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
841+{-----------------------------------------
843+-----------------------------------------}
439instance IsString
845instance IsString
440− (Expression outer commons grp schemas params from (null 'PGtext)) where
846+ (Expression schema relations grouping params (nullity 'PGtext)) where
441 fromString str = UnsafeExpression $
847 fromString str = UnsafeExpression $
442 "E\'" <> fromString (escape =<< str) <> "\'"
848 "E\'" <> fromString (escape =<< str) <> "\'"
443−instance IsString
849+ where
444− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
850+ escape = \case
445− fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
851+ '\NUL' -> "\\0"
446− "E\'" <> fromString (escape =<< str) <> "\'"
852+ '\'' -> "''"
447−instance IsString
853+ '"' -> "\\\""
448− (Expression outer commons grp schemas params from (null 'PGtsquery)) where
854+ '\b' -> "\\b"
449− fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
855+ '\n' -> "\\n"
450− "E\'" <> fromString (escape =<< str) <> "\'"
856+ '\r' -> "\\r"
452instance Semigroup
861instance Semigroup
453− (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
862+ (Expression schema relations grouping params (nullity 'PGtext)) where
454− (<>) = unsafeBinaryOp "||"
456− (Expression outer commons grp schemas params from (null 'PGjsonb)) where
457− (<>) = unsafeBinaryOp "||"
459− (Expression outer commons grp schemas params from (null 'PGtext)) where
460− (<>) = unsafeBinaryOp "||"
462− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
463 (<>) = unsafeBinaryOp "||"
863 (<>) = unsafeBinaryOp "||"
465instance Monoid
865instance Monoid
466− (Expression outer commons grp schemas params from (null 'PGtext)) where
866+ (Expression schema relations grouping params (nullity 'PGtext)) where
467− mempty = fromString ""
470− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
471 mempty = fromString ""
867 mempty = fromString ""
472 mappend = (<>)
868 mappend = (<>)
870+-- | >>> printSQL $ lower "ARRRGGG"
873+ :: Expression schema relations grouping params (nullity 'PGtext)
874+ -- ^ string to lower case
875+ -> Expression schema relations grouping params (nullity 'PGtext)
876+lower = unsafeFunction "lower"
878+-- | >>> printSQL $ upper "eeee"
881+ :: Expression schema relations grouping params (nullity 'PGtext)
882+ -- ^ string to upper case
883+ -> Expression schema relations grouping params (nullity 'PGtext)
884+upper = unsafeFunction "upper"
886+-- | >>> printSQL $ charLength "four"
887+-- char_length(E'four')
889+ :: Expression schema relations grouping params (nullity 'PGtext)
890+ -- ^ string to measure
891+ -> Expression schema relations grouping params (nullity 'PGint4)
892+charLength = unsafeFunction "char_length"
894+-- | The `like` expression returns true if the @string@ matches
895+-- the supplied @pattern@. If @pattern@ does not contain percent signs
896+-- or underscores, then the pattern only represents the string itself;
897+-- in that case `like` acts like the equals operator. An underscore (_)
898+-- in pattern stands for (matches) any single character; a percent sign (%)
899+-- matches any sequence of zero or more characters.
901+-- >>> printSQL $ "abc" `like` "a%"
902+-- (E'abc' LIKE E'a%')
904+ :: Expression schema relations grouping params (nullity 'PGtext)
906+ -> Expression schema relations grouping params (nullity 'PGtext)
908+ -> Expression schema relations grouping params (nullity 'PGbool)
909+like = unsafeBinaryOp "LIKE"
911+{-----------------------------------------
912+ -- json and jsonb support
914+See https://www.postgresql.org/docs/10/static/functions-json.html -- most
915+comments lifted directly from this page.
917+Table 9.44: json and jsonb operators
918+-----------------------------------------}
920+type PGjsonKey key = key `In` '[ 'PGint2, 'PGint4, 'PGtext ]
922+type PGjson_ json = json `In` '[ 'PGjson, 'PGjsonb ]
924+type Placeholder k = 'Text "(_::" :<>: 'ShowType k :<>: 'Text ")"
925+type ErrArrayOf arr ty = arr :<>: 'Text " " :<>: ty
926+type ErrPGfixarrayOf t = ErrArrayOf ('ShowType 'PGfixarray :<>: 'Text " " :<>: Placeholder Nat) t
927+type ErrPGvararrayOf t = ErrArrayOf ('ShowType 'PGvararray) t
929+type family PGarray name arr :: Constraint where
930+ PGarray name ('PGvararray x) = ()
931+ PGarray name ('PGfixarray n x) = ()
932+ PGarray name val = TypeError
933+ ('Text name :<>: 'Text ": Unsatisfied PGarrayOf constraint. Expected either: "
934+ :$$: 'Text " • " :<>: ErrPGvararrayOf (Placeholder PGType)
935+ :$$: 'Text " • " :<>: ErrPGfixarrayOf (Placeholder PGType)
936+ :$$: 'Text "But got: " :<>: 'ShowType val)
938+type family PGarrayOf name arr ty :: Constraint where
939+ PGarrayOf name ('PGvararray x) ty = x ~ ty
940+ PGarrayOf name ('PGfixarray n x) ty = x ~ ty
941+ PGarrayOf name val ty = TypeError
942+ ( 'Text name :<>: 'Text "Unsatisfied PGarrayOf constraint. Expected either: "
943+ :$$: 'Text " • " :<>: ErrPGvararrayOf ( 'ShowType ty )
944+ :$$: 'Text " • " :<>: ErrPGfixarrayOf ( 'ShowType ty )
945+ :$$: 'Text "But got: " :<>: 'ShowType val)
947+type IsPGtextArray name arr = PGarrayOf name arr 'PGtext
949+-- | Get JSON value (object field or array element) at a key.
951+ :: (PGjson_ json, PGjsonKey key)
952+ => Expression schema relations grouping params (nullity json)
953+ -> Expression schema relations grouping params (nullity key)
954+ -> Expression schema relations grouping params ('Null json)
955+(.->) = unsafeBinaryOp "->"
957+-- | Get JSON value (object field or array element) at a key, as text.
959+ :: (PGjson_ json, PGjsonKey key)
960+ => Expression schema relations grouping params (nullity json)
961+ -> Expression schema relations grouping params (nullity key)
962+ -> Expression schema relations grouping params ('Null 'PGtext)
963+(.->>) = unsafeBinaryOp "->>"
965+-- | Get JSON value at a specified path.
967+ :: (PGjson_ json, IsPGtextArray "(.#>)" path)
968+ => Expression schema relations grouping params (nullity json)
969+ -> Expression schema relations grouping params (nullity path)
970+ -> Expression schema relations grouping params ('Null json)
971+(.#>) = unsafeBinaryOp "#>"
973+-- | Get JSON value at a specified path as text.
975+ :: (PGjson_ json, IsPGtextArray "(.#>>)" path)
976+ => Expression schema relations grouping params (nullity json)
977+ -> Expression schema relations grouping params (nullity path)
978+ -> Expression schema relations grouping params ('Null 'PGtext)
979+(.#>>) = unsafeBinaryOp "#>>"
981+-- Additional jsonb operators
983+-- | Does the left JSON value contain the right JSON path/value entries at the
986+ :: Expression schema relations grouping params (nullity 'PGjsonb)
987+ -> Expression schema relations grouping params (nullity 'PGjsonb)
988+ -> Expression schema relations grouping params ('NotNull 'PGbool)
989+(.@>) = unsafeBinaryOp "@>"
991+-- | Are the left JSON path/value entries contained at the top level within the
994+ :: Expression schema relations grouping params (nullity 'PGjsonb)
995+ -> Expression schema relations grouping params (nullity 'PGjsonb)
996+ -> Expression schema relations grouping params ('NotNull 'PGbool)
997+(.<@) = unsafeBinaryOp "<@"
999+-- | Does the string exist as a top-level key within the JSON value?
1001+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1002+ -> Expression schema relations grouping params (nullity 'PGtext)
1003+ -> Expression schema relations grouping params ('NotNull 'PGbool)
1004+(.?) = unsafeBinaryOp "?"
1006+-- | Do any of these array strings exist as top-level keys?
1008+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1009+ -> Expression schema relations grouping params (nullity ('PGvararray 'PGtext))
1010+ -> Expression schema relations grouping params ('NotNull 'PGbool)
1011+(.?|) = unsafeBinaryOp "?|"
1013+-- | Do all of these array strings exist as top-level keys?
1015+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1016+ -> Expression schema relations grouping params (nullity ('PGvararray 'PGtext))
1017+ -> Expression schema relations grouping params ('NotNull 'PGbool)
1018+(.?&) = unsafeBinaryOp "?&"
1020+-- | Concatenate two jsonb values into a new jsonb value.
1022+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1023+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1024+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1025+(.||.) = unsafeBinaryOp "||"
1027+-- | Delete a key or keys from a JSON object, or remove an array element.
1029+-- If the right operand is..
1031+-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1032+-- are matched based on their key value.
1034+-- @ text[] @: Delete multiple key/value pairs or string elements
1035+-- from left operand. Key/value pairs are matched based on their key value.
1037+-- @ integer @: Delete the array element with specified index (Negative integers
1038+-- count from the end). Throws an error if top level container is not an array.
1040+ :: (key `In` '[ 'PGtext, 'PGvararray 'PGtext, 'PGint4, 'PGint2 ]) -- hlint error without parens here
1041+ => Expression schema relations grouping params (nullity 'PGjsonb)
1042+ -> Expression schema relations grouping params (nullity key)
1043+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1044+(.-.) = unsafeBinaryOp "-"
1046+-- | Delete the field or element with specified path (for JSON arrays, negative
1047+-- integers count from the end)
1049+ :: IsPGtextArray "(#-.)" arrayty
1050+ => Expression schema relations grouping params (nullity 'PGjsonb)
1051+ -> Expression schema relations grouping params (nullity arrayty)
1052+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1053+(#-.) = unsafeBinaryOp "#-"
1055+{-----------------------------------------
1056+Table 9.45: JSON creation functions
1057+-----------------------------------------}
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.
1066+ :: Expression schema relations grouping params (nullity ty)
1067+ -> Expression schema relations grouping params (nullity 'PGjson)
1068+toJson = unsafeFunction "to_json"
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.
1077+ :: Expression schema relations grouping params (nullity ty)
1078+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1079+toJsonb = unsafeUnaryOp "to_jsonb"
1081+-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1082+-- becomes a JSON array of arrays. Line feeds will be added between dimension-1
1083+-- elements if pretty_bool is true.
1085+ :: PGarray "arrayToJson" arr
1086+ => Expression schema relations grouping params (nullity arr)
1087+ -> Expression schema relations grouping params (nullity 'PGjson)
1088+arrayToJson = unsafeFunction "array_to_json"
1090+-- | Returns the row as a JSON object. Line feeds will be added between level-1
1091+-- elements if pretty_bool is true.
1093+ :: Expression schema relations grouping params (nullity ('PGcomposite ty))
1094+ -> Expression schema relations grouping params (nullity 'PGjson)
1095+rowToJson = unsafeFunction "row_to_json"
1097+-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1101+ => NP (Expression schema relations grouping params) elems
1102+ -> Expression schema relations grouping params (nullity 'PGjson)
1103+jsonBuildArray = unsafeVariadicFunction "json_build_array"
1105+-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1106+-- variadic argument list.
1109+ => NP (Expression schema relations grouping params) elems
1110+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1111+jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1113+type family PGobjectpairs name x :: Constraint where
1114+ PGobjectpairs name ('NotNull 'PGtext : nullity arg : xs) = PGobjectpairs name xs
1115+ PGobjectpairs name '[] = ()
1116+ PGobjectpairs name (x:xs) = TypeError
1117+ ( 'Text name :<>: 'Text ": Incorrect argument list:"
1118+ :$$: 'Text "Expected alternating list of keys and values."
1119+ :$$: 'Text "But got " :<>: 'ShowType (x:xs))
1121+-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1122+-- argument list. The elements of the argument list must alternate between text
1125+ :: (PGobjectpairs "jsonBuildObject" elems, SListI elems)
1126+ => NP (Expression schema relations grouping params) elems
1127+ -> Expression schema relations grouping params (nullity 'PGjson)
1128+jsonBuildObject = unsafeVariadicFunction "json_build_object"
1130+-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1131+-- variadic argument list. The elements of the argument list must alternate
1132+-- between text and values.
1134+ :: (PGobjectpairs "jsonbBuildObject" elems, SListI elems)
1135+ => NP (Expression schema relations grouping params) elems
1136+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1137+jsonbBuildObject = unsafeVariadicFunction "jsonb_build_object"
1139+-- | Builds a JSON object out of a text array. The array must have either
1140+-- exactly one dimension with an even number of members, in which case they are
1141+-- taken as alternating key/value pairs, or two dimensions such that each inner
1142+-- array has exactly two elements, which are taken as a key/value pair.
1144+ :: PGarrayOf "jsonObject" arr 'PGtext
1145+ => Expression schema relations grouping params (nullity arr)
1146+ -> Expression schema relations grouping params (nullity 'PGjson)
1147+jsonObject = unsafeFunction "json_object"
1149+-- | Builds a binary JSON object out of a text array. The array must have either
1150+-- exactly one dimension with an even number of members, in which case they are
1151+-- taken as alternating key/value pairs, or two dimensions such that each inner
1152+-- array has exactly two elements, which are taken as a key/value pair.
1154+ :: PGarrayOf "jsonbObject" arr 'PGtext
1155+ => Expression schema relations grouping params (nullity arr)
1156+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1157+jsonbObject = unsafeFunction "jsonb_object"
1159+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1160+-- keys and one for values, that are zipped pairwise to create a JSON object.
1162+ :: ( PGarrayOf "jsonZipObject" keysArray 'PGtext
1163+ , PGarrayOf "jsonZipObject" valuesArray 'PGtext)
1164+ => Expression schema relations grouping params (nullity keysArray)
1165+ -> Expression schema relations grouping params (nullity valuesArray)
1166+ -> Expression schema relations grouping params (nullity 'PGjson)
1167+jsonZipObject ks vs =
1168+ unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1170+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1171+-- keys and one for values, that are zipped pairwise to create a binary JSON
1174+ :: ( PGarrayOf "jsonbZipObject" keysArray 'PGtext
1175+ , PGarrayOf "jsonbZipObject" valuesArray 'PGtext)
1176+ => Expression schema relations grouping params (nullity keysArray)
1177+ -> Expression schema relations grouping params (nullity valuesArray)
1178+ -> Expression schema relations grouping params (nullity 'PGjsonb)
1179+jsonbZipObject ks vs =
1180+ unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1182+{-----------------------------------------
1183+Table 9.46: JSON processing functions
1184+-----------------------------------------}
1186+-- | Returns the number of elements in the outermost JSON array.
1188+ :: Expression schema relations grouping params (nullity 'PGjson)
1189+ -> Expression schema relations grouping params (nullity 'PGint4)
1190+jsonArrayLength = unsafeFunction "json_array_length"
1192+-- | Returns the number of elements in the outermost binary JSON array.
1194+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1195+ -> Expression schema relations grouping params (nullity 'PGint4)
1196+jsonbArrayLength = unsafeFunction "jsonb_array_length"
1199+ :: Expression schema relations grouping params (nullity 'PGjson)
1200+ -> Expression schema relations grouping params (nullity 'PGtext)
1201+jsonObjectKeys = unsafeFunction "json_object_keys"
1204+ :: Expression schema relations grouping params (nullity 'PGjsonb)
1205+ -> Expression schema relations grouping params (nullity 'PGtext)
1206+jsonbObjectKeys = unsafeFunction "jsonb_object_keys"
1208+{-----------------------------------------
1210+-----------------------------------------}
1212+-- | escape hatch to define aggregate functions
1214+ :: ByteString -- ^ aggregate function
1215+ -> Expression schema relations 'Ungrouped params (xty)
1216+ -> Expression schema relations ('Grouped bys) params (yty)
1217+unsafeAggregate fun x = UnsafeExpression $ mconcat
1218+ [fun, "(", renderExpression x, ")"]
1220+-- | escape hatch to define aggregate functions over distinct values
1221+unsafeAggregateDistinct
1222+ :: ByteString -- ^ aggregate function
1223+ -> Expression schema relations 'Ungrouped params (xty)
1224+ -> Expression schema relations ('Grouped bys) params (yty)
1225+unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
1226+ [fun, "(DISTINCT ", renderExpression x, ")"]
1230+-- expression :: Expression schema '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Grouped bys) params ('Null 'PGnumeric)
1231+-- expression = sum_ #col
1232+-- in printSQL expression
1237+ => Expression schema relations 'Ungrouped params (nullity ty)
1239+ -> Expression schema relations ('Grouped bys) params (nullity ty)
1240+sum_ = unsafeAggregate "sum"
1244+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGnumeric]] ('Grouped bys) params (nullity 'PGnumeric)
1245+-- expression = sumDistinct #col
1246+-- in printSQL expression
1248+-- sum(DISTINCT "col")
1251+ => Expression schema relations 'Ungrouped params (nullity ty)
1253+ -> Expression schema relations ('Grouped bys) params (nullity ty)
1254+sumDistinct = unsafeAggregateDistinct "sum"
1256+-- | A constraint for `PGType`s that you can take averages of and the resulting
1258+class PGAvg ty avg | ty -> avg where
1260+ :: Expression schema relations 'Ungrouped params (nullity ty)
1261+ -- ^ what to average
1262+ -> Expression schema relations ('Grouped bys) params (nullity avg)
1263+ avg = unsafeAggregate "avg"
1264+ avgDistinct = unsafeAggregateDistinct "avg"
1265+instance PGAvg 'PGint2 'PGnumeric
1266+instance PGAvg 'PGint4 'PGnumeric
1267+instance PGAvg 'PGint8 'PGnumeric
1268+instance PGAvg 'PGnumeric 'PGnumeric
1269+instance PGAvg 'PGfloat4 'PGfloat8
1270+instance PGAvg 'PGfloat8 'PGfloat8
1271+instance PGAvg 'PGinterval 'PGinterval
1275+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1276+-- expression = bitAnd #col
1277+-- in printSQL expression
1282+ => Expression schema relations 'Ungrouped params (nullity int)
1283+ -- ^ what to aggregate
1284+ -> Expression schema relations ('Grouped bys) params (nullity int)
1285+bitAnd = unsafeAggregate "bit_and"
1289+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1290+-- expression = bitOr #col
1291+-- in printSQL expression
1296+ => Expression schema relations 'Ungrouped params (nullity int)
1297+ -- ^ what to aggregate
1298+ -> Expression schema relations ('Grouped bys) params (nullity int)
1299+bitOr = unsafeAggregate "bit_or"
1303+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1304+-- expression = bitAndDistinct #col
1305+-- in printSQL expression
1307+-- bit_and(DISTINCT "col")
1310+ => Expression schema relations 'Ungrouped params (nullity int)
1311+ -- ^ what to aggregate
1312+ -> Expression schema relations ('Grouped bys) params (nullity int)
1313+bitAndDistinct = unsafeAggregateDistinct "bit_and"
1317+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1318+-- expression = bitOrDistinct #col
1319+-- in printSQL expression
1321+-- bit_or(DISTINCT "col")
1324+ => Expression schema relations 'Ungrouped params (nullity int)
1325+ -- ^ what to aggregate
1326+ -> Expression schema relations ('Grouped bys) params (nullity int)
1327+bitOrDistinct = unsafeAggregateDistinct "bit_or"
1331+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1332+-- expression = boolAnd #col
1333+-- in printSQL expression
1337+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1338+ -- ^ what to aggregate
1339+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1340+boolAnd = unsafeAggregate "bool_and"
1344+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1345+-- expression = boolOr #col
1346+-- in printSQL expression
1350+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1351+ -- ^ what to aggregate
1352+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1353+boolOr = unsafeAggregate "bool_or"
1357+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1358+-- expression = boolAndDistinct #col
1359+-- in printSQL expression
1361+-- bool_and(DISTINCT "col")
1363+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1364+ -- ^ what to aggregate
1365+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1366+boolAndDistinct = unsafeAggregateDistinct "bool_and"
1370+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1371+-- expression = boolOrDistinct #col
1372+-- in printSQL expression
1374+-- bool_or(DISTINCT "col")
1376+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1377+ -- ^ what to aggregate
1378+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1379+boolOrDistinct = unsafeAggregateDistinct "bool_or"
1381+-- | A special aggregation that does not require an input
1383+-- >>> printSQL countStar
1386+ :: Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1387+countStar = UnsafeExpression $ "count(*)"
1391+-- expression :: Expression schema '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
1392+-- expression = count #col
1393+-- in printSQL expression
1397+ :: Expression schema relations 'Ungrouped params ty
1399+ -> Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1400+count = unsafeAggregate "count"
1404+-- expression :: Expression schema '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
1405+-- expression = countDistinct #col
1406+-- in printSQL expression
1408+-- count(DISTINCT "col")
1410+ :: Expression schema relations 'Ungrouped params ty
1412+ -> Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1413+countDistinct = unsafeAggregateDistinct "count"
1415+-- | synonym for `boolAnd`
1419+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1420+-- expression = every #col
1421+-- in printSQL expression
1425+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1426+ -- ^ what to aggregate
1427+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1428+every = unsafeAggregate "every"
1430+-- | synonym for `boolAndDistinct`
1434+-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1435+-- expression = everyDistinct #col
1436+-- in printSQL expression
1438+-- every(DISTINCT "col")
1440+ :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1441+ -- ^ what to aggregate
1442+ -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1443+everyDistinct = unsafeAggregateDistinct "every"
1445+-- | minimum and maximum aggregation
1446+max_, min_, maxDistinct, minDistinct
1447+ :: Expression schema relations 'Ungrouped params (nullity ty)
1448+ -- ^ what to aggregate
1449+ -> Expression schema relations ('Grouped bys) params (nullity ty)
1450+max_ = unsafeAggregate "max"
1451+min_ = unsafeAggregate "min"
1452+maxDistinct = unsafeAggregateDistinct "max"
1453+minDistinct = unsafeAggregateDistinct "min"
1455+{-----------------------------------------
1457+-----------------------------------------}
1459+-- | `TypeExpression`s are used in `cast`s and `createTable` commands.
1460+newtype TypeExpression (schema :: SchemaType) (ty :: PGType)
1461+ = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1462+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
1464+instance (Has alias schema ('Typedef ty))
1465+ => IsLabel alias (TypeExpression schema ty) where
1466+ fromLabel = UnsafeTypeExpression (renderAlias (fromLabel @alias))
1468+-- | logical Boolean (true/false)
1469+bool :: TypeExpression schema 'PGbool
1470+bool = UnsafeTypeExpression "bool"
1471+-- | signed two-byte integer
1472+int2, smallint :: TypeExpression schema 'PGint2
1473+int2 = UnsafeTypeExpression "int2"
1474+smallint = UnsafeTypeExpression "smallint"
1475+-- | signed four-byte integer
1476+int4, int, integer :: TypeExpression schema 'PGint4
1477+int4 = UnsafeTypeExpression "int4"
1478+int = UnsafeTypeExpression "int"
1479+integer = UnsafeTypeExpression "integer"
1480+-- | signed eight-byte integer
1481+int8, bigint :: TypeExpression schema 'PGint8
1482+int8 = UnsafeTypeExpression "int8"
1483+bigint = UnsafeTypeExpression "bigint"
1484+-- | arbitrary precision numeric type
1485+numeric :: TypeExpression schema 'PGnumeric
1486+numeric = UnsafeTypeExpression "numeric"
1487+-- | single precision floating-point number (4 bytes)
1488+float4, real :: TypeExpression schema 'PGfloat4
1489+float4 = UnsafeTypeExpression "float4"
1490+real = UnsafeTypeExpression "real"
1491+-- | double precision floating-point number (8 bytes)
1492+float8, doublePrecision :: TypeExpression schema 'PGfloat8
1493+float8 = UnsafeTypeExpression "float8"
1494+doublePrecision = UnsafeTypeExpression "double precision"
1495+-- | variable-length character string
1496+text :: TypeExpression schema 'PGtext
1497+text = UnsafeTypeExpression "text"
1498+-- | fixed-length character string
1500+ :: (KnownNat n, 1 <= n)
1502+ -> TypeExpression schema ('PGchar n)
1503+char p = UnsafeTypeExpression $ "char(" <> renderNat p <> ")"
1504+character p = UnsafeTypeExpression $ "character(" <> renderNat p <> ")"
1505+-- | variable-length character string
1506+varchar, characterVarying
1507+ :: (KnownNat n, 1 <= n)
1509+ -> TypeExpression schema ('PGvarchar n)
1510+varchar p = UnsafeTypeExpression $ "varchar(" <> renderNat p <> ")"
1511+characterVarying p = UnsafeTypeExpression $
1512+ "character varying(" <> renderNat p <> ")"
1513+-- | binary data ("byte array")
1514+bytea :: TypeExpression schema 'PGbytea
1515+bytea = UnsafeTypeExpression "bytea"
1516+-- | date and time (no time zone)
1517+timestamp :: TypeExpression schema 'PGtimestamp
1518+timestamp = UnsafeTypeExpression "timestamp"
1519+-- | date and time, including time zone
1520+timestampWithTimeZone :: TypeExpression schema 'PGtimestamptz
1521+timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1522+-- | calendar date (year, month, day)
1523+date :: TypeExpression schema 'PGdate
1524+date = UnsafeTypeExpression "date"
1525+-- | time of day (no time zone)
1526+time :: TypeExpression schema 'PGtime
1527+time = UnsafeTypeExpression "time"
1528+-- | time of day, including time zone
1529+timeWithTimeZone :: TypeExpression schema 'PGtimetz
1530+timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1532+interval :: TypeExpression schema 'PGinterval
1533+interval = UnsafeTypeExpression "interval"
1534+-- | universally unique identifier
1535+uuid :: TypeExpression schema 'PGuuid
1536+uuid = UnsafeTypeExpression "uuid"
1537+-- | IPv4 or IPv6 host address
1538+inet :: TypeExpression schema 'PGinet
1539+inet = UnsafeTypeExpression "inet"
1540+-- | textual JSON data
1541+json :: TypeExpression schema 'PGjson
1542+json = UnsafeTypeExpression "json"
1543+-- | binary JSON data, decomposed
1544+jsonb :: TypeExpression schema 'PGjsonb
1545+jsonb = UnsafeTypeExpression "jsonb"
1546+-- | variable length array
1548+ :: TypeExpression schema pg
1549+ -> TypeExpression schema ('PGvararray pg)
1550+vararray ty = UnsafeTypeExpression $ renderTypeExpression ty <> "[]"
1551+-- | fixed length array
1553+-- >>> renderTypeExpression (fixarray (Proxy @2) json)
1558+ -> TypeExpression schema pg
1559+ -> TypeExpression schema ('PGfixarray n pg)
1560+fixarray p ty = UnsafeTypeExpression $
1561+ renderTypeExpression ty <> "[" <> renderNat p <> "]"
1563+-- | `pgtype` is a demoted version of a `PGType`
1564+class PGTyped schema (ty :: PGType) where pgtype :: TypeExpression schema ty
1565+instance PGTyped schema 'PGbool where pgtype = bool
1566+instance PGTyped schema 'PGint2 where pgtype = int2
1567+instance PGTyped schema 'PGint4 where pgtype = int4
1568+instance PGTyped schema 'PGint8 where pgtype = int8
1569+instance PGTyped schema 'PGnumeric where pgtype = numeric
1570+instance PGTyped schema 'PGfloat4 where pgtype = float4
1571+instance PGTyped schema 'PGfloat8 where pgtype = float8
1572+instance PGTyped schema 'PGtext where pgtype = text
1573+instance (KnownNat n, 1 <= n)
1574+ => PGTyped schema ('PGchar n) where pgtype = char (Proxy @n)
1575+instance (KnownNat n, 1 <= n)
1576+ => PGTyped schema ('PGvarchar n) where pgtype = varchar (Proxy @n)
1577+instance PGTyped schema 'PGbytea where pgtype = bytea
1578+instance PGTyped schema 'PGtimestamp where pgtype = timestamp
1579+instance PGTyped schema 'PGtimestamptz where pgtype = timestampWithTimeZone
1580+instance PGTyped schema 'PGdate where pgtype = date
1581+instance PGTyped schema 'PGtime where pgtype = time
1582+instance PGTyped schema 'PGtimetz where pgtype = timeWithTimeZone
1583+instance PGTyped schema 'PGinterval where pgtype = interval
1584+instance PGTyped schema 'PGuuid where pgtype = uuid
1585+instance PGTyped schema 'PGjson where pgtype = json
1586+instance PGTyped schema 'PGjsonb where pgtype = jsonb
1587+instance PGTyped schema ty => PGTyped schema ('PGvararray ty) where
1588+ pgtype = vararray (pgtype @schema @ty)
1589+instance (KnownNat n, PGTyped schema ty) => PGTyped schema ('PGfixarray n ty) where
1590+ pgtype = fixarray (Proxy @n) (pgtype @schema @ty)