@@ -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,490 +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− , atan2_
54− , cast
55− , quot_
56− , rem_
57− , trunc
58− , round_
59− , ceiling_
60− , greatest
61− , least
62− -- ** Conditions
63− , Condition
64− , true
65− , false
66− , not_
67− , (.&&)
68− , (.||)
69− , caseWhenThenElse
70− , ifThenElse
71− , (.==)
72− , (./=)
73− , (.>=)
74− , (.<)
75− , (.<=)
76− , (.>)
77− -- ** Time
78− , currentDate
79− , currentTime
80− , currentTimestamp
81− , localTime
82− , localTimestamp
83− -- ** Text
84− , lower
85− , upper
86− , charLength
87− , like
88− -- ** json or jsonb operators
89− , PGarray
90− , PGarrayOf
91− , PGjsonKey
92− , PGjson_
93− , (.->)
94− , (.->>)
95− , (.#>)
96− , (.#>>)
97− -- *** jsonb only operators
98− , (.@>)
99− , (.<@)
100− , (.?)
101− , (.?|)
102− , (.?&)
103− , (.||.)
104− , (.-.)
105− , (#-.)
106− -- *** Functions
107− , toJson
108− , toJsonb
109− , arrayToJson
110− , rowToJson
111− , jsonObjectKeys
112− , jsonbObjectKeys
113− -- ** Aggregation
114− , unsafeAggregate, unsafeAggregateDistinct
115− , sum_, sumDistinct
116− , PGAvg (avg, avgDistinct)
117− , bitAnd, bitOr, boolAnd, boolOr
118− , bitAndDistinct, bitOrDistinct, boolAndDistinct, boolOrDistinct
119− , countStar
120− , count, countDistinct
121− , every, everyDistinct
122− , max_, maxDistinct, min_, minDistinct
123− -- * Types
124− , TypeExpression (UnsafeTypeExpression, renderTypeExpression)
125− , PGTyped (pgtype)
126− , bool
127− , int2
128− , smallint
129− , int4
130− , int
131− , integer
132− , int8
133− , bigint
134− , numeric
135− , float4
136− , real
137− , float8
138− , doublePrecision
139− , text
140− , char
141− , character
142− , varchar
143− , characterVarying
144− , bytea
145− , timestamp
146− , timestampWithTimeZone
147− , date
148− , time
149− , timeWithTimeZone
150− , interval
151− , uuid
152− , inet
153− , json
154− , jsonb
155− , vararray
156− , 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 (..)
15757 -- * Re-export
15858 , (&)
159− , NP ((:*), Nil)
59+ , K (..)
60+ , unK
16061 ) where
16162
16263import Control.Category
16364import Control.DeepSeq
16465import Data.ByteString (ByteString)
16566import Data.Function ((&))
166−import Data.Semigroup
167−import Data.Ratio
67+import Data.Semigroup hiding (All)
16868import Data.String
169−import Generics.SOP hiding (from)
170−import GHC.Exts (Constraint)
69+import Generics.SOP hiding (All, from)
17170import GHC.OverloadedLabels
17271import GHC.TypeLits
72+import Numeric
17373import Prelude hiding (id, (.))
17474
17575import qualified GHC.Generics as GHC
17676
77+import Squeal.PostgreSQL.Alias
78+import Squeal.PostgreSQL.List
17779import Squeal.PostgreSQL.Render
17880import Squeal.PostgreSQL.Schema
17981
82+-- $setup
83+-- >>> import Squeal.PostgreSQL
84+
18085{-----------------------------------------
18186column expressions
18287-----------------------------------------}
18388
18489{- | `Expression`s are used in a variety of contexts,
185−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,
18692as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
18793`Squeal.PostgreSQL.Manipulation.update`,
188−or in search `Condition`s in a number of commands.
94+or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
18995
19096The expression syntax allows the calculation of
19197values from primitive expression using arithmetic, logical,
19298and 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`.
193113-}
194114newtype Expression
195− (schema :: SchemaType)
196− (relations :: RelationsType)
197− (grouping :: Grouping)
115+ (outer :: FromType)
116+ (commons :: FromType)
117+ (grp :: Grouping)
118+ (schemas :: SchemasType)
198119 (params :: [NullityType])
120+ (from :: FromType)
199121 (ty :: NullityType)
200122 = UnsafeExpression { renderExpression :: ByteString }
201123 deriving (GHC.Generic,Show,Eq,Ord,NFData)
202−
203−instance RenderSQL (Expression schema relations grouping params ty) where
124+instance RenderSQL (Expression outer commons grp schemas params from ty) where
204125 renderSQL = renderExpression
205126
206−{- | A `HasParameter` constraint is used to indicate a value that is
207−supplied externally to a SQL statement.
208−`Squeal.PostgreSQL.PQ.manipulateParams`,
209−`Squeal.PostgreSQL.PQ.queryParams` and
210−`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
211−separately from the SQL command string, in which case `param`s are used to
212−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)
213181-}
214−class KnownNat n => HasParameter
215− (n :: Nat)
216− (schema :: SchemaType)
217− (params :: [NullityType])
218− (ty :: NullityType)
219− | n params -> ty where
220− -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
221− --
222− -- >>> let expr = parameter @1 int4 :: Expression sch rels grp '[ 'Null 'PGint4] ('Null 'PGint4)
223− -- >>> printSQL expr
224− -- ($1 :: int4)
225− parameter
226− :: TypeExpression schema (PGTypeOf ty)
227− -> Expression schema relations grouping params ty
228− parameter ty = UnsafeExpression $ parenthesized $
229− "$" <> renderNat (Proxy @n) <+> "::"
230− <+> renderTypeExpression ty
231−instance {-# OVERLAPPING #-} HasParameter 1 schema (ty1:tys) ty1
232−instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) schema params ty)
233− => HasParameter n schema (ty' : params) ty
234−
235−-- | `param` takes a `Nat` using type application and for basic types,
236−-- infers a `TypeExpression`.
237−--
238−-- >>> let expr = param @1 :: Expression sch rels grp '[ 'Null 'PGint4] ('Null 'PGint4)
239−-- >>> printSQL expr
240−-- ($1 :: int4)
241−param
242− :: forall n schema params relations grouping ty
243− . (PGTyped schema (PGTypeOf ty), HasParameter n schema params ty)
244− => Expression schema relations grouping params ty -- ^ param
245−param = parameter @n pgtype
246−
247−instance (HasUnique relation relations columns, Has column columns ty)
248− => IsLabel column (Expression schema relations 'Ungrouped params ty) where
249− fromLabel = UnsafeExpression $ renderAlias (Alias @column)
250−instance (HasUnique relation relations columns, Has column columns ty)
251− => IsLabel column
252− (Aliased (Expression schema relations 'Ungrouped params) (column ::: ty)) where
253− fromLabel = fromLabel @column `As` Alias @column
254−instance (HasUnique relation relations columns, Has column columns ty)
255− => IsLabel column
256− (NP (Aliased (Expression schema relations 'Ungrouped params)) '[column ::: ty]) where
257− fromLabel = fromLabel @column :* Nil
258−
259−instance (Has relation relations columns, Has column columns ty)
260− => IsQualified relation column (Expression schema relations 'Ungrouped params ty) where
261− relation ! column = UnsafeExpression $
262− renderAlias relation <> "." <> renderAlias column
263−instance (Has relation relations columns, Has column columns ty)
264− => IsQualified relation column
265− (Aliased (Expression schema relations 'Ungrouped params) (column ::: ty)) where
266− relation ! column = relation ! column `As` column
267−instance (Has relation relations columns, Has column columns ty)
268− => IsQualified relation column
269− (NP (Aliased (Expression schema relations 'Ungrouped params)) '[column ::: ty]) where
270− 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
271245
272246instance
273− ( HasUnique relation relations columns
274− , Has column columns ty
275− , GroupedBy relation column bys
276− ) => IsLabel column
277− (Expression schema relations ('Grouped bys) params ty) where
278− 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)
253+instance
254+ ( HasUnique tab (Join outer from) row
255+ , Has col row ty
256+ , GroupedBy tab col bys
257+ , tys ~ '[ty]
258+ ) => IsLabel col
259+ (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
260+ fromLabel = fromLabel @col :* Nil
279261instance
280− ( HasUnique relation relations columns
281− , Has column columns ty
282− , GroupedBy relation column bys
283− ) => IsLabel column
284− ( Aliased (Expression schema relations ('Grouped bys) params)
285− (column ::: ty) ) where
286− fromLabel = fromLabel @column `As` Alias @column
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
287269instance
288− ( HasUnique relation relations columns
289− , Has column columns ty
290− , GroupedBy relation column bys
291− ) => IsLabel column
292− ( NP (Aliased (Expression schema relations ('Grouped bys) params))
293− '[column ::: ty] ) where
294− fromLabel = fromLabel @column :* Nil
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
295277
296278instance
297− ( Has relation relations columns
298− , Has column columns ty
299− , GroupedBy relation column bys
300− ) => IsQualified relation column
301− (Expression schema relations ('Grouped bys) params ty) where
302− relation ! column = UnsafeExpression $
303− 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
304286instance
305− ( Has relation relations columns
306− , Has column columns ty
307− , GroupedBy relation column bys
308− ) => IsQualified relation column
309− (Aliased (Expression schema relations ('Grouped bys) params)
310− (column ::: ty)) where
311− 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
312294instance
313− ( Has relation relations columns
314− , Has column columns ty
315− , GroupedBy relation column bys
316− ) => IsQualified relation column
317− ( NP (Aliased (Expression schema relations ('Grouped bys) params))
318− '[column ::: ty]) where
319− relation ! column = relation ! column :* Nil
320−
321−-- | analagous to `Nothing`
322−--
323−-- >>> printSQL null_
324−-- NULL
325−null_ :: Expression schema rels grouping params ('Null ty)
326−null_ = UnsafeExpression "NULL"
327−
328−-- | analagous to `Just`
329−--
330−-- >>> printSQL $ notNull true
331−-- TRUE
332−notNull
333− :: Expression schema rels grouping params ('NotNull ty)
334− -> Expression schema rels grouping params ('Null ty)
335−notNull = UnsafeExpression . renderExpression
336−
337−-- | return the leftmost value which is not NULL
338−--
339−-- >>> printSQL $ coalesce [null_, notNull true] false
340−-- COALESCE(NULL, TRUE, FALSE)
341−coalesce
342− :: [Expression schema relations grouping params ('Null ty)]
343− -- ^ @NULL@s may be present
344− -> Expression schema relations grouping params ('NotNull ty)
345− -- ^ @NULL@ is absent
346− -> Expression schema relations grouping params ('NotNull ty)
347−coalesce nullxs notNullx = UnsafeExpression $
348− "COALESCE" <> parenthesized (commaSeparated
349− ((renderExpression <$> nullxs) <> [renderExpression notNullx]))
350−
351−-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
352−--
353−-- >>> printSQL $ fromNull true null_
354−-- COALESCE(NULL, TRUE)
355−fromNull
356− :: Expression schema relations grouping params ('NotNull ty)
357− -- ^ what to convert @NULL@ to
358− -> Expression schema relations grouping params ('Null ty)
359− -> Expression schema relations grouping params ('NotNull ty)
360−fromNull notNullx nullx = coalesce [nullx] notNullx
361−
362−-- | >>> printSQL $ null_ & isNull
363−-- NULL IS NULL
364−isNull
365− :: Expression schema relations grouping params ('Null ty)
366− -- ^ possibly @NULL@
367− -> Condition schema relations grouping params
368−isNull x = UnsafeExpression $ renderExpression x <+> "IS NULL"
369−
370−-- | >>> printSQL $ null_ & isNotNull
371−-- NULL IS NOT NULL
372−isNotNull
373− :: Expression schema relations grouping params ('Null ty)
374− -- ^ possibly @NULL@
375− -> Condition schema relations grouping params
376−isNotNull x = UnsafeExpression $ renderExpression x <+> "IS NOT NULL"
377−
378−-- | analagous to `maybe` using @IS NULL@
379−--
380−-- >>> printSQL $ matchNull true not_ null_
381−-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
382−matchNull
383− :: Expression schema relations grouping params (nullty)
384− -- ^ what to convert @NULL@ to
385− -> ( Expression schema relations grouping params ('NotNull ty)
386− -> Expression schema relations grouping params (nullty) )
387− -- ^ function to perform when @NULL@ is absent
388− -> Expression schema relations grouping params ('Null ty)
389− -> Expression schema relations grouping params (nullty)
390−matchNull y f x = ifThenElse (isNull x) y
391− (f (UnsafeExpression (renderExpression x)))
392−
393−{-| right inverse to `fromNull`, if its arguments are equal then
394−`nullIf` gives @NULL@.
395−
396−>>> :set -XTypeApplications -XDataKinds
397−>>> let expr = nullIf false (param @1) :: Expression schema rels grp '[ 'NotNull 'PGbool] ('Null 'PGbool)
398−>>> printSQL expr
399−NULL IF (FALSE, ($1 :: bool))
400−-}
401−nullIf
402− :: Expression schema relations grouping params ('NotNull ty)
403− -- ^ @NULL@ is absent
404− -> Expression schema relations grouping params ('NotNull ty)
405− -- ^ @NULL@ is absent
406− -> Expression schema relations grouping params ('Null ty)
407−nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
408− (renderExpression x <> ", " <> renderExpression y)
409−
410−-- | >>> printSQL $ array [null_, notNull false, notNull true]
411−-- ARRAY[NULL, FALSE, TRUE]
412−array
413− :: [Expression schema relations grouping params ('Null ty)]
414− -- ^ array elements
415− -> Expression schema relations grouping params (nullity ('PGvararray ty))
416−array xs = UnsafeExpression $
417− "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
418310
419311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
420− (Expression schema relations grouping params (nullity ('PGenum labels))) where
421− label = UnsafeExpression $ renderLabel (PGlabel @label)
422−
423−-- | A row constructor is an expression that builds a row value
424−-- (also called a composite value) using values for its member fields.
425−--
426−-- >>> type Complex = PGcomposite '["real" ::: 'PGfloat8, "imaginary" ::: 'PGfloat8]
427−-- >>> let i = row (0 `As` #real :* 1 `As` #imaginary :* Nil) :: Expression '[] '[] 'Ungrouped '[] ('NotNull Complex)
428−-- >>> printSQL i
429−-- ROW(0, 1)
430−row
431− :: SListI (Nulls fields)
432− => NP (Aliased (Expression schema relations grouping params)) (Nulls fields)
433− -- ^ zero or more expressions for the row field values
434− -> Expression schema relations grouping params (nullity ('PGcomposite fields))
435−row exprs = UnsafeExpression $ "ROW" <> parenthesized
436− (renderCommaSeparated (\ (expr `As` _) -> renderExpression expr) exprs)
437−
438−instance Has field fields ty => IsLabel field
439− ( Expression schema relation grouping params (nullity ('PGcomposite fields))
440− -> Expression schema relation grouping params ('Null ty) ) where
441− fromLabel expr = UnsafeExpression $
442− parenthesized (renderExpression expr) <> "." <>
443− fromString (symbolVal (Proxy @field))
444−
445−instance Semigroup
446− (Expression schema relations grouping params (nullity ('PGvararray ty))) where
447− (<>) = unsafeBinaryOp "||"
448−
449−instance Monoid
450− (Expression schema relations grouping params (nullity ('PGvararray ty))) where
451− mempty = array []
452− mappend = (<>)
453−
454−-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression sch rels grp '[ 'NotNull 'PGtimestamptz] ('NotNull 'PGtimestamptz)
455−-- >>> printSQL expr
456−-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
457−greatest
458− :: Expression schema relations grouping params (nullty)
459− -- ^ needs at least 1 argument
460− -> [Expression schema relations grouping params (nullty)]
461− -- ^ or more
462− -> Expression schema relations grouping params (nullty)
463−greatest x xs = UnsafeExpression $ "GREATEST("
464− <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
465−
466−-- | >>> printSQL $ least currentTimestamp [null_]
467−-- LEAST(CURRENT_TIMESTAMP, NULL)
468−least
469− :: Expression schema relations grouping params (nullty)
470− -- ^ needs at least 1 argument
471− -> [Expression schema relations grouping params (nullty)]
472− -- ^ or more
473− -> Expression schema relations grouping params (nullty)
474−least x xs = UnsafeExpression $ "LEAST("
475− <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
312+ (Expression outer commons grp schemas params from (null ('PGenum labels))) where
313+ label = UnsafeExpression $ renderSQL (PGlabel @label)
476314
477315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
478316-- (TRUE OR FALSE)
479−unsafeBinaryOp
480− :: ByteString
481− -- ^ operator
482− -> Expression schema relations grouping params (ty0)
483− -> Expression schema relations grouping params (ty1)
484− -> Expression schema relations grouping params (ty2)
317+unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
485318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
486− renderExpression x <+> op <+> renderExpression y
319+ renderSQL x <+> op <+> renderSQL y
487320
488−-- | >>> printSQL $ unsafeUnaryOp "NOT" true
321+binaryOp
322+ :: forall op sch schemas schema x y z.
323+ ( Has sch schemas schema
324+ , Has op schema ('Operator ('BinaryOp x y z)) )
325+ => OperatorDB schemas x y z
326+binaryOp = unsafeBinaryOp $ renderSymbol @op
327+
328+-- | >>> printSQL $ unsafeLeftOp "NOT" true
489329-- (NOT TRUE)
490−unsafeUnaryOp
491− :: ByteString
492− -- ^ operator
493− -> Expression schema relations grouping params (ty0)
494− -> Expression schema relations grouping params (ty1)
495−unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
496− 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
497351
498352-- | >>> printSQL $ unsafeFunction "f" true
499353-- f(TRUE)
500−unsafeFunction
501− :: ByteString
502− -- ^ function
503− -> Expression schema relations grouping params (xty)
504− -> Expression schema relations grouping params (yty)
354+unsafeFunction :: ByteString -> x --> y
505355unsafeFunction fun x = UnsafeExpression $
506− fun <> parenthesized (renderExpression x)
507−
508−unsafeVariadicFunction
509− :: ByteString
510− -- ^ function
511− -> [Expression schema relations grouping params xty]
512− -> Expression schema relations grouping params (yty)
513−unsafeVariadicFunction fun x = UnsafeExpression $
514− fun <> parenthesized (commaSeparated (map renderExpression x))
515−
516−instance PGNum ty
517− => Num (Expression schema relations 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
518380 (+) = unsafeBinaryOp "+"
519381 (-) = unsafeBinaryOp "-"
520382 (*) = unsafeBinaryOp "*"
@@ -525,19 +387,24 @@ instance PGNum ty
525387 . fromString
526388 . show
527389
528−instance (PGNum ty, PGFloating ty) => Fractional
529− (Expression schema relations 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
530392 (/) = unsafeBinaryOp "/"
531− fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
393+ fromRational
394+ = UnsafeExpression
395+ . fromString
396+ . ($ "")
397+ . showFFloat Nothing
398+ . fromRat @Double
532399
533−instance (PGNum ty, PGFloating ty) => Floating
534− (Expression schema relations 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
535402 pi = UnsafeExpression "pi()"
536403 exp = unsafeFunction "exp"
537404 log = unsafeFunction "ln"
538405 sqrt = unsafeFunction "sqrt"
539406 b ** x = UnsafeExpression $
540− "power(" <> renderExpression b <> ", " <> renderExpression x <> ")"
407+ "power(" <> renderSQL b <> ", " <> renderSQL x <> ")"
541408 logBase b y = log y / log b
542409 sin = unsafeFunction "sin"
543410 cos = unsafeFunction "cos"
@@ -552,927 +419,54 @@ instance (PGNum ty, PGFloating ty) => Floating
552419 acosh x = log (x + sqrt (x*x - 1))
553420 atanh x = log ((1 + x) / (1 - x)) / 2
554421
555−-- | >>> :{
556−-- let
557−-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
558−-- expression = atan2_ pi 2
559−-- in printSQL expression
560−-- :}
561−-- atan2(pi(), 2)
562−atan2_
563− :: PGFloating float
564− => Expression schema relations grouping params (nullity float)
565− -- ^ numerator
566− -> Expression schema relations grouping params (nullity float)
567− -- ^ denominator
568− -> Expression schema relations grouping params (nullity float)
569−atan2_ y x = UnsafeExpression $
570− "atan2(" <> renderExpression y <> ", " <> renderExpression x <> ")"
571−
572−-- When a `cast` is applied to an `Expression` of a known type, it
573−-- represents a run-time type conversion. The cast will succeed only if a
574−-- suitable type conversion operation has been defined.
575−--
576−-- | >>> printSQL $ true & cast int4
577−-- (TRUE :: int4)
578−cast
579− :: TypeExpression schema ty1
580− -- ^ type to cast as
581− -> Expression schema relations grouping params (nullity ty0)
582− -- ^ value to convert
583− -> Expression schema relations grouping params (nullity ty1)
584−cast ty x = UnsafeExpression $ parenthesized $
585− renderExpression x <+> "::" <+> renderTypeExpression ty
586−
587−-- | integer division, truncates the result
588−--
589−-- >>> :{
590−-- let
591−-- expression :: Expression schema relations grouping params (nullity 'PGint2)
592−-- expression = 5 `quot_` 2
593−-- in printSQL expression
594−-- :}
595−-- (5 / 2)
596−quot_
597− :: PGIntegral int
598− => Expression schema relations grouping params (nullity int)
599− -- ^ numerator
600− -> Expression schema relations grouping params (nullity int)
601− -- ^ denominator
602− -> Expression schema relations grouping params (nullity int)
603−quot_ = unsafeBinaryOp "/"
604−
605−-- | remainder upon integer division
606−--
607−-- >>> :{
608−-- let
609−-- expression :: Expression schema relations grouping params (nullity 'PGint2)
610−-- expression = 5 `rem_` 2
611−-- in printSQL expression
612−-- :}
613−-- (5 % 2)
614−rem_
615− :: PGIntegral int
616− => Expression schema relations grouping params (nullity int)
617− -- ^ numerator
618− -> Expression schema relations grouping params (nullity int)
619− -- ^ denominator
620− -> Expression schema relations grouping params (nullity int)
621−rem_ = unsafeBinaryOp "%"
622−
623−-- | >>> :{
624−-- let
625−-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
626−-- expression = trunc pi
627−-- in printSQL expression
628−-- :}
629−-- trunc(pi())
630−trunc
631− :: PGFloating frac
632− => Expression schema relations grouping params (nullity frac)
633− -- ^ fractional number
634− -> Expression schema relations grouping params (nullity frac)
635−trunc = unsafeFunction "trunc"
636−
637−-- | >>> :{
638−-- let
639−-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
640−-- expression = round_ pi
641−-- in printSQL expression
642−-- :}
643−-- round(pi())
644−round_
645− :: PGFloating frac
646− => Expression schema relations grouping params (nullity frac)
647− -- ^ fractional number
648− -> Expression schema relations grouping params (nullity frac)
649−round_ = unsafeFunction "round"
650−
651−-- | >>> :{
652−-- let
653−-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
654−-- expression = ceiling_ pi
655−-- in printSQL expression
656−-- :}
657−-- ceiling(pi())
658−ceiling_
659− :: PGFloating frac
660− => Expression schema relations grouping params (nullity frac)
661− -- ^ fractional number
662− -> Expression schema relations grouping params (nullity frac)
663−ceiling_ = unsafeFunction "ceiling"
664−
665−-- | A `Condition` is a boolean valued `Expression`. While SQL allows
666−-- conditions to have @NULL@, Squeal instead chooses to disallow @NULL@,
667−-- forcing one to handle the case of @NULL@ explicitly to produce
668−-- a `Condition`.
669−type Condition schema relations grouping params =
670− Expression schema relations grouping params ('NotNull 'PGbool)
671−
672−-- | >>> printSQL true
673−-- TRUE
674−true :: Condition schema relations grouping params
675−true = UnsafeExpression "TRUE"
676−
677−-- | >>> printSQL false
678−-- FALSE
679−false :: Condition schema relations grouping params
680−false = UnsafeExpression "FALSE"
681−
682−-- | >>> printSQL $ not_ true
683−-- (NOT TRUE)
684−not_
685− :: Condition schema relations grouping params
686− -> Condition schema relations grouping params
687−not_ = unsafeUnaryOp "NOT"
688−
689−-- | >>> printSQL $ true .&& false
690−-- (TRUE AND FALSE)
691−(.&&)
692− :: Condition schema relations grouping params
693− -> Condition schema relations grouping params
694− -> Condition schema relations grouping params
695−(.&&) = unsafeBinaryOp "AND"
696−
697−-- | >>> printSQL $ true .|| false
698−-- (TRUE OR FALSE)
699−(.||)
700− :: Condition schema relations grouping params
701− -> Condition schema relations grouping params
702− -> Condition schema relations grouping params
703−(.||) = unsafeBinaryOp "OR"
704−
705−-- | >>> :{
706−-- let
707−-- expression :: Expression schema relations grouping params (nullity 'PGint2)
708−-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
709−-- in printSQL expression
710−-- :}
711−-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
712−caseWhenThenElse
713− :: [ ( Condition schema relations grouping params
714− , Expression schema relations grouping params (ty)
715− ) ]
716− -- ^ whens and thens
717− -> Expression schema relations grouping params (ty)
718− -- ^ else
719− -> Expression schema relations grouping params (ty)
720−caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
721− [ "CASE"
722− , mconcat
723− [ mconcat
724− [ " WHEN ", renderExpression when_
725− , " THEN ", renderExpression then_
726− ]
727− | (when_,then_) <- whenThens
728− ]
729− , " ELSE ", renderExpression else_
730− , " END"
731− ]
732−
733−-- | >>> :{
734−-- let
735−-- expression :: Expression schema relations grouping params (nullity 'PGint2)
736−-- expression = ifThenElse true 1 0
737−-- in printSQL expression
738−-- :}
739−-- CASE WHEN TRUE THEN 1 ELSE 0 END
740−ifThenElse
741− :: Condition schema relations grouping params
742− -> Expression schema relations grouping params (ty) -- ^ then
743− -> Expression schema relations grouping params (ty) -- ^ else
744− -> Expression schema relations grouping params (ty)
745−ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
746−
747−-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
748−-- will produce @NULL@s if one of their arguments is @NULL@.
749−--
750−-- >>> printSQL $ notNull true .== null_
751−-- (TRUE = NULL)
752−(.==)
753− :: Expression schema relations grouping params (nullity ty) -- ^ lhs
754− -> Expression schema relations grouping params (nullity ty) -- ^ rhs
755− -> Expression schema relations grouping params (nullity 'PGbool)
756−(.==) = unsafeBinaryOp "="
757−infix 4 .==
758−
759−-- | >>> printSQL $ notNull true ./= null_
760−-- (TRUE <> NULL)
761−(./=)
762− :: Expression schema relations grouping params (nullity ty) -- ^ lhs
763− -> Expression schema relations grouping params (nullity ty) -- ^ rhs
764− -> Expression schema relations grouping params (nullity 'PGbool)
765−(./=) = unsafeBinaryOp "<>"
766−infix 4 ./=
767−
768−-- | >>> printSQL $ notNull true .>= null_
769−-- (TRUE >= NULL)
770−(.>=)
771− :: Expression schema relations grouping params (nullity ty) -- ^ lhs
772− -> Expression schema relations grouping params (nullity ty) -- ^ rhs
773− -> Expression schema relations grouping params (nullity 'PGbool)
774−(.>=) = unsafeBinaryOp ">="
775−infix 4 .>=
776−
777−-- | >>> printSQL $ notNull true .< null_
778−-- (TRUE < NULL)
779−(.<)
780− :: Expression schema relations grouping params (nullity ty) -- ^ lhs
781− -> Expression schema relations grouping params (nullity ty) -- ^ rhs
782− -> Expression schema relations grouping params (nullity 'PGbool)
783−(.<) = unsafeBinaryOp "<"
784−infix 4 .<
785−
786−-- | >>> printSQL $ notNull true .<= null_
787−-- (TRUE <= NULL)
788−(.<=)
789− :: Expression schema relations grouping params (nullity ty) -- ^ lhs
790− -> Expression schema relations grouping params (nullity ty) -- ^ rhs
791− -> Expression schema relations grouping params (nullity 'PGbool)
792−(.<=) = unsafeBinaryOp "<="
793−infix 4 .<=
794−
795−-- | >>> printSQL $ notNull true .> null_
796−-- (TRUE > NULL)
797−(.>)
798− :: Expression schema relations grouping params (nullity ty) -- ^ lhs
799− -> Expression schema relations grouping params (nullity ty) -- ^ rhs
800− -> Expression schema relations grouping params (nullity 'PGbool)
801−(.>) = unsafeBinaryOp ">"
802−infix 4 .>
803−
804−-- | >>> printSQL currentDate
805−-- CURRENT_DATE
806−currentDate
807− :: Expression schema relations grouping params (nullity 'PGdate)
808−currentDate = UnsafeExpression "CURRENT_DATE"
809−
810−-- | >>> printSQL currentTime
811−-- CURRENT_TIME
812−currentTime
813− :: Expression schema relations grouping params (nullity 'PGtimetz)
814−currentTime = UnsafeExpression "CURRENT_TIME"
815−
816−-- | >>> printSQL currentTimestamp
817−-- CURRENT_TIMESTAMP
818−currentTimestamp
819− :: Expression schema relations grouping params (nullity 'PGtimestamptz)
820−currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
821−
822−-- | >>> printSQL localTime
823−-- LOCALTIME
824−localTime
825− :: Expression schema relations grouping params (nullity 'PGtime)
826−localTime = UnsafeExpression "LOCALTIME"
827−
828−-- | >>> printSQL localTimestamp
829−-- LOCALTIMESTAMP
830−localTimestamp
831− :: Expression schema relations grouping params (nullity 'PGtimestamp)
832−localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
833−
834−{-----------------------------------------
835−text
836−-----------------------------------------}
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)
837438
838439instance IsString
839− (Expression schema relations grouping params (nullity 'PGtext)) where
440+ (Expression outer commons grp schemas params from (null 'PGtext)) where
840441 fromString str = UnsafeExpression $
841442 "E\'" <> fromString (escape =<< str) <> "\'"
842− where
843− escape = \case
844− '\NUL' -> "\\0"
845− '\'' -> "''"
846− '"' -> "\\\""
847− '\b' -> "\\b"
848− '\n' -> "\\n"
849− '\r' -> "\\r"
850− '\t' -> "\\t"
851− '\\' -> "\\\\"
852− 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) <> "\'"
853451
854452instance Semigroup
855− (Expression schema relations 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
856463 (<>) = unsafeBinaryOp "||"
857464
858465instance Monoid
859− (Expression schema relations 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
860471 mempty = fromString ""
861472 mappend = (<>)
862−
863−-- | >>> printSQL $ lower "ARRRGGG"
864−-- lower(E'ARRRGGG')
865−lower
866− :: Expression schema relations grouping params (nullity 'PGtext)
867− -- ^ string to lower case
868− -> Expression schema relations grouping params (nullity 'PGtext)
869−lower = unsafeFunction "lower"
870−
871−-- | >>> printSQL $ upper "eeee"
872−-- upper(E'eeee')
873−upper
874− :: Expression schema relations grouping params (nullity 'PGtext)
875− -- ^ string to upper case
876− -> Expression schema relations grouping params (nullity 'PGtext)
877−upper = unsafeFunction "upper"
878−
879−-- | >>> printSQL $ charLength "four"
880−-- char_length(E'four')
881−charLength
882− :: Expression schema relations grouping params (nullity 'PGtext)
883− -- ^ string to measure
884− -> Expression schema relations grouping params (nullity 'PGint4)
885−charLength = unsafeFunction "char_length"
886−
887−-- | The `like` expression returns true if the @string@ matches
888−-- the supplied @pattern@. If @pattern@ does not contain percent signs
889−-- or underscores, then the pattern only represents the string itself;
890−-- in that case `like` acts like the equals operator. An underscore (_)
891−-- in pattern stands for (matches) any single character; a percent sign (%)
892−-- matches any sequence of zero or more characters.
893−--
894−-- >>> printSQL $ "abc" `like` "a%"
895−-- (E'abc' LIKE E'a%')
896−like
897− :: Expression schema relations grouping params (nullity 'PGtext)
898− -- ^ string
899− -> Expression schema relations grouping params (nullity 'PGtext)
900− -- ^ pattern
901− -> Expression schema relations grouping params (nullity 'PGbool)
902−like = unsafeBinaryOp "LIKE"
903−
904−{-----------------------------------------
905−json and jsonb operators
906−see https://www.postgresql.org/docs/10/static/functions-json.html
907−-----------------------------------------}
908−
909−type PGjsonKey key = key `In` '[ 'PGint2, 'PGint4, 'PGtext ]
910−
911−type PGjson_ json = json `In` '[ 'PGjson, 'PGjsonb ]
912−
913−type Placeholder k
914− = 'Text "(_"
915− ':<>: 'Text "::"
916− ':<>: 'ShowType k ':<>:
917− 'Text ")"
918−
919−type ErrArrayOf arr ty = arr ':<>: 'Text " " ':<>: ty
920−type ErrPGfixarrayOf t = ErrArrayOf ('ShowType 'PGfixarray ':<>: 'Text " " ':<>: Placeholder Nat) t
921−type ErrPGvararrayOf t = ErrArrayOf ('ShowType 'PGvararray) t
922−
923−type family PGarray arr :: Constraint where
924− PGarray ('PGvararray x) = ()
925− PGarray ('PGfixarray n x) = ()
926− PGarray val = TypeError
927− ('Text "Unsatisfied PGarrayOf constraint. Expected either: "
928− ':$$: 'Text " • " ':<>: ErrPGvararrayOf (Placeholder PGType)
929− ':$$: 'Text " • " ':<>: ErrPGfixarrayOf (Placeholder PGType)
930− ':$$: 'Text "But got: " ':<>: 'ShowType val)
931−
932−type family PGarrayOf arr ty :: Constraint where
933− PGarrayOf ('PGvararray x) ty = x ~ ty
934− PGarrayOf ('PGfixarray n x) ty = x ~ ty
935− PGarrayOf val ty = TypeError
936− ('Text "Unsatisfied PGarrayOf constraint. Expected either: "
937− ':$$: 'Text " • " ':<>: ErrPGvararrayOf ('ShowType ty)
938− ':$$: 'Text " • " ':<>: ErrPGfixarrayOf ('ShowType ty)
939− ':$$: 'Text "But got: " ':<>: 'ShowType val)
940−
941−type IsPGtextArray arr = PGarrayOf arr 'PGtext
942−
943−-- | Get JSON value (object field or array element) at a key.
944−(.->)
945− :: (PGjson_ json, PGjsonKey key)
946− => Expression schema relations grouping params (jnull json)
947− -> Expression schema relations grouping params (knull key)
948− -> Expression schema relations 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 relations grouping params (jnull json)
955− -> Expression schema relations grouping params (knull key)
956− -> Expression schema relations grouping params ('Null 'PGtext)
957−(.->>) = unsafeBinaryOp "->>"
958−
959−-- | Get JSON value at a specified path.
960−(.#>)
961− :: (PGjson_ json, IsPGtextArray path)
962− => Expression schema relations grouping params (jnull json)
963− -> Expression schema relations grouping params (knull path)
964− -> Expression schema relations grouping params ('Null json)
965−(.#>) = unsafeBinaryOp "#>"
966−
967−-- | Get JSON value at a specified path as text.
968−(.#>>)
969− :: (PGjson_ json, IsPGtextArray path)
970− => Expression schema relations grouping params (jnull json)
971− -> Expression schema relations grouping params (knull path)
972− -> Expression schema relations grouping params ('Null 'PGtext)
973−(.#>>) = unsafeBinaryOp "#>>"
974−
975−-- Additional jsonb operators
976−
977−-- | Or operator for nulls; if either argument is null, then the result is null.
978−type family Null2 a b where
979− Null2 'Null a = 'Null
980− Null2 a 'Null = 'Null
981− Null2 'NotNull 'NotNull = 'NotNull
982−
983−-- | See 'Null2'
984−type family NullOfN xs where
985− NullOfN ('Null ty:xs) = 'Null
986− NullOfN (x:xs) = NullOfN xs
987− NullOfN '[] = 'NotNull
988−
989−-- | Does the left JSON value contain the right JSON path/value entries at the
990−-- top level?
991−(.@>)
992− :: Expression schema relations grouping params (null0 'PGjsonb)
993− -> Expression schema relations grouping params (null1 'PGjsonb)
994− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
995−(.@>) = unsafeBinaryOp "@>"
996−
997−-- | Are the left JSON path/value entries contained at the top level within the
998−-- right JSON value?
999−(.<@)
1000− :: Expression schema relations grouping params (null0 'PGjsonb)
1001− -> Expression schema relations grouping params (null1 'PGjsonb)
1002− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
1003−(.<@) = unsafeBinaryOp "<@"
1004−
1005−-- | Does the string exist as a top-level key within the JSON value?
1006−(.?)
1007− :: Expression schema relations grouping params (null0 'PGjsonb)
1008− -> Expression schema relations grouping params (null1 'PGtext)
1009− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
1010−(.?) = unsafeBinaryOp "?"
1011−
1012−-- | Do any of these array strings exist as top-level keys?
1013−(.?|)
1014− :: Expression schema relations grouping params (null0 'PGjsonb)
1015− -> Expression schema relations grouping params (null1 ('PGvararray 'PGtext))
1016− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
1017−(.?|) = unsafeBinaryOp "?|"
1018−
1019−-- | Do all of these array strings exist as top-level keys?
1020−(.?&)
1021− :: Expression schema relations grouping params (null0 'PGjsonb)
1022− -> Expression schema relations grouping params (null1 ('PGvararray 'PGtext))
1023− -> Expression schema relations grouping params (Null2 null0 null1 'PGbool)
1024−(.?&) = unsafeBinaryOp "?&"
1025−
1026−-- | Concatenate two jsonb values into a new jsonb value
1027−(.||.)
1028− :: Expression schema relations grouping params (null0 'PGjsonb)
1029− -> Expression schema relations grouping params (null1 'PGjsonb)
1030− -> Expression schema relations grouping params (Null2 null0 null1 'PGjsonb)
1031−(.||.) = unsafeBinaryOp "||"
1032−
1033−-- | Delete a key or keys from a JSON object, or remove an array element.
1034−--
1035−-- If the right operand is..
1036−--
1037−-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1038−-- are matched based on their key value.
1039−--
1040−-- @ text[] @: Delete multiple key/value pairs or string elements
1041−-- from left operand. Key/value pairs are matched based on their key value.
1042−--
1043−-- @ integer @: Delete the array element with specified index (Negative integers
1044−-- count from the end). Throws an error if top level container is not an array.
1045−(.-.)
1046− :: (key `In` '[ 'PGtext, 'PGvararray 'PGtext, 'PGint4, 'PGint2 ]) -- hlint error without parens here
1047− => Expression schema relations grouping params (null0 'PGjsonb)
1048− -> Expression schema relations grouping params (null1 key)
1049− -> Expression schema relations grouping params (Null2 null0 null1 'PGjsonb)
1050−(.-.) = unsafeBinaryOp "-"
1051−
1052−-- | Delete the field or element with specified path (for JSON arrays, negative
1053−-- integers count from the end)
1054−(#-.)
1055− :: IsPGtextArray arrayty
1056− => Expression schema relations grouping params (null0 'PGjsonb)
1057− -> Expression schema relations grouping params (null1 arrayty)
1058− -> Expression schema relations grouping params (Null2 null0 null1 'PGjsonb)
1059−(#-.) = unsafeBinaryOp "#-"
1060−
1061−toJson
1062− :: Expression schema relations grouping params (nullity ty)
1063− -> Expression schema relations grouping params (nullity 'PGjson)
1064−toJson = unsafeFunction "to_json"
1065−
1066−toJsonb
1067− :: Expression schema relations grouping params (nullity ty)
1068− -> Expression schema relations grouping params (nullity 'PGjsonb)
1069−toJsonb = unsafeUnaryOp "to_jsonb"
1070−
1071−arrayToJson
1072− :: PGarray arr
1073− => Expression schema relations grouping params (nullity arr)
1074− -> Expression schema relations grouping params (nullity 'PGjson)
1075−arrayToJson = unsafeFunction "array_to_json"
1076−
1077−rowToJson
1078− :: Expression schema relations grouping params (nullity ('PGcomposite ty))
1079− -> Expression schema relations grouping params (nullity 'PGjson)
1080−rowToJson = unsafeFunction "row_to_json"
1081−
1082−jsonObjectKeys
1083− :: Expression schema relations grouping params (nullity 'PGjson)
1084− -> Expression schema relations grouping params (nullity 'PGtext)
1085−jsonObjectKeys = unsafeFunction "json_object_keys"
1086−
1087−jsonbObjectKeys
1088− :: Expression schema relations grouping params (nullity 'PGjsonb)
1089− -> Expression schema relations grouping params (nullity 'PGtext)
1090−jsonbObjectKeys = unsafeFunction "jsonb_object_keys"
1091−
1092−-- TODO: jsonBuildArray, jsonbBuildArray, jsonObject, jsonbObject
1093−-- probably something like
1094−-- :: NP (Expression s r g p) xs -> Expression s r g p ('NotNull 'PGjson[b])
1095−
1096−{-----------------------------------------
1097−aggregation
1098−-----------------------------------------}
1099−
1100−-- | escape hatch to define aggregate functions
1101−unsafeAggregate
1102− :: ByteString -- ^ aggregate function
1103− -> Expression schema relations 'Ungrouped params (xty)
1104− -> Expression schema relations ('Grouped bys) params (yty)
1105−unsafeAggregate fun x = UnsafeExpression $ mconcat
1106− [fun, "(", renderExpression x, ")"]
1107−
1108−-- | escape hatch to define aggregate functions over distinct values
1109−unsafeAggregateDistinct
1110− :: ByteString -- ^ aggregate function
1111− -> Expression schema relations 'Ungrouped params (xty)
1112− -> Expression schema relations ('Grouped bys) params (yty)
1113−unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
1114− [fun, "(DISTINCT ", renderExpression x, ")"]
1115−
1116−-- | >>> :{
1117−-- let
1118−-- expression :: Expression schema '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Grouped bys) params ('Null 'PGnumeric)
1119−-- expression = sum_ #col
1120−-- in printSQL expression
1121−-- :}
1122−-- sum("col")
1123−sum_
1124− :: PGNum ty
1125− => Expression schema relations 'Ungrouped params (nullity ty)
1126− -- ^ what to sum
1127− -> Expression schema relations ('Grouped bys) params (nullity ty)
1128−sum_ = unsafeAggregate "sum"
1129−
1130−-- | >>> :{
1131−-- let
1132−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGnumeric]] ('Grouped bys) params (nullity 'PGnumeric)
1133−-- expression = sumDistinct #col
1134−-- in printSQL expression
1135−-- :}
1136−-- sum(DISTINCT "col")
1137−sumDistinct
1138− :: PGNum ty
1139− => Expression schema relations 'Ungrouped params (nullity ty)
1140− -- ^ what to sum
1141− -> Expression schema relations ('Grouped bys) params (nullity ty)
1142−sumDistinct = unsafeAggregateDistinct "sum"
1143−
1144−-- | A constraint for `PGType`s that you can take averages of and the resulting
1145−-- `PGType`.
1146−class PGAvg ty avg | ty -> avg where
1147− avg, avgDistinct
1148− :: Expression schema relations 'Ungrouped params (nullity ty)
1149− -- ^ what to average
1150− -> Expression schema relations ('Grouped bys) params (nullity avg)
1151− avg = unsafeAggregate "avg"
1152− avgDistinct = unsafeAggregateDistinct "avg"
1153−instance PGAvg 'PGint2 'PGnumeric
1154−instance PGAvg 'PGint4 'PGnumeric
1155−instance PGAvg 'PGint8 'PGnumeric
1156−instance PGAvg 'PGnumeric 'PGnumeric
1157−instance PGAvg 'PGfloat4 'PGfloat8
1158−instance PGAvg 'PGfloat8 'PGfloat8
1159−instance PGAvg 'PGinterval 'PGinterval
1160−
1161−-- | >>> :{
1162−-- let
1163−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1164−-- expression = bitAnd #col
1165−-- in printSQL expression
1166−-- :}
1167−-- bit_and("col")
1168−bitAnd
1169− :: PGIntegral int
1170− => Expression schema relations 'Ungrouped params (nullity int)
1171− -- ^ what to aggregate
1172− -> Expression schema relations ('Grouped bys) params (nullity int)
1173−bitAnd = unsafeAggregate "bit_and"
1174−
1175−-- | >>> :{
1176−-- let
1177−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1178−-- expression = bitOr #col
1179−-- in printSQL expression
1180−-- :}
1181−-- bit_or("col")
1182−bitOr
1183− :: PGIntegral int
1184− => Expression schema relations 'Ungrouped params (nullity int)
1185− -- ^ what to aggregate
1186− -> Expression schema relations ('Grouped bys) params (nullity int)
1187−bitOr = unsafeAggregate "bit_or"
1188−
1189−-- | >>> :{
1190−-- let
1191−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1192−-- expression = bitAndDistinct #col
1193−-- in printSQL expression
1194−-- :}
1195−-- bit_and(DISTINCT "col")
1196−bitAndDistinct
1197− :: PGIntegral int
1198− => Expression schema relations 'Ungrouped params (nullity int)
1199− -- ^ what to aggregate
1200− -> Expression schema relations ('Grouped bys) params (nullity int)
1201−bitAndDistinct = unsafeAggregateDistinct "bit_and"
1202−
1203−-- | >>> :{
1204−-- let
1205−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1206−-- expression = bitOrDistinct #col
1207−-- in printSQL expression
1208−-- :}
1209−-- bit_or(DISTINCT "col")
1210−bitOrDistinct
1211− :: PGIntegral int
1212− => Expression schema relations 'Ungrouped params (nullity int)
1213− -- ^ what to aggregate
1214− -> Expression schema relations ('Grouped bys) params (nullity int)
1215−bitOrDistinct = unsafeAggregateDistinct "bit_or"
1216−
1217−-- | >>> :{
1218−-- let
1219−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1220−-- expression = boolAnd #col
1221−-- in printSQL expression
1222−-- :}
1223−-- bool_and("col")
1224−boolAnd
1225− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1226− -- ^ what to aggregate
1227− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1228−boolAnd = unsafeAggregate "bool_and"
1229−
1230−-- | >>> :{
1231−-- let
1232−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1233−-- expression = boolOr #col
1234−-- in printSQL expression
1235−-- :}
1236−-- bool_or("col")
1237−boolOr
1238− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1239− -- ^ what to aggregate
1240− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1241−boolOr = unsafeAggregate "bool_or"
1242−
1243−-- | >>> :{
1244−-- let
1245−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1246−-- expression = boolAndDistinct #col
1247−-- in printSQL expression
1248−-- :}
1249−-- bool_and(DISTINCT "col")
1250−boolAndDistinct
1251− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1252− -- ^ what to aggregate
1253− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1254−boolAndDistinct = unsafeAggregateDistinct "bool_and"
1255−
1256−-- | >>> :{
1257−-- let
1258−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1259−-- expression = boolOrDistinct #col
1260−-- in printSQL expression
1261−-- :}
1262−-- bool_or(DISTINCT "col")
1263−boolOrDistinct
1264− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1265− -- ^ what to aggregate
1266− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1267−boolOrDistinct = unsafeAggregateDistinct "bool_or"
1268−
1269−-- | A special aggregation that does not require an input
1270−--
1271−-- >>> printSQL countStar
1272−-- count(*)
1273−countStar
1274− :: Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1275−countStar = UnsafeExpression $ "count(*)"
1276−
1277−-- | >>> :{
1278−-- let
1279−-- expression :: Expression schema '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
1280−-- expression = count #col
1281−-- in printSQL expression
1282−-- :}
1283−-- count("col")
1284−count
1285− :: Expression schema relations 'Ungrouped params ty
1286− -- ^ what to count
1287− -> Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1288−count = unsafeAggregate "count"
1289−
1290−-- | >>> :{
1291−-- let
1292−-- expression :: Expression schema '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
1293−-- expression = countDistinct #col
1294−-- in printSQL expression
1295−-- :}
1296−-- count(DISTINCT "col")
1297−countDistinct
1298− :: Expression schema relations 'Ungrouped params ty
1299− -- ^ what to count
1300− -> Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1301−countDistinct = unsafeAggregateDistinct "count"
1302−
1303−-- | synonym for `boolAnd`
1304−--
1305−-- >>> :{
1306−-- let
1307−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1308−-- expression = every #col
1309−-- in printSQL expression
1310−-- :}
1311−-- every("col")
1312−every
1313− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1314− -- ^ what to aggregate
1315− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1316−every = unsafeAggregate "every"
1317−
1318−-- | synonym for `boolAndDistinct`
1319−--
1320−-- >>> :{
1321−-- let
1322−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1323−-- expression = everyDistinct #col
1324−-- in printSQL expression
1325−-- :}
1326−-- every(DISTINCT "col")
1327−everyDistinct
1328− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1329− -- ^ what to aggregate
1330− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1331−everyDistinct = unsafeAggregateDistinct "every"
1332−
1333−-- | minimum and maximum aggregation
1334−max_, min_, maxDistinct, minDistinct
1335− :: Expression schema relations 'Ungrouped params (nullity ty)
1336− -- ^ what to aggregate
1337− -> Expression schema relations ('Grouped bys) params (nullity ty)
1338−max_ = unsafeAggregate "max"
1339−min_ = unsafeAggregate "min"
1340−maxDistinct = unsafeAggregateDistinct "max"
1341−minDistinct = unsafeAggregateDistinct "min"
1342−
1343−{-----------------------------------------
1344−type expressions
1345−-----------------------------------------}
1346−
1347−-- | `TypeExpression`s are used in `cast`s and `createTable` commands.
1348−newtype TypeExpression (schema :: SchemaType) (ty :: PGType)
1349− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1350− deriving (GHC.Generic,Show,Eq,Ord,NFData)
1351−
1352−instance (Has alias schema ('Typedef ty))
1353− => IsLabel alias (TypeExpression schema ty) where
1354− fromLabel = UnsafeTypeExpression (renderAlias (fromLabel @alias))
1355−
1356−-- | logical Boolean (true/false)
1357−bool :: TypeExpression schema 'PGbool
1358−bool = UnsafeTypeExpression "bool"
1359−-- | signed two-byte integer
1360−int2, smallint :: TypeExpression schema 'PGint2
1361−int2 = UnsafeTypeExpression "int2"
1362−smallint = UnsafeTypeExpression "smallint"
1363−-- | signed four-byte integer
1364−int4, int, integer :: TypeExpression schema 'PGint4
1365−int4 = UnsafeTypeExpression "int4"
1366−int = UnsafeTypeExpression "int"
1367−integer = UnsafeTypeExpression "integer"
1368−-- | signed eight-byte integer
1369−int8, bigint :: TypeExpression schema 'PGint8
1370−int8 = UnsafeTypeExpression "int8"
1371−bigint = UnsafeTypeExpression "bigint"
1372−-- | arbitrary precision numeric type
1373−numeric :: TypeExpression schema 'PGnumeric
1374−numeric = UnsafeTypeExpression "numeric"
1375−-- | single precision floating-point number (4 bytes)
1376−float4, real :: TypeExpression schema 'PGfloat4
1377−float4 = UnsafeTypeExpression "float4"
1378−real = UnsafeTypeExpression "real"
1379−-- | double precision floating-point number (8 bytes)
1380−float8, doublePrecision :: TypeExpression schema 'PGfloat8
1381−float8 = UnsafeTypeExpression "float8"
1382−doublePrecision = UnsafeTypeExpression "double precision"
1383−-- | variable-length character string
1384−text :: TypeExpression schema 'PGtext
1385−text = UnsafeTypeExpression "text"
1386−-- | fixed-length character string
1387−char, character
1388− :: (KnownNat n, 1 <= n)
1389− => proxy n
1390− -> TypeExpression schema ('PGchar n)
1391−char p = UnsafeTypeExpression $ "char(" <> renderNat p <> ")"
1392−character p = UnsafeTypeExpression $ "character(" <> renderNat p <> ")"
1393−-- | variable-length character string
1394−varchar, characterVarying
1395− :: (KnownNat n, 1 <= n)
1396− => proxy n
1397− -> TypeExpression schema ('PGvarchar n)
1398−varchar p = UnsafeTypeExpression $ "varchar(" <> renderNat p <> ")"
1399−characterVarying p = UnsafeTypeExpression $
1400− "character varying(" <> renderNat p <> ")"
1401−-- | binary data ("byte array")
1402−bytea :: TypeExpression schema 'PGbytea
1403−bytea = UnsafeTypeExpression "bytea"
1404−-- | date and time (no time zone)
1405−timestamp :: TypeExpression schema 'PGtimestamp
1406−timestamp = UnsafeTypeExpression "timestamp"
1407−-- | date and time, including time zone
1408−timestampWithTimeZone :: TypeExpression schema 'PGtimestamptz
1409−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1410−-- | calendar date (year, month, day)
1411−date :: TypeExpression schema 'PGdate
1412−date = UnsafeTypeExpression "date"
1413−-- | time of day (no time zone)
1414−time :: TypeExpression schema 'PGtime
1415−time = UnsafeTypeExpression "time"
1416−-- | time of day, including time zone
1417−timeWithTimeZone :: TypeExpression schema 'PGtimetz
1418−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1419−-- | time span
1420−interval :: TypeExpression schema 'PGinterval
1421−interval = UnsafeTypeExpression "interval"
1422−-- | universally unique identifier
1423−uuid :: TypeExpression schema 'PGuuid
1424−uuid = UnsafeTypeExpression "uuid"
1425−-- | IPv4 or IPv6 host address
1426−inet :: TypeExpression schema 'PGinet
1427−inet = UnsafeTypeExpression "inet"
1428−-- | textual JSON data
1429−json :: TypeExpression schema 'PGjson
1430−json = UnsafeTypeExpression "json"
1431−-- | binary JSON data, decomposed
1432−jsonb :: TypeExpression schema 'PGjsonb
1433−jsonb = UnsafeTypeExpression "jsonb"
1434−-- | variable length array
1435−vararray
1436− :: TypeExpression schema pg
1437− -> TypeExpression schema ('PGvararray pg)
1438−vararray ty = UnsafeTypeExpression $ renderTypeExpression ty <> "[]"
1439−-- | fixed length array
1440−--
1441−-- >>> renderTypeExpression (fixarray (Proxy @2) json)
1442−-- "json[2]"
1443−fixarray
1444− :: KnownNat n
1445− => proxy n
1446− -> TypeExpression schema pg
1447− -> TypeExpression schema ('PGfixarray n pg)
1448−fixarray p ty = UnsafeTypeExpression $
1449− renderTypeExpression ty <> "[" <> renderNat p <> "]"
1450−
1451−-- | `pgtype` is a demoted version of a `PGType`
1452−class PGTyped schema (ty :: PGType) where pgtype :: TypeExpression schema ty
1453−instance PGTyped schema 'PGbool where pgtype = bool
1454−instance PGTyped schema 'PGint2 where pgtype = int2
1455−instance PGTyped schema 'PGint4 where pgtype = int4
1456−instance PGTyped schema 'PGint8 where pgtype = int8
1457−instance PGTyped schema 'PGnumeric where pgtype = numeric
1458−instance PGTyped schema 'PGfloat4 where pgtype = float4
1459−instance PGTyped schema 'PGfloat8 where pgtype = float8
1460−instance PGTyped schema 'PGtext where pgtype = text
1461−instance (KnownNat n, 1 <= n)
1462− => PGTyped schema ('PGchar n) where pgtype = char (Proxy @n)
1463−instance (KnownNat n, 1 <= n)
1464− => PGTyped schema ('PGvarchar n) where pgtype = varchar (Proxy @n)
1465−instance PGTyped schema 'PGbytea where pgtype = bytea
1466−instance PGTyped schema 'PGtimestamp where pgtype = timestamp
1467−instance PGTyped schema 'PGtimestamptz where pgtype = timestampWithTimeZone
1468−instance PGTyped schema 'PGdate where pgtype = date
1469−instance PGTyped schema 'PGtime where pgtype = time
1470−instance PGTyped schema 'PGtimetz where pgtype = timeWithTimeZone
1471−instance PGTyped schema 'PGinterval where pgtype = interval
1472−instance PGTyped schema 'PGuuid where pgtype = uuid
1473−instance PGTyped schema 'PGjson where pgtype = json
1474−instance PGTyped schema 'PGjsonb where pgtype = jsonb
1475−instance PGTyped schema ty => PGTyped schema ('PGvararray ty) where
1476− pgtype = vararray (pgtype @schema @ty)
1477−instance (KnownNat n, PGTyped schema ty) => PGTyped schema ('PGfixarray n ty) where
1478− pgtype = fixarray (Proxy @n) (pgtype @schema @ty)