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