@@ -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 -fno-warn-unticked-promoted-constructors #-}
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,497 +32,351 @@ Squeal expressions are the atoms used to build statements.
3132
3233module Squeal.PostgreSQL.Expression
3334 ( -- * Expression
34− Expression (UnsafeExpression, renderExpression)
35− , HasParameter (parameter)
36− , param
37− -- ** Null
38− , null_
39− , notNull
40− , coalesce
41− , fromNull
42− , isNull
43− , isNotNull
44− , matchNull
45− , nullIf
46− -- ** Collections
47− , array
48− , row
49− -- ** Functions
50− , unsafeBinaryOp
51− , unsafeUnaryOp
35+ Expression (..)
36+ , Expr
37+ , type (-->)
38+ , FunctionDB
5239 , unsafeFunction
53− , unsafeVariadicFunction
54− , atan2_
55− , cast
56− , quot_
57− , rem_
58− , trunc
59− , round_
60− , ceiling_
61− , greatest
62− , least
63− -- ** Conditions
64− , Condition
65− , true
66− , false
67− , not_
68− , (.&&)
69− , (.||)
70− , caseWhenThenElse
71− , ifThenElse
72− , (.==)
73− , (./=)
74− , (.>=)
75− , (.<)
76− , (.<=)
77− , (.>)
78− -- ** Time
79− , currentDate
80− , currentTime
81− , currentTimestamp
82− , localTime
83− , localTimestamp
84− -- ** Text
85− , lower
86− , upper
87− , charLength
88− , like
89− -- ** json or jsonb operators
90− , PGarray
91− , PGarrayOf
92− , PGjsonKey
93− , PGjson_
94− , PGobjectpairs
95− , (.->)
96− , (.->>)
97− , (.#>)
98− , (.#>>)
99− -- *** jsonb only operators
100− , (.@>)
101− , (.<@)
102− , (.?)
103− , (.?|)
104− , (.?&)
105− , (.||.)
106− , (.-.)
107− , (#-.)
108− -- *** Functions
109− , toJson
110− , toJsonb
111− , arrayToJson
112− , rowToJson
113− , jsonBuildArray
114− , jsonbBuildArray
115− , jsonBuildObject
116− , jsonbBuildObject
117− , jsonObjectKeys
118− , jsonbObjectKeys
119− -- ** Aggregation
120− , unsafeAggregate, unsafeAggregateDistinct
121− , sum_, sumDistinct
122− , PGAvg (avg, avgDistinct)
123− , bitAnd, bitOr, boolAnd, boolOr
124− , bitAndDistinct, bitOrDistinct, boolAndDistinct, boolOrDistinct
125− , countStar
126− , count, countDistinct
127− , every, everyDistinct
128− , max_, maxDistinct, min_, minDistinct
129− -- * Types
130− , TypeExpression (UnsafeTypeExpression, renderTypeExpression)
131− , PGTyped (pgtype)
132− , bool
133− , int2
134− , smallint
135− , int4
136− , int
137− , integer
138− , int8
139− , bigint
140− , numeric
141− , float4
142− , real
143− , float8
144− , doublePrecision
145− , text
146− , char
147− , character
148− , varchar
149− , characterVarying
150− , bytea
151− , timestamp
152− , timestampWithTimeZone
153− , date
154− , time
155− , timeWithTimeZone
156− , interval
157− , uuid
158− , inet
159− , json
160− , jsonb
161− , vararray
162− , 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 (..)
16357 -- * Re-export
16458 , (&)
165− , NP ((:*), Nil)
59+ , K (..)
60+ , unK
16661 ) where
16762
16863import Control.Category
16964import Control.DeepSeq
17065import Data.ByteString (ByteString)
17166import Data.Function ((&))
172−import Data.Semigroup
173−import Data.Ratio
67+import Data.Semigroup hiding (All)
17468import Data.String
175−import Generics.SOP hiding (from)
176−import GHC.Exts (Constraint)
69+import Generics.SOP hiding (All, from)
17770import GHC.OverloadedLabels
17871import GHC.TypeLits
72+import Numeric
17973import Prelude hiding (id, (.))
18074
18175import qualified GHC.Generics as GHC
18276
77+import Squeal.PostgreSQL.Alias
78+import Squeal.PostgreSQL.List
18379import Squeal.PostgreSQL.Render
18480import Squeal.PostgreSQL.Schema
18581
82+-- $setup
83+-- >>> import Squeal.PostgreSQL
84+
18685{-----------------------------------------
18786column expressions
18887-----------------------------------------}
18988
19089{- | `Expression`s are used in a variety of contexts,
191−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,
19292as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
19393`Squeal.PostgreSQL.Manipulation.update`,
194−or in search `Condition`s in a number of commands.
94+or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
19595
19696The expression syntax allows the calculation of
19797values from primitive expression using arithmetic, logical,
19898and 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`.
199113-}
200114newtype Expression
201− (schema :: SchemaType)
202− (relations :: RelationsType)
203− (grouping :: Grouping)
115+ (outer :: FromType)
116+ (commons :: FromType)
117+ (grp :: Grouping)
118+ (schemas :: SchemasType)
204119 (params :: [NullityType])
120+ (from :: FromType)
205121 (ty :: NullityType)
206122 = UnsafeExpression { renderExpression :: ByteString }
207123 deriving (GHC.Generic,Show,Eq,Ord,NFData)
208−
209−instance RenderSQL (Expression schema relations grouping params ty) where
124+instance RenderSQL (Expression outer commons grp schemas params from ty) where
210125 renderSQL = renderExpression
211126
212−{- | A `HasParameter` constraint is used to indicate a value that is
213−supplied externally to a SQL statement.
214−`Squeal.PostgreSQL.PQ.manipulateParams`,
215−`Squeal.PostgreSQL.PQ.queryParams` and
216−`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
217−separately from the SQL command string, in which case `param`s are used to
218−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)
219181-}
220−class KnownNat n => HasParameter
221− (n :: Nat)
222− (schema :: SchemaType)
223− (params :: [NullityType])
224− (ty :: NullityType)
225− | n params -> ty where
226− -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
227− --
228− -- >>> let expr = parameter @1 int4 :: Expression sch rels grp '[ 'Null 'PGint4] ('Null 'PGint4)
229− -- >>> printSQL expr
230− -- ($1 :: int4)
231− parameter
232− :: TypeExpression schema (PGTypeOf ty)
233− -> Expression schema relations grouping params ty
234− parameter ty = UnsafeExpression $ parenthesized $
235− "$" <> renderNat (Proxy @n) <+> "::"
236− <+> renderTypeExpression ty
237−instance {-# OVERLAPPING #-} HasParameter 1 schema (ty1:tys) ty1
238−instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) schema params ty)
239− => HasParameter n schema (ty' : params) ty
240−
241−-- | `param` takes a `Nat` using type application and for basic types,
242−-- infers a `TypeExpression`.
243−--
244−-- >>> let expr = param @1 :: Expression sch rels grp '[ 'Null 'PGint4] ('Null 'PGint4)
245−-- >>> printSQL expr
246−-- ($1 :: int4)
247−param
248− :: forall n schema params relations grouping ty
249− . (PGTyped schema (PGTypeOf ty), HasParameter n schema params ty)
250− => Expression schema relations grouping params ty -- ^ param
251−param = parameter @n pgtype
252−
253−instance (HasUnique relation relations columns, Has column columns ty)
254− => IsLabel column (Expression schema relations 'Ungrouped params ty) where
255− fromLabel = UnsafeExpression $ renderAlias (Alias @column)
256−instance (HasUnique relation relations columns, Has column columns ty)
257− => IsLabel column
258− (Aliased (Expression schema relations 'Ungrouped params) (column ::: ty)) where
259− fromLabel = fromLabel @column `As` Alias @column
260−instance (HasUnique relation relations columns, Has column columns ty)
261− => IsLabel column
262− (NP (Aliased (Expression schema relations 'Ungrouped params)) '[column ::: ty]) where
263− fromLabel = fromLabel @column :* Nil
264−
265−instance (Has relation relations columns, Has column columns ty)
266− => IsQualified relation column (Expression schema relations 'Ungrouped params ty) where
267− relation ! column = UnsafeExpression $
268− renderAlias relation <> "." <> renderAlias column
269−instance (Has relation relations columns, Has column columns ty)
270− => IsQualified relation column
271− (Aliased (Expression schema relations 'Ungrouped params) (column ::: ty)) where
272− relation ! column = relation ! column `As` column
273−instance (Has relation relations columns, Has column columns ty)
274− => IsQualified relation column
275− (NP (Aliased (Expression schema relations 'Ungrouped params)) '[column ::: ty]) where
276− 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
277245
278246instance
279− ( HasUnique relation relations columns
280− , Has column columns ty
281− , GroupedBy relation column bys
282− ) => IsLabel column
283− (Expression schema relations ('Grouped bys) params ty) where
284− 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
285261instance
286− ( HasUnique relation relations columns
287− , Has column columns ty
288− , GroupedBy relation column bys
289− ) => IsLabel column
290− ( Aliased (Expression schema relations ('Grouped bys) params)
291− (column ::: ty) ) where
292− 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
293269instance
294− ( HasUnique relation relations columns
295− , Has column columns ty
296− , GroupedBy relation column bys
297− ) => IsLabel column
298− ( NP (Aliased (Expression schema relations ('Grouped bys) params))
299− '[column ::: ty] ) where
300− 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
301277
302278instance
303− ( Has relation relations columns
304− , Has column columns ty
305− , GroupedBy relation column bys
306− ) => IsQualified relation column
307− (Expression schema relations ('Grouped bys) params ty) where
308− relation ! column = UnsafeExpression $
309− 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
310286instance
311− ( Has relation relations columns
312− , Has column columns ty
313− , GroupedBy relation column bys
314− ) => IsQualified relation column
315− (Aliased (Expression schema relations ('Grouped bys) params)
316− (column ::: ty)) where
317− 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
318294instance
319− ( Has relation relations columns
320− , Has column columns ty
321− , GroupedBy relation column bys
322− ) => IsQualified relation column
323− ( NP (Aliased (Expression schema relations ('Grouped bys) params))
324− '[column ::: ty]) where
325− relation ! column = relation ! column :* Nil
326−
327−-- | analagous to `Nothing`
328−--
329−-- >>> printSQL null_
330−-- NULL
331−null_ :: Expression schema rels grouping params ('Null ty)
332−null_ = UnsafeExpression "NULL"
333−
334−-- | analagous to `Just`
335−--
336−-- >>> printSQL $ notNull true
337−-- TRUE
338−notNull
339− :: Expression schema rels grouping params ('NotNull ty)
340− -> Expression schema rels grouping params ('Null ty)
341−notNull = UnsafeExpression . renderExpression
342−
343−-- | return the leftmost value which is not NULL
344−--
345−-- >>> printSQL $ coalesce [null_, notNull true] false
346−-- COALESCE(NULL, TRUE, FALSE)
347−coalesce
348− :: [Expression schema relations grouping params ('Null ty)]
349− -- ^ @NULL@s may be present
350− -> Expression schema relations grouping params ('NotNull ty)
351− -- ^ @NULL@ is absent
352− -> Expression schema relations grouping params ('NotNull ty)
353−coalesce nullxs notNullx = UnsafeExpression $
354− "COALESCE" <> parenthesized (commaSeparated
355− ((renderExpression <$> nullxs) <> [renderExpression notNullx]))
356−
357−-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
358−--
359−-- >>> printSQL $ fromNull true null_
360−-- COALESCE(NULL, TRUE)
361−fromNull
362− :: Expression schema relations grouping params ('NotNull ty)
363− -- ^ what to convert @NULL@ to
364− -> Expression schema relations grouping params ('Null ty)
365− -> Expression schema relations grouping params ('NotNull ty)
366−fromNull notNullx nullx = coalesce [nullx] notNullx
367−
368−-- | >>> printSQL $ null_ & isNull
369−-- NULL IS NULL
370−isNull
371− :: Expression schema relations grouping params ('Null ty)
372− -- ^ possibly @NULL@
373− -> Condition schema relations grouping params
374−isNull x = UnsafeExpression $ renderExpression x <+> "IS NULL"
375−
376−-- | >>> printSQL $ null_ & isNotNull
377−-- NULL IS NOT NULL
378−isNotNull
379− :: Expression schema relations grouping params ('Null ty)
380− -- ^ possibly @NULL@
381− -> Condition schema relations grouping params
382−isNotNull x = UnsafeExpression $ renderExpression x <+> "IS NOT NULL"
383−
384−-- | analagous to `maybe` using @IS NULL@
385−--
386−-- >>> printSQL $ matchNull true not_ null_
387−-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
388−matchNull
389− :: Expression schema relations grouping params (nullty)
390− -- ^ what to convert @NULL@ to
391− -> ( Expression schema relations grouping params ('NotNull ty)
392− -> Expression schema relations grouping params (nullty) )
393− -- ^ function to perform when @NULL@ is absent
394− -> Expression schema relations grouping params ('Null ty)
395− -> Expression schema relations grouping params (nullty)
396−matchNull y f x = ifThenElse (isNull x) y
397− (f (UnsafeExpression (renderExpression x)))
398−
399−{-| right inverse to `fromNull`, if its arguments are equal then
400−`nullIf` gives @NULL@.
401−
402−>>> :set -XTypeApplications -XDataKinds
403−>>> let expr = nullIf false (param @1) :: Expression schema rels grp '[ 'NotNull 'PGbool] ('Null 'PGbool)
404−>>> printSQL expr
405−NULL IF (FALSE, ($1 :: bool))
406−-}
407−nullIf
408− :: Expression schema relations grouping params ('NotNull ty)
409− -- ^ @NULL@ is absent
410− -> Expression schema relations grouping params ('NotNull ty)
411− -- ^ @NULL@ is absent
412− -> Expression schema relations grouping params ('Null ty)
413−nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
414− (renderExpression x <> ", " <> renderExpression y)
415−
416−-- | >>> printSQL $ array [null_, notNull false, notNull true]
417−-- ARRAY[NULL, FALSE, TRUE]
418−array
419− :: [Expression schema relations grouping params ('Null ty)]
420− -- ^ array elements
421− -> Expression schema relations grouping params (nullity ('PGvararray ty))
422−array xs = UnsafeExpression $
423− "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
424310
425311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
426− (Expression schema relations grouping params (nullity ('PGenum labels))) where
427− label = UnsafeExpression $ renderLabel (PGlabel @label)
428−
429−-- | A row constructor is an expression that builds a row value
430−-- (also called a composite value) using values for its member fields.
431−--
432−-- >>> type Complex = PGcomposite '["real" ::: 'PGfloat8, "imaginary" ::: 'PGfloat8]
433−-- >>> let i = row (0 `As` #real :* 1 `As` #imaginary :* Nil) :: Expression '[] '[] 'Ungrouped '[] ('NotNull Complex)
434−-- >>> printSQL i
435−-- ROW(0, 1)
436−row
437− :: SListI (Nulls fields)
438− => NP (Aliased (Expression schema relations grouping params)) (Nulls fields)
439− -- ^ zero or more expressions for the row field values
440− -> Expression schema relations grouping params (nullity ('PGcomposite fields))
441−row exprs = UnsafeExpression $ "ROW" <> parenthesized
442− (renderCommaSeparated (\ (expr `As` _) -> renderExpression expr) exprs)
443−
444−instance Has field fields ty => IsLabel field
445− ( Expression schema relation grouping params (nullity ('PGcomposite fields))
446− -> Expression schema relation grouping params ('Null ty) ) where
447− fromLabel expr = UnsafeExpression $
448− parenthesized (renderExpression expr) <> "." <>
449− fromString (symbolVal (Proxy @field))
450−
451−instance Semigroup
452− (Expression schema relations grouping params (nullity ('PGvararray ty))) where
453− (<>) = unsafeBinaryOp "||"
454−
455−instance Monoid
456− (Expression schema relations grouping params (nullity ('PGvararray ty))) where
457− mempty = array []
458− mappend = (<>)
459−
460−-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression sch rels grp '[ 'NotNull 'PGtimestamptz] ('NotNull 'PGtimestamptz)
461−-- >>> printSQL expr
462−-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
463−greatest
464− :: Expression schema relations grouping params (nullty)
465− -- ^ needs at least 1 argument
466− -> [Expression schema relations grouping params (nullty)]
467− -- ^ or more
468− -> Expression schema relations grouping params (nullty)
469−greatest x xs = UnsafeExpression $ "GREATEST("
470− <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
471−
472−-- | >>> printSQL $ least currentTimestamp [null_]
473−-- LEAST(CURRENT_TIMESTAMP, NULL)
474−least
475− :: Expression schema relations grouping params (nullty)
476− -- ^ needs at least 1 argument
477− -> [Expression schema relations grouping params (nullty)]
478− -- ^ or more
479− -> Expression schema relations grouping params (nullty)
480−least x xs = UnsafeExpression $ "LEAST("
481− <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
312+ (Expression outer commons grp schemas params from (null ('PGenum labels))) where
313+ label = UnsafeExpression $ renderSQL (PGlabel @label)
482314
483315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
484316-- (TRUE OR FALSE)
485−unsafeBinaryOp
486− :: ByteString
487− -- ^ operator
488− -> Expression schema relations grouping params (ty0)
489− -> Expression schema relations grouping params (ty1)
490− -> Expression schema relations grouping params (ty2)
317+unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
491318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
492− renderExpression x <+> op <+> renderExpression y
319+ renderSQL x <+> op <+> renderSQL y
320+
321+binaryOp
322+ :: forall op sch schemas schema x y z.
323+ ( Has sch schemas schema
324+ , Has op schema ('Operator ('BinaryOp x y z)) )
325+ => OperatorDB schemas x y z
326+binaryOp = unsafeBinaryOp $ renderSymbol @op
493327
494−-- | >>> printSQL $ unsafeUnaryOp "NOT" true
328+-- | >>> printSQL $ unsafeLeftOp "NOT" true
495329-- (NOT TRUE)
496−unsafeUnaryOp
497− :: ByteString
498− -- ^ operator
499− -> Expression schema relations grouping params (ty0)
500− -> Expression schema relations grouping params (ty1)
501−unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
502− 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
503351
504352-- | >>> printSQL $ unsafeFunction "f" true
505353-- f(TRUE)
506−unsafeFunction
507− :: ByteString
508− -- ^ function
509− -> Expression schema relations grouping params (xty)
510− -> Expression schema relations grouping params (yty)
354+unsafeFunction :: ByteString -> x --> y
511355unsafeFunction fun x = UnsafeExpression $
512− fun <> parenthesized (renderExpression x)
513−
514−unsafeVariadicFunction
515− :: SListI elems
516− => ByteString
517− -- ^ function
518− -> NP (Expression schema relations grouping params) elems
519− -> Expression schema relations grouping params ret
520−unsafeVariadicFunction fun x = UnsafeExpression $
521− fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderExpression) x)))
522−
523−instance PGNum ty
524− => 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
525380 (+) = unsafeBinaryOp "+"
526381 (-) = unsafeBinaryOp "-"
527382 (*) = unsafeBinaryOp "*"
@@ -532,19 +387,24 @@ instance PGNum ty
532387 . fromString
533388 . show
534389
535−instance (PGNum ty, PGFloating ty) => Fractional
536− (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
537392 (/) = unsafeBinaryOp "/"
538− fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
393+ fromRational
394+ = UnsafeExpression
395+ . fromString
396+ . ($ "")
397+ . showFFloat Nothing
398+ . fromRat @Double
539399
540−instance (PGNum ty, PGFloating ty) => Floating
541− (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
542402 pi = UnsafeExpression "pi()"
543403 exp = unsafeFunction "exp"
544404 log = unsafeFunction "ln"
545405 sqrt = unsafeFunction "sqrt"
546406 b ** x = UnsafeExpression $
547− "power(" <> renderExpression b <> ", " <> renderExpression x <> ")"
407+ "power(" <> renderSQL b <> ", " <> renderSQL x <> ")"
548408 logBase b y = log y / log b
549409 sin = unsafeFunction "sin"
550410 cos = unsafeFunction "cos"
@@ -559,1032 +419,54 @@ instance (PGNum ty, PGFloating ty) => Floating
559419 acosh x = log (x + sqrt (x*x - 1))
560420 atanh x = log ((1 + x) / (1 - x)) / 2
561421
562−-- | >>> :{
563−-- let
564−-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
565−-- expression = atan2_ pi 2
566−-- in printSQL expression
567−-- :}
568−-- atan2(pi(), 2)
569−atan2_
570− :: PGFloating float
571− => Expression schema relations grouping params (nullity float)
572− -- ^ numerator
573− -> Expression schema relations grouping params (nullity float)
574− -- ^ denominator
575− -> Expression schema relations grouping params (nullity float)
576−atan2_ y x = UnsafeExpression $
577− "atan2(" <> renderExpression y <> ", " <> renderExpression x <> ")"
578−
579−-- When a `cast` is applied to an `Expression` of a known type, it
580−-- represents a run-time type conversion. The cast will succeed only if a
581−-- suitable type conversion operation has been defined.
582−--
583−-- | >>> printSQL $ true & cast int4
584−-- (TRUE :: int4)
585−cast
586− :: TypeExpression schema ty1
587− -- ^ type to cast as
588− -> Expression schema relations grouping params (nullity ty0)
589− -- ^ value to convert
590− -> Expression schema relations grouping params (nullity ty1)
591−cast ty x = UnsafeExpression $ parenthesized $
592− renderExpression x <+> "::" <+> renderTypeExpression ty
593−
594−-- | integer division, truncates the result
595−--
596−-- >>> :{
597−-- let
598−-- expression :: Expression schema relations grouping params (nullity 'PGint2)
599−-- expression = 5 `quot_` 2
600−-- in printSQL expression
601−-- :}
602−-- (5 / 2)
603−quot_
604− :: PGIntegral int
605− => Expression schema relations grouping params (nullity int)
606− -- ^ numerator
607− -> Expression schema relations grouping params (nullity int)
608− -- ^ denominator
609− -> Expression schema relations grouping params (nullity int)
610−quot_ = unsafeBinaryOp "/"
611−
612−-- | remainder upon integer division
613−--
614−-- >>> :{
615−-- let
616−-- expression :: Expression schema relations grouping params (nullity 'PGint2)
617−-- expression = 5 `rem_` 2
618−-- in printSQL expression
619−-- :}
620−-- (5 % 2)
621−rem_
622− :: PGIntegral int
623− => Expression schema relations grouping params (nullity int)
624− -- ^ numerator
625− -> Expression schema relations grouping params (nullity int)
626− -- ^ denominator
627− -> Expression schema relations grouping params (nullity int)
628−rem_ = unsafeBinaryOp "%"
629−
630−-- | >>> :{
631−-- let
632−-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
633−-- expression = trunc pi
634−-- in printSQL expression
635−-- :}
636−-- trunc(pi())
637−trunc
638− :: PGFloating frac
639− => Expression schema relations grouping params (nullity frac)
640− -- ^ fractional number
641− -> Expression schema relations grouping params (nullity frac)
642−trunc = unsafeFunction "trunc"
643−
644−-- | >>> :{
645−-- let
646−-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
647−-- expression = round_ pi
648−-- in printSQL expression
649−-- :}
650−-- round(pi())
651−round_
652− :: PGFloating frac
653− => Expression schema relations grouping params (nullity frac)
654− -- ^ fractional number
655− -> Expression schema relations grouping params (nullity frac)
656−round_ = unsafeFunction "round"
657−
658−-- | >>> :{
659−-- let
660−-- expression :: Expression schema relations grouping params (nullity 'PGfloat4)
661−-- expression = ceiling_ pi
662−-- in printSQL expression
663−-- :}
664−-- ceiling(pi())
665−ceiling_
666− :: PGFloating frac
667− => Expression schema relations grouping params (nullity frac)
668− -- ^ fractional number
669− -> Expression schema relations grouping params (nullity frac)
670−ceiling_ = unsafeFunction "ceiling"
671−
672−-- | A `Condition` is a boolean valued `Expression`. While SQL allows
673−-- conditions to have @NULL@, Squeal instead chooses to disallow @NULL@,
674−-- forcing one to handle the case of @NULL@ explicitly to produce
675−-- a `Condition`.
676−type Condition schema relations grouping params =
677− Expression schema relations grouping params ('NotNull 'PGbool)
678−
679−-- | >>> printSQL true
680−-- TRUE
681−true :: Condition schema relations grouping params
682−true = UnsafeExpression "TRUE"
683−
684−-- | >>> printSQL false
685−-- FALSE
686−false :: Condition schema relations grouping params
687−false = UnsafeExpression "FALSE"
688−
689−-- | >>> printSQL $ not_ true
690−-- (NOT TRUE)
691−not_
692− :: Condition schema relations grouping params
693− -> Condition schema relations grouping params
694−not_ = unsafeUnaryOp "NOT"
695−
696−-- | >>> printSQL $ true .&& false
697−-- (TRUE AND FALSE)
698−(.&&)
699− :: Condition schema relations grouping params
700− -> Condition schema relations grouping params
701− -> Condition schema relations grouping params
702−(.&&) = unsafeBinaryOp "AND"
703−
704−-- | >>> printSQL $ true .|| false
705−-- (TRUE OR FALSE)
706−(.||)
707− :: Condition schema relations grouping params
708− -> Condition schema relations grouping params
709− -> Condition schema relations grouping params
710−(.||) = unsafeBinaryOp "OR"
711−
712−-- | >>> :{
713−-- let
714−-- expression :: Expression schema relations grouping params (nullity 'PGint2)
715−-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
716−-- in printSQL expression
717−-- :}
718−-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
719−caseWhenThenElse
720− :: [ ( Condition schema relations grouping params
721− , Expression schema relations grouping params (ty)
722− ) ]
723− -- ^ whens and thens
724− -> Expression schema relations grouping params (ty)
725− -- ^ else
726− -> Expression schema relations grouping params (ty)
727−caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
728− [ "CASE"
729− , mconcat
730− [ mconcat
731− [ " WHEN ", renderExpression when_
732− , " THEN ", renderExpression then_
733− ]
734− | (when_,then_) <- whenThens
735− ]
736− , " ELSE ", renderExpression else_
737− , " END"
738− ]
739−
740−-- | >>> :{
741−-- let
742−-- expression :: Expression schema relations grouping params (nullity 'PGint2)
743−-- expression = ifThenElse true 1 0
744−-- in printSQL expression
745−-- :}
746−-- CASE WHEN TRUE THEN 1 ELSE 0 END
747−ifThenElse
748− :: Condition schema relations grouping params
749− -> Expression schema relations grouping params (ty) -- ^ then
750− -> Expression schema relations grouping params (ty) -- ^ else
751− -> Expression schema relations grouping params (ty)
752−ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
753−
754−-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
755−-- will produce @NULL@s if one of their arguments is @NULL@.
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 $ notNull true .> null_
803−-- (TRUE > NULL)
804−(.>)
805− :: Expression schema relations grouping params (nullity ty) -- ^ lhs
806− -> Expression schema relations grouping params (nullity ty) -- ^ rhs
807− -> Expression schema relations grouping params (nullity 'PGbool)
808−(.>) = unsafeBinaryOp ">"
809−infix 4 .>
810−
811−-- | >>> printSQL currentDate
812−-- CURRENT_DATE
813−currentDate
814− :: Expression schema relations grouping params (nullity 'PGdate)
815−currentDate = UnsafeExpression "CURRENT_DATE"
816−
817−-- | >>> printSQL currentTime
818−-- CURRENT_TIME
819−currentTime
820− :: Expression schema relations grouping params (nullity 'PGtimetz)
821−currentTime = UnsafeExpression "CURRENT_TIME"
822−
823−-- | >>> printSQL currentTimestamp
824−-- CURRENT_TIMESTAMP
825−currentTimestamp
826− :: Expression schema relations grouping params (nullity 'PGtimestamptz)
827−currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
828−
829−-- | >>> printSQL localTime
830−-- LOCALTIME
831−localTime
832− :: Expression schema relations grouping params (nullity 'PGtime)
833−localTime = UnsafeExpression "LOCALTIME"
834−
835−-- | >>> printSQL localTimestamp
836−-- LOCALTIMESTAMP
837−localTimestamp
838− :: Expression schema relations grouping params (nullity 'PGtimestamp)
839−localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
840−
841−{-----------------------------------------
842−text
843−-----------------------------------------}
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)
844438
845439instance IsString
846− (Expression schema relations grouping params (nullity 'PGtext)) where
440+ (Expression outer commons grp schemas params from (null 'PGtext)) where
847441 fromString str = UnsafeExpression $
848442 "E\'" <> fromString (escape =<< str) <> "\'"
849− where
850− escape = \case
851− '\NUL' -> "\\0"
852− '\'' -> "''"
853− '"' -> "\\\""
854− '\b' -> "\\b"
855− '\n' -> "\\n"
856− '\r' -> "\\r"
857− '\t' -> "\\t"
858− '\\' -> "\\\\"
859− 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) <> "\'"
860451
861452instance Semigroup
862− (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
863463 (<>) = unsafeBinaryOp "||"
864464
865465instance Monoid
866− (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
867471 mempty = fromString ""
868472 mappend = (<>)
869−
870−-- | >>> printSQL $ lower "ARRRGGG"
871−-- lower(E'ARRRGGG')
872−lower
873− :: Expression schema relations grouping params (nullity 'PGtext)
874− -- ^ string to lower case
875− -> Expression schema relations grouping params (nullity 'PGtext)
876−lower = unsafeFunction "lower"
877−
878−-- | >>> printSQL $ upper "eeee"
879−-- upper(E'eeee')
880−upper
881− :: Expression schema relations grouping params (nullity 'PGtext)
882− -- ^ string to upper case
883− -> Expression schema relations grouping params (nullity 'PGtext)
884−upper = unsafeFunction "upper"
885−
886−-- | >>> printSQL $ charLength "four"
887−-- char_length(E'four')
888−charLength
889− :: Expression schema relations grouping params (nullity 'PGtext)
890− -- ^ string to measure
891− -> Expression schema relations grouping params (nullity 'PGint4)
892−charLength = unsafeFunction "char_length"
893−
894−-- | The `like` expression returns true if the @string@ matches
895−-- the supplied @pattern@. If @pattern@ does not contain percent signs
896−-- or underscores, then the pattern only represents the string itself;
897−-- in that case `like` acts like the equals operator. An underscore (_)
898−-- in pattern stands for (matches) any single character; a percent sign (%)
899−-- matches any sequence of zero or more characters.
900−--
901−-- >>> printSQL $ "abc" `like` "a%"
902−-- (E'abc' LIKE E'a%')
903−like
904− :: Expression schema relations grouping params (nullity 'PGtext)
905− -- ^ string
906− -> Expression schema relations grouping params (nullity 'PGtext)
907− -- ^ pattern
908− -> Expression schema relations grouping params (nullity 'PGbool)
909−like = unsafeBinaryOp "LIKE"
910−
911−{-----------------------------------------
912− -- json and jsonb support
913−
914−See https://www.postgresql.org/docs/10/static/functions-json.html -- most
915−comments lifted directly from this page.
916−
917−Table 9.44: json and jsonb operators
918−-----------------------------------------}
919−
920−type PGjsonKey key = key `In` '[ 'PGint2, 'PGint4, 'PGtext ]
921−
922−type PGjson_ json = json `In` '[ 'PGjson, 'PGjsonb ]
923−
924−type Placeholder k = 'Text "(_::" :<>: 'ShowType k :<>: 'Text ")"
925−type ErrArrayOf arr ty = arr :<>: 'Text " " :<>: ty
926−type ErrPGfixarrayOf t = ErrArrayOf ('ShowType 'PGfixarray :<>: 'Text " " :<>: Placeholder Nat) t
927−type ErrPGvararrayOf t = ErrArrayOf ('ShowType 'PGvararray) t
928−
929−type family PGarray name arr :: Constraint where
930− PGarray name ('PGvararray x) = ()
931− PGarray name ('PGfixarray n x) = ()
932− PGarray name val = TypeError
933− ('Text name :<>: 'Text ": Unsatisfied PGarrayOf constraint. Expected either: "
934− :$$: 'Text " • " :<>: ErrPGvararrayOf (Placeholder PGType)
935− :$$: 'Text " • " :<>: ErrPGfixarrayOf (Placeholder PGType)
936− :$$: 'Text "But got: " :<>: 'ShowType val)
937−
938−type family PGarrayOf name arr ty :: Constraint where
939− PGarrayOf name ('PGvararray x) ty = x ~ ty
940− PGarrayOf name ('PGfixarray n x) ty = x ~ ty
941− PGarrayOf name val ty = TypeError
942− ( 'Text name :<>: 'Text "Unsatisfied PGarrayOf constraint. Expected either: "
943− :$$: 'Text " • " :<>: ErrPGvararrayOf ( 'ShowType ty )
944− :$$: 'Text " • " :<>: ErrPGfixarrayOf ( 'ShowType ty )
945− :$$: 'Text "But got: " :<>: 'ShowType val)
946−
947−type IsPGtextArray name arr = PGarrayOf name arr 'PGtext
948−
949−-- | Get JSON value (object field or array element) at a key.
950−(.->)
951− :: (PGjson_ json, PGjsonKey key)
952− => Expression schema relations grouping params (nullity json)
953− -> Expression schema relations grouping params (nullity key)
954− -> Expression schema relations grouping params ('Null json)
955−(.->) = unsafeBinaryOp "->"
956−
957−-- | Get JSON value (object field or array element) at a key, as text.
958−(.->>)
959− :: (PGjson_ json, PGjsonKey key)
960− => Expression schema relations grouping params (nullity json)
961− -> Expression schema relations grouping params (nullity key)
962− -> Expression schema relations grouping params ('Null 'PGtext)
963−(.->>) = unsafeBinaryOp "->>"
964−
965−-- | Get JSON value at a specified path.
966−(.#>)
967− :: (PGjson_ json, IsPGtextArray "(.#>)" path)
968− => Expression schema relations grouping params (nullity json)
969− -> Expression schema relations grouping params (nullity path)
970− -> Expression schema relations grouping params ('Null json)
971−(.#>) = unsafeBinaryOp "#>"
972−
973−-- | Get JSON value at a specified path as text.
974−(.#>>)
975− :: (PGjson_ json, IsPGtextArray "(.#>>)" path)
976− => Expression schema relations grouping params (nullity json)
977− -> Expression schema relations grouping params (nullity path)
978− -> Expression schema relations grouping params ('Null 'PGtext)
979−(.#>>) = unsafeBinaryOp "#>>"
980−
981−-- Additional jsonb operators
982−
983−-- | Does the left JSON value contain the right JSON path/value entries at the
984−-- top level?
985−(.@>)
986− :: Expression schema relations grouping params (nullity 'PGjsonb)
987− -> Expression schema relations grouping params (nullity 'PGjsonb)
988− -> Expression schema relations grouping params ('NotNull 'PGbool)
989−(.@>) = unsafeBinaryOp "@>"
990−
991−-- | Are the left JSON path/value entries contained at the top level within the
992−-- right JSON value?
993−(.<@)
994− :: Expression schema relations grouping params (nullity 'PGjsonb)
995− -> Expression schema relations grouping params (nullity 'PGjsonb)
996− -> Expression schema relations grouping params ('NotNull 'PGbool)
997−(.<@) = unsafeBinaryOp "<@"
998−
999−-- | Does the string exist as a top-level key within the JSON value?
1000−(.?)
1001− :: Expression schema relations grouping params (nullity 'PGjsonb)
1002− -> Expression schema relations grouping params (nullity 'PGtext)
1003− -> Expression schema relations grouping params ('NotNull 'PGbool)
1004−(.?) = unsafeBinaryOp "?"
1005−
1006−-- | Do any of these array strings exist as top-level keys?
1007−(.?|)
1008− :: Expression schema relations grouping params (nullity 'PGjsonb)
1009− -> Expression schema relations grouping params (nullity ('PGvararray 'PGtext))
1010− -> Expression schema relations grouping params ('NotNull 'PGbool)
1011−(.?|) = unsafeBinaryOp "?|"
1012−
1013−-- | Do all of these array strings exist as top-level keys?
1014−(.?&)
1015− :: Expression schema relations grouping params (nullity 'PGjsonb)
1016− -> Expression schema relations grouping params (nullity ('PGvararray 'PGtext))
1017− -> Expression schema relations grouping params ('NotNull 'PGbool)
1018−(.?&) = unsafeBinaryOp "?&"
1019−
1020−-- | Concatenate two jsonb values into a new jsonb value.
1021−(.||.)
1022− :: Expression schema relations grouping params (nullity 'PGjsonb)
1023− -> Expression schema relations grouping params (nullity 'PGjsonb)
1024− -> Expression schema relations grouping params (nullity 'PGjsonb)
1025−(.||.) = unsafeBinaryOp "||"
1026−
1027−-- | Delete a key or keys from a JSON object, or remove an array element.
1028−--
1029−-- If the right operand is..
1030−--
1031−-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1032−-- are matched based on their key value.
1033−--
1034−-- @ text[] @: Delete multiple key/value pairs or string elements
1035−-- from left operand. Key/value pairs are matched based on their key value.
1036−--
1037−-- @ integer @: Delete the array element with specified index (Negative integers
1038−-- count from the end). Throws an error if top level container is not an array.
1039−(.-.)
1040− :: (key `In` '[ 'PGtext, 'PGvararray 'PGtext, 'PGint4, 'PGint2 ]) -- hlint error without parens here
1041− => Expression schema relations grouping params (nullity 'PGjsonb)
1042− -> Expression schema relations grouping params (nullity key)
1043− -> Expression schema relations grouping params (nullity 'PGjsonb)
1044−(.-.) = unsafeBinaryOp "-"
1045−
1046−-- | Delete the field or element with specified path (for JSON arrays, negative
1047−-- integers count from the end)
1048−(#-.)
1049− :: IsPGtextArray "(#-.)" arrayty
1050− => Expression schema relations grouping params (nullity 'PGjsonb)
1051− -> Expression schema relations grouping params (nullity arrayty)
1052− -> Expression schema relations grouping params (nullity 'PGjsonb)
1053−(#-.) = unsafeBinaryOp "#-"
1054−
1055−{-----------------------------------------
1056−Table 9.45: JSON creation functions
1057−-----------------------------------------}
1058−
1059−-- | Returns the value as json. Arrays and composites are converted
1060−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1061−-- type to json, the cast function will be used to perform the conversion;
1062−-- otherwise, a scalar value is produced. For any scalar type other than a
1063−-- number, a Boolean, or a null value, the text representation will be used, in
1064−-- such a fashion that it is a valid json value.
1065−toJson
1066− :: Expression schema relations grouping params (nullity ty)
1067− -> Expression schema relations grouping params (nullity 'PGjson)
1068−toJson = unsafeFunction "to_json"
1069−
1070−-- | Returns the value as jsonb. Arrays and composites are converted
1071−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1072−-- type to json, the cast function will be used to perform the conversion;
1073−-- otherwise, a scalar value is produced. For any scalar type other than a
1074−-- number, a Boolean, or a null value, the text representation will be used, in
1075−-- such a fashion that it is a valid jsonb value.
1076−toJsonb
1077− :: Expression schema relations grouping params (nullity ty)
1078− -> Expression schema relations grouping params (nullity 'PGjsonb)
1079−toJsonb = unsafeUnaryOp "to_jsonb"
1080−
1081−-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1082−-- becomes a JSON array of arrays. Line feeds will be added between dimension-1
1083−-- elements if pretty_bool is true.
1084−arrayToJson
1085− :: PGarray "arrayToJson" arr
1086− => Expression schema relations grouping params (nullity arr)
1087− -> Expression schema relations grouping params (nullity 'PGjson)
1088−arrayToJson = unsafeFunction "array_to_json"
1089−
1090−-- | Returns the row as a JSON object. Line feeds will be added between level-1
1091−-- elements if pretty_bool is true.
1092−rowToJson
1093− :: Expression schema relations grouping params (nullity ('PGcomposite ty))
1094− -> Expression schema relations grouping params (nullity 'PGjson)
1095−rowToJson = unsafeFunction "row_to_json"
1096−
1097−-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1098−-- argument list.
1099−jsonBuildArray
1100− :: SListI elems
1101− => NP (Expression schema relations grouping params) elems
1102− -> Expression schema relations grouping params (nullity 'PGjson)
1103−jsonBuildArray = unsafeVariadicFunction "json_build_array"
1104−
1105−-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1106−-- variadic argument list.
1107−jsonbBuildArray
1108− :: SListI elems
1109− => NP (Expression schema relations grouping params) elems
1110− -> Expression schema relations grouping params (nullity 'PGjsonb)
1111−jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1112−
1113−type family PGobjectpairs name x :: Constraint where
1114− PGobjectpairs name ('NotNull 'PGtext : nullity arg : xs) = PGobjectpairs name xs
1115− PGobjectpairs name '[] = ()
1116− PGobjectpairs name (x:xs) = TypeError
1117− ( 'Text name :<>: 'Text ": Incorrect argument list:"
1118− :$$: 'Text "Expected alternating list of keys and values."
1119− :$$: 'Text "But got " :<>: 'ShowType (x:xs))
1120−
1121−-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1122−-- argument list. The elements of the argument list must alternate between text
1123−-- and values.
1124−jsonBuildObject
1125− :: (PGobjectpairs "jsonBuildObject" elems, SListI elems)
1126− => NP (Expression schema relations grouping params) elems
1127− -> Expression schema relations grouping params (nullity 'PGjson)
1128−jsonBuildObject = unsafeVariadicFunction "json_build_object"
1129−
1130−-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1131−-- variadic argument list. The elements of the argument list must alternate
1132−-- between text and values.
1133−jsonbBuildObject
1134− :: (PGobjectpairs "jsonbBuildObject" elems, SListI elems)
1135− => NP (Expression schema relations grouping params) elems
1136− -> Expression schema relations grouping params (nullity 'PGjsonb)
1137−jsonbBuildObject = unsafeVariadicFunction "jsonb_build_object"
1138−
1139−-- | Builds a JSON object out of a text array. The array must have either
1140−-- exactly one dimension with an even number of members, in which case they are
1141−-- taken as alternating key/value pairs, or two dimensions such that each inner
1142−-- array has exactly two elements, which are taken as a key/value pair.
1143−jsonObject
1144− :: PGarrayOf "jsonObject" arr 'PGtext
1145− => Expression schema relations grouping params (nullity arr)
1146− -> Expression schema relations grouping params (nullity 'PGjson)
1147−jsonObject = unsafeFunction "json_object"
1148−
1149−-- | Builds a binary JSON object out of a text array. The array must have either
1150−-- exactly one dimension with an even number of members, in which case they are
1151−-- taken as alternating key/value pairs, or two dimensions such that each inner
1152−-- array has exactly two elements, which are taken as a key/value pair.
1153−jsonbObject
1154− :: PGarrayOf "jsonbObject" arr 'PGtext
1155− => Expression schema relations grouping params (nullity arr)
1156− -> Expression schema relations grouping params (nullity 'PGjsonb)
1157−jsonbObject = unsafeFunction "jsonb_object"
1158−
1159−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1160−-- keys and one for values, that are zipped pairwise to create a JSON object.
1161−jsonZipObject
1162− :: ( PGarrayOf "jsonZipObject" keysArray 'PGtext
1163− , PGarrayOf "jsonZipObject" valuesArray 'PGtext)
1164− => Expression schema relations grouping params (nullity keysArray)
1165− -> Expression schema relations grouping params (nullity valuesArray)
1166− -> Expression schema relations grouping params (nullity 'PGjson)
1167−jsonZipObject ks vs =
1168− unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1169−
1170−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1171−-- keys and one for values, that are zipped pairwise to create a binary JSON
1172−-- object.
1173−jsonbZipObject
1174− :: ( PGarrayOf "jsonbZipObject" keysArray 'PGtext
1175− , PGarrayOf "jsonbZipObject" valuesArray 'PGtext)
1176− => Expression schema relations grouping params (nullity keysArray)
1177− -> Expression schema relations grouping params (nullity valuesArray)
1178− -> Expression schema relations grouping params (nullity 'PGjsonb)
1179−jsonbZipObject ks vs =
1180− unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1181−
1182−{-----------------------------------------
1183−Table 9.46: JSON processing functions
1184−-----------------------------------------}
1185−
1186−-- | Returns the number of elements in the outermost JSON array.
1187−jsonArrayLength
1188− :: Expression schema relations grouping params (nullity 'PGjson)
1189− -> Expression schema relations grouping params (nullity 'PGint4)
1190−jsonArrayLength = unsafeFunction "json_array_length"
1191−
1192−-- | Returns the number of elements in the outermost binary JSON array.
1193−jsonbArrayLength
1194− :: Expression schema relations grouping params (nullity 'PGjsonb)
1195− -> Expression schema relations grouping params (nullity 'PGint4)
1196−jsonbArrayLength = unsafeFunction "jsonb_array_length"
1197−
1198−jsonObjectKeys
1199− :: Expression schema relations grouping params (nullity 'PGjson)
1200− -> Expression schema relations grouping params (nullity 'PGtext)
1201−jsonObjectKeys = unsafeFunction "json_object_keys"
1202−
1203−jsonbObjectKeys
1204− :: Expression schema relations grouping params (nullity 'PGjsonb)
1205− -> Expression schema relations grouping params (nullity 'PGtext)
1206−jsonbObjectKeys = unsafeFunction "jsonb_object_keys"
1207−
1208−{-----------------------------------------
1209−aggregation
1210−-----------------------------------------}
1211−
1212−-- | escape hatch to define aggregate functions
1213−unsafeAggregate
1214− :: ByteString -- ^ aggregate function
1215− -> Expression schema relations 'Ungrouped params (xty)
1216− -> Expression schema relations ('Grouped bys) params (yty)
1217−unsafeAggregate fun x = UnsafeExpression $ mconcat
1218− [fun, "(", renderExpression x, ")"]
1219−
1220−-- | escape hatch to define aggregate functions over distinct values
1221−unsafeAggregateDistinct
1222− :: ByteString -- ^ aggregate function
1223− -> Expression schema relations 'Ungrouped params (xty)
1224− -> Expression schema relations ('Grouped bys) params (yty)
1225−unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
1226− [fun, "(DISTINCT ", renderExpression x, ")"]
1227−
1228−-- | >>> :{
1229−-- let
1230−-- expression :: Expression schema '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Grouped bys) params ('Null 'PGnumeric)
1231−-- expression = sum_ #col
1232−-- in printSQL expression
1233−-- :}
1234−-- sum("col")
1235−sum_
1236− :: PGNum ty
1237− => Expression schema relations 'Ungrouped params (nullity ty)
1238− -- ^ what to sum
1239− -> Expression schema relations ('Grouped bys) params (nullity ty)
1240−sum_ = unsafeAggregate "sum"
1241−
1242−-- | >>> :{
1243−-- let
1244−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGnumeric]] ('Grouped bys) params (nullity 'PGnumeric)
1245−-- expression = sumDistinct #col
1246−-- in printSQL expression
1247−-- :}
1248−-- sum(DISTINCT "col")
1249−sumDistinct
1250− :: PGNum ty
1251− => Expression schema relations 'Ungrouped params (nullity ty)
1252− -- ^ what to sum
1253− -> Expression schema relations ('Grouped bys) params (nullity ty)
1254−sumDistinct = unsafeAggregateDistinct "sum"
1255−
1256−-- | A constraint for `PGType`s that you can take averages of and the resulting
1257−-- `PGType`.
1258−class PGAvg ty avg | ty -> avg where
1259− avg, avgDistinct
1260− :: Expression schema relations 'Ungrouped params (nullity ty)
1261− -- ^ what to average
1262− -> Expression schema relations ('Grouped bys) params (nullity avg)
1263− avg = unsafeAggregate "avg"
1264− avgDistinct = unsafeAggregateDistinct "avg"
1265−instance PGAvg 'PGint2 'PGnumeric
1266−instance PGAvg 'PGint4 'PGnumeric
1267−instance PGAvg 'PGint8 'PGnumeric
1268−instance PGAvg 'PGnumeric 'PGnumeric
1269−instance PGAvg 'PGfloat4 'PGfloat8
1270−instance PGAvg 'PGfloat8 'PGfloat8
1271−instance PGAvg 'PGinterval 'PGinterval
1272−
1273−-- | >>> :{
1274−-- let
1275−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1276−-- expression = bitAnd #col
1277−-- in printSQL expression
1278−-- :}
1279−-- bit_and("col")
1280−bitAnd
1281− :: PGIntegral int
1282− => Expression schema relations 'Ungrouped params (nullity int)
1283− -- ^ what to aggregate
1284− -> Expression schema relations ('Grouped bys) params (nullity int)
1285−bitAnd = unsafeAggregate "bit_and"
1286−
1287−-- | >>> :{
1288−-- let
1289−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1290−-- expression = bitOr #col
1291−-- in printSQL expression
1292−-- :}
1293−-- bit_or("col")
1294−bitOr
1295− :: PGIntegral int
1296− => Expression schema relations 'Ungrouped params (nullity int)
1297− -- ^ what to aggregate
1298− -> Expression schema relations ('Grouped bys) params (nullity int)
1299−bitOr = unsafeAggregate "bit_or"
1300−
1301−-- | >>> :{
1302−-- let
1303−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1304−-- expression = bitAndDistinct #col
1305−-- in printSQL expression
1306−-- :}
1307−-- bit_and(DISTINCT "col")
1308−bitAndDistinct
1309− :: PGIntegral int
1310− => Expression schema relations 'Ungrouped params (nullity int)
1311− -- ^ what to aggregate
1312− -> Expression schema relations ('Grouped bys) params (nullity int)
1313−bitAndDistinct = unsafeAggregateDistinct "bit_and"
1314−
1315−-- | >>> :{
1316−-- let
1317−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
1318−-- expression = bitOrDistinct #col
1319−-- in printSQL expression
1320−-- :}
1321−-- bit_or(DISTINCT "col")
1322−bitOrDistinct
1323− :: PGIntegral int
1324− => Expression schema relations 'Ungrouped params (nullity int)
1325− -- ^ what to aggregate
1326− -> Expression schema relations ('Grouped bys) params (nullity int)
1327−bitOrDistinct = unsafeAggregateDistinct "bit_or"
1328−
1329−-- | >>> :{
1330−-- let
1331−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1332−-- expression = boolAnd #col
1333−-- in printSQL expression
1334−-- :}
1335−-- bool_and("col")
1336−boolAnd
1337− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1338− -- ^ what to aggregate
1339− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1340−boolAnd = unsafeAggregate "bool_and"
1341−
1342−-- | >>> :{
1343−-- let
1344−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1345−-- expression = boolOr #col
1346−-- in printSQL expression
1347−-- :}
1348−-- bool_or("col")
1349−boolOr
1350− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1351− -- ^ what to aggregate
1352− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1353−boolOr = unsafeAggregate "bool_or"
1354−
1355−-- | >>> :{
1356−-- let
1357−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1358−-- expression = boolAndDistinct #col
1359−-- in printSQL expression
1360−-- :}
1361−-- bool_and(DISTINCT "col")
1362−boolAndDistinct
1363− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1364− -- ^ what to aggregate
1365− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1366−boolAndDistinct = unsafeAggregateDistinct "bool_and"
1367−
1368−-- | >>> :{
1369−-- let
1370−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1371−-- expression = boolOrDistinct #col
1372−-- in printSQL expression
1373−-- :}
1374−-- bool_or(DISTINCT "col")
1375−boolOrDistinct
1376− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1377− -- ^ what to aggregate
1378− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1379−boolOrDistinct = unsafeAggregateDistinct "bool_or"
1380−
1381−-- | A special aggregation that does not require an input
1382−--
1383−-- >>> printSQL countStar
1384−-- count(*)
1385−countStar
1386− :: Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1387−countStar = UnsafeExpression $ "count(*)"
1388−
1389−-- | >>> :{
1390−-- let
1391−-- expression :: Expression schema '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
1392−-- expression = count #col
1393−-- in printSQL expression
1394−-- :}
1395−-- count("col")
1396−count
1397− :: Expression schema relations 'Ungrouped params ty
1398− -- ^ what to count
1399− -> Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1400−count = unsafeAggregate "count"
1401−
1402−-- | >>> :{
1403−-- let
1404−-- expression :: Expression schema '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
1405−-- expression = countDistinct #col
1406−-- in printSQL expression
1407−-- :}
1408−-- count(DISTINCT "col")
1409−countDistinct
1410− :: Expression schema relations 'Ungrouped params ty
1411− -- ^ what to count
1412− -> Expression schema relations ('Grouped bys) params ('NotNull 'PGint8)
1413−countDistinct = unsafeAggregateDistinct "count"
1414−
1415−-- | synonym for `boolAnd`
1416−--
1417−-- >>> :{
1418−-- let
1419−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1420−-- expression = every #col
1421−-- in printSQL expression
1422−-- :}
1423−-- every("col")
1424−every
1425− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1426− -- ^ what to aggregate
1427− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1428−every = unsafeAggregate "every"
1429−
1430−-- | synonym for `boolAndDistinct`
1431−--
1432−-- >>> :{
1433−-- let
1434−-- expression :: Expression schema '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1435−-- expression = everyDistinct #col
1436−-- in printSQL expression
1437−-- :}
1438−-- every(DISTINCT "col")
1439−everyDistinct
1440− :: Expression schema relations 'Ungrouped params (nullity 'PGbool)
1441− -- ^ what to aggregate
1442− -> Expression schema relations ('Grouped bys) params (nullity 'PGbool)
1443−everyDistinct = unsafeAggregateDistinct "every"
1444−
1445−-- | minimum and maximum aggregation
1446−max_, min_, maxDistinct, minDistinct
1447− :: Expression schema relations 'Ungrouped params (nullity ty)
1448− -- ^ what to aggregate
1449− -> Expression schema relations ('Grouped bys) params (nullity ty)
1450−max_ = unsafeAggregate "max"
1451−min_ = unsafeAggregate "min"
1452−maxDistinct = unsafeAggregateDistinct "max"
1453−minDistinct = unsafeAggregateDistinct "min"
1454−
1455−{-----------------------------------------
1456−type expressions
1457−-----------------------------------------}
1458−
1459−-- | `TypeExpression`s are used in `cast`s and `createTable` commands.
1460−newtype TypeExpression (schema :: SchemaType) (ty :: PGType)
1461− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1462− deriving (GHC.Generic,Show,Eq,Ord,NFData)
1463−
1464−instance (Has alias schema ('Typedef ty))
1465− => IsLabel alias (TypeExpression schema ty) where
1466− fromLabel = UnsafeTypeExpression (renderAlias (fromLabel @alias))
1467−
1468−-- | logical Boolean (true/false)
1469−bool :: TypeExpression schema 'PGbool
1470−bool = UnsafeTypeExpression "bool"
1471−-- | signed two-byte integer
1472−int2, smallint :: TypeExpression schema 'PGint2
1473−int2 = UnsafeTypeExpression "int2"
1474−smallint = UnsafeTypeExpression "smallint"
1475−-- | signed four-byte integer
1476−int4, int, integer :: TypeExpression schema 'PGint4
1477−int4 = UnsafeTypeExpression "int4"
1478−int = UnsafeTypeExpression "int"
1479−integer = UnsafeTypeExpression "integer"
1480−-- | signed eight-byte integer
1481−int8, bigint :: TypeExpression schema 'PGint8
1482−int8 = UnsafeTypeExpression "int8"
1483−bigint = UnsafeTypeExpression "bigint"
1484−-- | arbitrary precision numeric type
1485−numeric :: TypeExpression schema 'PGnumeric
1486−numeric = UnsafeTypeExpression "numeric"
1487−-- | single precision floating-point number (4 bytes)
1488−float4, real :: TypeExpression schema 'PGfloat4
1489−float4 = UnsafeTypeExpression "float4"
1490−real = UnsafeTypeExpression "real"
1491−-- | double precision floating-point number (8 bytes)
1492−float8, doublePrecision :: TypeExpression schema 'PGfloat8
1493−float8 = UnsafeTypeExpression "float8"
1494−doublePrecision = UnsafeTypeExpression "double precision"
1495−-- | variable-length character string
1496−text :: TypeExpression schema 'PGtext
1497−text = UnsafeTypeExpression "text"
1498−-- | fixed-length character string
1499−char, character
1500− :: (KnownNat n, 1 <= n)
1501− => proxy n
1502− -> TypeExpression schema ('PGchar n)
1503−char p = UnsafeTypeExpression $ "char(" <> renderNat p <> ")"
1504−character p = UnsafeTypeExpression $ "character(" <> renderNat p <> ")"
1505−-- | variable-length character string
1506−varchar, characterVarying
1507− :: (KnownNat n, 1 <= n)
1508− => proxy n
1509− -> TypeExpression schema ('PGvarchar n)
1510−varchar p = UnsafeTypeExpression $ "varchar(" <> renderNat p <> ")"
1511−characterVarying p = UnsafeTypeExpression $
1512− "character varying(" <> renderNat p <> ")"
1513−-- | binary data ("byte array")
1514−bytea :: TypeExpression schema 'PGbytea
1515−bytea = UnsafeTypeExpression "bytea"
1516−-- | date and time (no time zone)
1517−timestamp :: TypeExpression schema 'PGtimestamp
1518−timestamp = UnsafeTypeExpression "timestamp"
1519−-- | date and time, including time zone
1520−timestampWithTimeZone :: TypeExpression schema 'PGtimestamptz
1521−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1522−-- | calendar date (year, month, day)
1523−date :: TypeExpression schema 'PGdate
1524−date = UnsafeTypeExpression "date"
1525−-- | time of day (no time zone)
1526−time :: TypeExpression schema 'PGtime
1527−time = UnsafeTypeExpression "time"
1528−-- | time of day, including time zone
1529−timeWithTimeZone :: TypeExpression schema 'PGtimetz
1530−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1531−-- | time span
1532−interval :: TypeExpression schema 'PGinterval
1533−interval = UnsafeTypeExpression "interval"
1534−-- | universally unique identifier
1535−uuid :: TypeExpression schema 'PGuuid
1536−uuid = UnsafeTypeExpression "uuid"
1537−-- | IPv4 or IPv6 host address
1538−inet :: TypeExpression schema 'PGinet
1539−inet = UnsafeTypeExpression "inet"
1540−-- | textual JSON data
1541−json :: TypeExpression schema 'PGjson
1542−json = UnsafeTypeExpression "json"
1543−-- | binary JSON data, decomposed
1544−jsonb :: TypeExpression schema 'PGjsonb
1545−jsonb = UnsafeTypeExpression "jsonb"
1546−-- | variable length array
1547−vararray
1548− :: TypeExpression schema pg
1549− -> TypeExpression schema ('PGvararray pg)
1550−vararray ty = UnsafeTypeExpression $ renderTypeExpression ty <> "[]"
1551−-- | fixed length array
1552−--
1553−-- >>> renderTypeExpression (fixarray (Proxy @2) json)
1554−-- "json[2]"
1555−fixarray
1556− :: KnownNat n
1557− => proxy n
1558− -> TypeExpression schema pg
1559− -> TypeExpression schema ('PGfixarray n pg)
1560−fixarray p ty = UnsafeTypeExpression $
1561− renderTypeExpression ty <> "[" <> renderNat p <> "]"
1562−
1563−-- | `pgtype` is a demoted version of a `PGType`
1564−class PGTyped schema (ty :: PGType) where pgtype :: TypeExpression schema ty
1565−instance PGTyped schema 'PGbool where pgtype = bool
1566−instance PGTyped schema 'PGint2 where pgtype = int2
1567−instance PGTyped schema 'PGint4 where pgtype = int4
1568−instance PGTyped schema 'PGint8 where pgtype = int8
1569−instance PGTyped schema 'PGnumeric where pgtype = numeric
1570−instance PGTyped schema 'PGfloat4 where pgtype = float4
1571−instance PGTyped schema 'PGfloat8 where pgtype = float8
1572−instance PGTyped schema 'PGtext where pgtype = text
1573−instance (KnownNat n, 1 <= n)
1574− => PGTyped schema ('PGchar n) where pgtype = char (Proxy @n)
1575−instance (KnownNat n, 1 <= n)
1576− => PGTyped schema ('PGvarchar n) where pgtype = varchar (Proxy @n)
1577−instance PGTyped schema 'PGbytea where pgtype = bytea
1578−instance PGTyped schema 'PGtimestamp where pgtype = timestamp
1579−instance PGTyped schema 'PGtimestamptz where pgtype = timestampWithTimeZone
1580−instance PGTyped schema 'PGdate where pgtype = date
1581−instance PGTyped schema 'PGtime where pgtype = time
1582−instance PGTyped schema 'PGtimetz where pgtype = timeWithTimeZone
1583−instance PGTyped schema 'PGinterval where pgtype = interval
1584−instance PGTyped schema 'PGuuid where pgtype = uuid
1585−instance PGTyped schema 'PGjson where pgtype = json
1586−instance PGTyped schema 'PGjsonb where pgtype = jsonb
1587−instance PGTyped schema ty => PGTyped schema ('PGvararray ty) where
1588− pgtype = vararray (pgtype @schema @ty)
1589−instance (KnownNat n, PGTyped schema ty) => PGTyped schema ('PGfixarray n ty) where
1590− pgtype = fixarray (Proxy @n) (pgtype @schema @ty)