@@ -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
@@ -32,547 +33,350 @@ Squeal expressions are the atoms used to build statements.
3233module Squeal.PostgreSQL.Expression
3334 ( -- * Expression
3435 Expression (..)
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− , index
49− , row
50− , field
51− -- ** Functions
52− , unsafeBinaryOp
53− , unsafeUnaryOp
36+ , Expr
37+ , type (-->)
38+ , FunctionDB
5439 , unsafeFunction
55− , unsafeVariadicFunction
56− , atan2_
57− , cast
58− , quot_
59− , rem_
60− , trunc
61− , round_
62− , ceiling_
63− , greatest
64− , least
65− -- ** Conditions
66− , true
67− , false
68− , not_
69− , (.&&)
70− , (.||)
71− , Condition
72− , caseWhenThenElse
73− , ifThenElse
74− , (.==)
75− , (./=)
76− , (.>=)
77− , (.<)
78− , (.<=)
79− , (.>)
80− -- ** Time
81− , currentDate
82− , currentTime
83− , currentTimestamp
84− , localTime
85− , localTimestamp
86− -- ** Text
87− , lower
88− , upper
89− , charLength
90− , like
91− , ilike
92− -- ** Json
93− -- *** Json and Jsonb operators
94− , (.->)
95− , (.->>)
96− , (.#>)
97− , (.#>>)
98− -- *** Jsonb operators
99− , (.@>)
100− , (.<@)
101− , (.?)
102− , (.?|)
103− , (.?&)
104− , (.-.)
105− , (#-.)
106− -- *** Functions
107− , jsonLit
108− , jsonbLit
109− , toJson
110− , toJsonb
111− , arrayToJson
112− , rowToJson
113− , jsonBuildArray
114− , jsonbBuildArray
115− , jsonBuildObject
116− , jsonbBuildObject
117− , jsonObject
118− , jsonbObject
119− , jsonZipObject
120− , jsonbZipObject
121− , jsonArrayLength
122− , jsonbArrayLength
123− , jsonExtractPath
124− , jsonbExtractPath
125− , jsonExtractPathAsText
126− , jsonbExtractPathAsText
127− , jsonTypeof
128− , jsonbTypeof
129− , jsonStripNulls
130− , jsonbStripNulls
131− , jsonbSet
132− , jsonbInsert
133− , jsonbPretty
134− -- ** Aggregation
135− , unsafeAggregate, unsafeAggregateDistinct
136− , sum_, sumDistinct
137− , PGAvg (avg, avgDistinct)
138− , bitAnd, bitOr, boolAnd, boolOr
139− , bitAndDistinct, bitOrDistinct, boolAndDistinct, boolOrDistinct
140− , countStar
141− , count, countDistinct
142− , every, everyDistinct
143− , max_, maxDistinct, min_, minDistinct
144− -- * Types
145− , TypeExpression (..)
146− , PGTyped (..)
147− , typedef
148− , typetable
149− , typeview
150− , bool
151− , int2
152− , smallint
153− , int4
154− , int
155− , integer
156− , int8
157− , bigint
158− , numeric
159− , float4
160− , real
161− , float8
162− , doublePrecision
163− , text
164− , char
165− , character
166− , varchar
167− , characterVarying
168− , bytea
169− , timestamp
170− , timestampWithTimeZone
171− , date
172− , time
173− , timeWithTimeZone
174− , interval
175− , uuid
176− , inet
177− , json
178− , jsonb
179− , vararray
180− , 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 (..)
18157 -- * Re-export
18258 , (&)
183− , NP ((:*), Nil)
59+ , K (..)
60+ , unK
18461 ) where
18562
18663import Control.Category
18764import Control.DeepSeq
18865import Data.ByteString (ByteString)
189−import Data.ByteString.Lazy (toStrict)
19066import Data.Function ((&))
19167import Data.Semigroup hiding (All)
192−import qualified Data.Aeson as JSON
193−import Data.Ratio
19468import Data.String
195−import Data.Word
196−import Generics.SOP hiding (from)
69+import Generics.SOP hiding (All, from)
19770import GHC.OverloadedLabels
19871import GHC.TypeLits
72+import Numeric
19973import Prelude hiding (id, (.))
20074
201−import qualified Data.ByteString as ByteString
20275import qualified GHC.Generics as GHC
20376
77+import Squeal.PostgreSQL.Alias
78+import Squeal.PostgreSQL.List
20479import Squeal.PostgreSQL.Render
20580import Squeal.PostgreSQL.Schema
20681
82+-- $setup
83+-- >>> import Squeal.PostgreSQL
84+
20785{-----------------------------------------
20886column expressions
20987-----------------------------------------}
21088
21189{- | `Expression`s are used in a variety of contexts,
212−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,
21392as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
21493`Squeal.PostgreSQL.Manipulation.update`,
215−or in search `Condition`s in a number of commands.
94+or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
21695
21796The expression syntax allows the calculation of
21897values from primitive expression using arithmetic, logical,
21998and 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`.
220113-}
221114newtype Expression
115+ (outer :: FromType)
222116 (commons :: FromType)
117+ (grp :: Grouping)
223118 (schemas :: SchemasType)
224119 (params :: [NullityType])
225− (grp :: Grouping)
226120 (from :: FromType)
227121 (ty :: NullityType)
228122 = UnsafeExpression { renderExpression :: ByteString }
229123 deriving (GHC.Generic,Show,Eq,Ord,NFData)
230−
231−instance RenderSQL (Expression commons schemas params grp from ty) where
124+instance RenderSQL (Expression outer commons grp schemas params from ty) where
232125 renderSQL = renderExpression
233126
234−{- | A `HasParameter` constraint is used to indicate a value that is
235−supplied externally to a SQL statement.
236−`Squeal.PostgreSQL.PQ.manipulateParams`,
237−`Squeal.PostgreSQL.PQ.queryParams` and
238−`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
239−separately from the SQL command string, in which case `param`s are used to
240−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)
241181-}
242−class KnownNat n => HasParameter
243− (n :: Nat)
244− (params :: [NullityType])
245− (ty :: NullityType)
246− | n params -> ty where
247− -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
248− --
249− -- >>> let expr = parameter @1 int4 :: Expression '[] schemas '[ 'Null 'PGint4] grp from ('Null 'PGint4)
250− -- >>> printSQL expr
251− -- ($1 :: int4)
252− parameter
253− :: TypeExpression schemas ty
254− -> Expression commons schemas params grp from ty
255− parameter ty = UnsafeExpression $ parenthesized $
256− "$" <> renderNat @n <+> "::"
257− <+> renderSQL ty
258−instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
259−instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
260− => HasParameter n (ty' : params) ty
261−
262−-- | `param` takes a `Nat` using type application and for basic types,
263−-- infers a `TypeExpression`.
264−--
265−-- >>> let expr = param @1 :: Expression commons schemas '[ 'Null 'PGint4] grp from ('Null 'PGint4)
266−-- >>> printSQL expr
267−-- ($1 :: int4)
268−param
269− :: forall n commons schemas params from grp ty
270− . (PGTyped schemas ty, HasParameter n params ty)
271− => Expression commons schemas params grp from ty -- ^ param
272−param = parameter @n (pgtype @schemas)
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)
273214
274−instance (HasUnique tab from row, Has col row ty)
275− => IsLabel col (Expression commons schemas params 'Ungrouped from ty) where
215+instance (HasUnique tab (Join outer from) row, Has col row ty)
216+ => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
276217 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
277−instance (HasUnique tab from row, Has col row ty, column ~ (col ::: ty))
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))
278222 => IsLabel col
279− (Aliased (Expression commons schemas params 'Ungrouped from) column) where
223+ (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
280224 fromLabel = fromLabel @col `As` Alias
281−instance (HasUnique tab from row, Has col row ty, columns ~ '[col ::: ty])
225+instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
282226 => IsLabel col
283− (NP (Aliased (Expression commons schemas params 'Ungrouped from)) columns) where
227+ (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
284228 fromLabel = fromLabel @col :* Nil
285229
286−instance (Has tab from row, Has col row ty)
287− => IsQualified tab col (Expression commons schemas params 'Ungrouped from ty) where
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
288232 tab ! col = UnsafeExpression $
289233 renderSQL tab <> "." <> renderSQL col
290−instance (Has tab from row, Has col row ty, column ~ (col ::: ty))
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))
291238 => IsQualified tab col
292− (Aliased (Expression commons schemas params 'Ungrouped from) column) where
239+ (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
293240 tab ! col = tab ! col `As` col
294−instance (Has tab from row, Has col row ty, columns ~ '[col ::: ty])
241+instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
295242 => IsQualified tab col
296− (NP (Aliased (Expression commons schemas params 'Ungrouped from)) columns) where
243+ (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
297244 tab ! col = tab ! col :* Nil
298245
299246instance
300− ( HasUnique tab from row
247+ ( HasUnique tab (Join outer from) row
301248 , Has col row ty
302249 , GroupedBy tab col bys
303250 ) => IsLabel col
304− (Expression commons schemas params ('Grouped bys) from ty) where
251+ (Expression outer commons ('Grouped bys) schemas params from ty) where
305252 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
306253instance
307− ( HasUnique tab from row
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
261+instance
262+ ( HasUnique tab (Join outer from) row
308263 , Has col row ty
309264 , GroupedBy tab col bys
310265 , column ~ (col ::: ty)
311266 ) => IsLabel col
312− (Aliased (Expression commons schemas params ('Grouped bys) from) column) where
267+ (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
313268 fromLabel = fromLabel @col `As` Alias
314269instance
315− ( HasUnique tab from row
270+ ( HasUnique tab (Join outer from) row
316271 , Has col row ty
317272 , GroupedBy tab col bys
318273 , columns ~ '[col ::: ty]
319274 ) => IsLabel col
320− (NP (Aliased (Expression commons schemas params ('Grouped bys) from)) columns) where
275+ (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
321276 fromLabel = fromLabel @col :* Nil
322277
323278instance
324− ( Has tab from row
279+ ( Has tab (Join outer from) row
325280 , Has col row ty
326281 , GroupedBy tab col bys
327282 ) => IsQualified tab col
328− (Expression commons schemas params ('Grouped bys) from ty) where
283+ (Expression outer commons ('Grouped bys) schemas params from ty) where
329284 tab ! col = UnsafeExpression $
330285 renderSQL tab <> "." <> renderSQL col
331286instance
332− ( Has tab from row
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
294+instance
295+ ( Has tab (Join outer from) row
333296 , Has col row ty
334297 , GroupedBy tab col bys
335298 , column ~ (col ::: ty)
336299 ) => IsQualified tab col
337− (Aliased (Expression commons schemas params ('Grouped bys) from) column) where
300+ (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
338301 tab ! col = tab ! col `As` col
339302instance
340− ( Has tab from row
303+ ( Has tab (Join outer from) row
341304 , Has col row ty
342305 , GroupedBy tab col bys
343306 , columns ~ '[col ::: ty]
344307 ) => IsQualified tab col
345− (NP (Aliased (Expression commons schemas params ('Grouped bys) from)) columns) where
308+ (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
346309 tab ! col = tab ! col :* Nil
347310
348−-- | analagous to `Nothing`
349−--
350−-- >>> printSQL null_
351−-- NULL
352−null_ :: Expression commons schemas rels grouping params ('Null ty)
353−null_ = UnsafeExpression "NULL"
354−
355−-- | analagous to `Just`
356−--
357−-- >>> printSQL $ notNull true
358−-- TRUE
359−notNull
360− :: Expression commons schemas rels grouping params ('NotNull ty)
361− -> Expression commons schemas rels grouping params ('Null ty)
362−notNull = UnsafeExpression . renderSQL
363−
364−-- | return the leftmost value which is not NULL
365−--
366−-- >>> printSQL $ coalesce [null_, true] false
367−-- COALESCE(NULL, TRUE, FALSE)
368−coalesce
369− :: [Expression commons schemas params grp from ('Null ty)]
370− -- ^ @NULL@s may be present
371− -> Expression commons schemas params grp from ('NotNull ty)
372− -- ^ @NULL@ is absent
373− -> Expression commons schemas params grp from ('NotNull ty)
374−coalesce nullxs notNullx = UnsafeExpression $
375− "COALESCE" <> parenthesized (commaSeparated
376− ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
377−
378−-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
379−--
380−-- >>> printSQL $ fromNull true null_
381−-- COALESCE(NULL, TRUE)
382−fromNull
383− :: Expression commons schemas params grp from ('NotNull ty)
384− -- ^ what to convert @NULL@ to
385− -> Expression commons schemas params grp from ('Null ty)
386− -> Expression commons schemas params grp from ('NotNull ty)
387−fromNull notNullx nullx = coalesce [nullx] notNullx
388−
389−-- | >>> printSQL $ null_ & isNull
390−-- NULL IS NULL
391−isNull
392− :: Expression commons schemas params grp from ('Null ty)
393− -- ^ possibly @NULL@
394− -> Condition commons schemas params grp from
395−isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
396−
397−-- | >>> printSQL $ null_ & isNotNull
398−-- NULL IS NOT NULL
399−isNotNull
400− :: Expression commons schemas params grp from ('Null ty)
401− -- ^ possibly @NULL@
402− -> Condition commons schemas params grp from
403−isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
404−
405−-- | analagous to `maybe` using @IS NULL@
406−--
407−-- >>> printSQL $ matchNull true not_ null_
408−-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
409−matchNull
410− :: Expression commons schemas params grp from (nullty)
411− -- ^ what to convert @NULL@ to
412− -> ( Expression commons schemas params grp from ('NotNull ty)
413− -> Expression commons schemas params grp from (nullty) )
414− -- ^ function to perform when @NULL@ is absent
415− -> Expression commons schemas params grp from ('Null ty)
416− -> Expression commons schemas params grp from (nullty)
417−matchNull y f x = ifThenElse (isNull x) y
418− (f (UnsafeExpression (renderSQL x)))
419−
420−{-| right inverse to `fromNull`, if its arguments are equal then
421−`nullIf` gives @NULL@.
422−
423−>>> :set -XTypeApplications -XDataKinds
424−>>> let expr = nullIf false (param @1) :: Expression commons schemas '[ 'NotNull 'PGbool] grp from ('Null 'PGbool)
425−>>> printSQL expr
426−NULL IF (FALSE, ($1 :: bool))
427−-}
428−nullIf
429− :: Expression commons schemas params grp from ('NotNull ty)
430− -- ^ @NULL@ is absent
431− -> Expression commons schemas params grp from ('NotNull ty)
432− -- ^ @NULL@ is absent
433− -> Expression commons schemas params grp from ('Null ty)
434−nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
435− (renderSQL x <> ", " <> renderSQL y)
436−
437−-- | >>> printSQL $ array [null_, false, true]
438−-- ARRAY[NULL, FALSE, TRUE]
439−array
440− :: [Expression commons schemas params grp from ty]
441− -- ^ array elements
442− -> Expression commons schemas params grp from (nullity ('PGvararray ty))
443−array xs = UnsafeExpression $
444− "ARRAY[" <> commaSeparated (renderSQL <$> xs) <> "]"
445−
446−-- | >>> printSQL $ array [null_, false, true] & index 2
447−-- (ARRAY[NULL, FALSE, TRUE])[2]
448−index
449− :: Word64 -- ^ index
450− -> Expression commons schemas params grp from (nullity ('PGvararray ty)) -- ^ array
451− -> Expression commons schemas params grp from (NullifyType ty)
452−index n expr = UnsafeExpression $
453− parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
454−
455311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
456− (Expression commons schemas params grp from (nullity ('PGenum labels))) where
312+ (Expression outer commons grp schemas params from (null ('PGenum labels))) where
457313 label = UnsafeExpression $ renderSQL (PGlabel @label)
458314
459−-- | A row constructor is an expression that builds a row value
460−-- (also called a composite value) using values for its member fields.
461−--
462−-- >>> :{
463−-- type Complex = 'PGcomposite
464−-- '[ "real" ::: 'NotNull 'PGfloat8
465−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
466−-- :}
467−--
468−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression commons schemas from grp params ('NotNull Complex)
469−-- >>> printSQL i
470−-- ROW(0, 1)
471−row
472− :: SListI row
473− => NP (Aliased (Expression commons schemas params grp from)) row
474− -- ^ zero or more expressions for the row field values
475− -> Expression commons schemas params grp from (nullity ('PGcomposite row))
476−row exprs = UnsafeExpression $ "ROW" <> parenthesized
477− (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
478−
479−-- | >>> :{
480−-- type Complex = 'PGcomposite
481−-- '[ "real" ::: 'NotNull 'PGfloat8
482−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
483−-- type Schema = '["complex" ::: 'Typedef Complex]
484−-- :}
485−--
486−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression '[] (Public Schema) from grp params ('NotNull Complex)
487−-- >>> printSQL $ i & field #complex #imaginary
488−-- (ROW(0, 1)::"complex")."imaginary"
489−field
490− :: ( Has sch schemas schema
491− , Has tydef schema ('Typedef ('PGcomposite row))
492− , Has field row ty)
493− => QualifiedAlias sch tydef -- ^ row type
494− -> Alias field -- ^ field name
495− -> Expression commons schemas params grp from ('NotNull ('PGcomposite row))
496− -> Expression commons schemas params grp from ty
497−field td fld expr = UnsafeExpression $
498− parenthesized (renderSQL expr <> "::" <> renderSQL td)
499− <> "." <> renderSQL fld
500−
501−instance Semigroup
502− (Expression commons schemas params grp from (nullity ('PGvararray ty))) where
503− (<>) = unsafeBinaryOp "||"
504−
505−instance Monoid
506− (Expression commons schemas params grp from (nullity ('PGvararray ty))) where
507− mempty = array []
508− mappend = (<>)
509−
510−-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression commons schemas '[ 'NotNull 'PGtimestamptz] grp from ('NotNull 'PGtimestamptz)
511−-- >>> printSQL expr
512−-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
513−greatest
514− :: Expression commons schemas params grp from (nullty)
515− -- ^ needs at least 1 argument
516− -> [Expression commons schemas params grp from (nullty)]
517− -- ^ or more
518− -> Expression commons schemas params grp from (nullty)
519−greatest x xs = UnsafeExpression $ "GREATEST("
520− <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
521−
522−-- | >>> printSQL $ least currentTimestamp [null_]
523−-- LEAST(CURRENT_TIMESTAMP, NULL)
524−least
525− :: Expression commons schemas params grp from (nullty)
526− -- ^ needs at least 1 argument
527− -> [Expression commons schemas params grp from (nullty)]
528− -- ^ or more
529− -> Expression commons schemas params grp from (nullty)
530−least x xs = UnsafeExpression $ "LEAST("
531− <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
532−
533315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
534316-- (TRUE OR FALSE)
535−unsafeBinaryOp
536− :: ByteString
537− -- ^ operator
538− -> Expression commons schemas params grp from (ty0)
539− -> Expression commons schemas params grp from (ty1)
540− -> Expression commons schemas params grp from (ty2)
317+unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
541318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
542319 renderSQL x <+> op <+> renderSQL y
543320
544−-- | >>> 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
545329-- (NOT TRUE)
546−unsafeUnaryOp
547− :: ByteString
548− -- ^ operator
549− -> Expression commons schemas params grp from (ty0)
550− -> Expression commons schemas params grp from (ty1)
551−unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
552− op <+> renderSQL 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
553351
554352-- | >>> printSQL $ unsafeFunction "f" true
555353-- f(TRUE)
556−unsafeFunction
557− :: ByteString
558− -- ^ function
559− -> Expression commons schemas params grp from (xty)
560− -> Expression commons schemas params grp from (yty)
354+unsafeFunction :: ByteString -> x --> y
561355unsafeFunction fun x = UnsafeExpression $
562356 fun <> parenthesized (renderSQL x)
563357
564−-- | Helper for defining variadic functions.
565−unsafeVariadicFunction
566− :: SListI elems
567− => ByteString
568− -- ^ function
569− -> NP (Expression commons schemas params grp from) elems
570− -> Expression commons schemas params grp from ret
571−unsafeVariadicFunction fun x = UnsafeExpression $
572− fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderSQL) x)))
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
573377
574378instance ty `In` PGNum
575− => Num (Expression commons schemas params grp from (nullity ty)) where
379+ => Num (Expression outer commons grp schemas params from (null ty)) where
576380 (+) = unsafeBinaryOp "+"
577381 (-) = unsafeBinaryOp "-"
578382 (*) = unsafeBinaryOp "*"
@@ -584,12 +388,17 @@ instance ty `In` PGNum
584388 . show
585389
586390instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
587− (Expression commons schemas params grp from (nullity ty)) where
391+ (Expression outer commons grp schemas params from (null ty)) where
588392 (/) = unsafeBinaryOp "/"
589− fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
393+ fromRational
394+ = UnsafeExpression
395+ . fromString
396+ . ($ "")
397+ . showFFloat Nothing
398+ . fromRat @Double
590399
591400instance (ty `In` PGNum, ty `In` PGFloating) => Floating
592− (Expression commons schemas params grp from (nullity ty)) where
401+ (Expression outer commons grp schemas params from (null ty)) where
593402 pi = UnsafeExpression "pi()"
594403 exp = unsafeFunction "exp"
595404 log = unsafeFunction "ln"
@@ -610,1182 +419,54 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
610419 acosh x = log (x + sqrt (x*x - 1))
611420 atanh x = log ((1 + x) / (1 - x)) / 2
612421
613−-- | >>> :{
614−-- let
615−-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
616−-- expression = atan2_ pi 2
617−-- in printSQL expression
618−-- :}
619−-- atan2(pi(), 2)
620−atan2_
621− :: float `In` PGFloating
622− => Expression commons schemas params grp from (nullity float)
623− -- ^ numerator
624− -> Expression commons schemas params grp from (nullity float)
625− -- ^ denominator
626− -> Expression commons schemas params grp from (nullity float)
627−atan2_ y x = UnsafeExpression $
628− "atan2(" <> renderSQL y <> ", " <> renderSQL x <> ")"
629−
630−-- When a `cast` is applied to an `Expression` of a known type, it
631−-- represents a run-time type conversion. The cast will succeed only if a
632−-- suitable type conversion operation has been defined.
633−--
634−-- | >>> printSQL $ true & cast int4
635−-- (TRUE :: int4)
636−cast
637− :: TypeExpression schemas ty1
638− -- ^ type to cast as
639− -> Expression commons schemas params grp from ty0
640− -- ^ value to convert
641− -> Expression commons schemas params grp from ty1
642−cast ty x = UnsafeExpression $ parenthesized $
643− renderSQL x <+> "::" <+> renderSQL ty
644−
645−-- | integer division, truncates the result
646−--
647−-- >>> :{
648−-- let
649−-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
650−-- expression = 5 `quot_` 2
651−-- in printSQL expression
652−-- :}
653−-- (5 / 2)
654−quot_
655− :: int `In` PGIntegral
656− => Expression commons schemas params grp from (nullity int)
657− -- ^ numerator
658− -> Expression commons schemas params grp from (nullity int)
659− -- ^ denominator
660− -> Expression commons schemas params grp from (nullity int)
661−quot_ = unsafeBinaryOp "/"
662−
663−-- | remainder upon integer division
664−--
665−-- >>> :{
666−-- let
667−-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
668−-- expression = 5 `rem_` 2
669−-- in printSQL expression
670−-- :}
671−-- (5 % 2)
672−rem_
673− :: int `In` PGIntegral
674− => Expression commons schemas params grp from (nullity int)
675− -- ^ numerator
676− -> Expression commons schemas params grp from (nullity int)
677− -- ^ denominator
678− -> Expression commons schemas params grp from (nullity int)
679−rem_ = unsafeBinaryOp "%"
680−
681−-- | >>> :{
682−-- let
683−-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
684−-- expression = trunc pi
685−-- in printSQL expression
686−-- :}
687−-- trunc(pi())
688−trunc
689− :: frac `In` PGFloating
690− => Expression commons schemas params grp from (nullity frac)
691− -- ^ fractional number
692− -> Expression commons schemas params grp from (nullity frac)
693−trunc = unsafeFunction "trunc"
694−
695−-- | >>> :{
696−-- let
697−-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
698−-- expression = round_ pi
699−-- in printSQL expression
700−-- :}
701−-- round(pi())
702−round_
703− :: frac `In` PGFloating
704− => Expression commons schemas params grp from (nullity frac)
705− -- ^ fractional number
706− -> Expression commons schemas params grp from (nullity frac)
707−round_ = unsafeFunction "round"
708−
709−-- | >>> :{
710−-- let
711−-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
712−-- expression = ceiling_ pi
713−-- in printSQL expression
714−-- :}
715−-- ceiling(pi())
716−ceiling_
717− :: frac `In` PGFloating
718− => Expression commons schemas params grp from (nullity frac)
719− -- ^ fractional number
720− -> Expression commons schemas params grp from (nullity frac)
721−ceiling_ = unsafeFunction "ceiling"
722−
723−-- | A `Condition` is an `Expression`, which can evaluate
724−-- to `true`, `false` or `null_`. This is because SQL uses
725−-- a three valued logic.
726−type Condition commons schemas params grp from =
727− Expression commons schemas params grp from ('Null 'PGbool)
728−
729−-- | >>> printSQL true
730−-- TRUE
731−true :: Expression commons schemas params grp from (nullity 'PGbool)
732−true = UnsafeExpression "TRUE"
733−
734−-- | >>> printSQL false
735−-- FALSE
736−false :: Expression commons schemas params grp from (nullity 'PGbool)
737−false = UnsafeExpression "FALSE"
738−
739−-- | >>> printSQL $ not_ true
740−-- (NOT TRUE)
741−not_
742− :: Expression commons schemas params grp from (nullity 'PGbool)
743− -> Expression commons schemas params grp from (nullity 'PGbool)
744−not_ = unsafeUnaryOp "NOT"
745−
746−-- | >>> printSQL $ true .&& false
747−-- (TRUE AND FALSE)
748−(.&&)
749− :: Expression commons schemas params grp from (nullity 'PGbool)
750− -> Expression commons schemas params grp from (nullity 'PGbool)
751− -> Expression commons schemas params grp from (nullity 'PGbool)
752−infixr 3 .&&
753−(.&&) = unsafeBinaryOp "AND"
754−
755−-- | >>> printSQL $ true .|| false
756−-- (TRUE OR FALSE)
757−(.||)
758− :: Expression commons schemas params grp from (nullity 'PGbool)
759− -> Expression commons schemas params grp from (nullity 'PGbool)
760− -> Expression commons schemas params grp from (nullity 'PGbool)
761−infixr 2 .||
762−(.||) = unsafeBinaryOp "OR"
763−
764−-- | >>> :{
765−-- let
766−-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
767−-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
768−-- in printSQL expression
769−-- :}
770−-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
771−caseWhenThenElse
772− :: [ ( Condition commons schemas params grp from
773− , Expression commons schemas params grp from ty
774− ) ]
775− -- ^ whens and thens
776− -> Expression commons schemas params grp from ty
777− -- ^ else
778− -> Expression commons schemas params grp from ty
779−caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
780− [ "CASE"
781− , mconcat
782− [ mconcat
783− [ " WHEN ", renderSQL when_
784− , " THEN ", renderSQL then_
785− ]
786− | (when_,then_) <- whenThens
787− ]
788− , " ELSE ", renderSQL else_
789− , " END"
790− ]
791−
792−-- | >>> :{
793−-- let
794−-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
795−-- expression = ifThenElse true 1 0
796−-- in printSQL expression
797−-- :}
798−-- CASE WHEN TRUE THEN 1 ELSE 0 END
799−ifThenElse
800− :: Condition commons schemas params grp from
801− -> Expression commons schemas params grp from ty -- ^ then
802− -> Expression commons schemas params grp from ty -- ^ else
803− -> Expression commons schemas params grp from ty
804−ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
805−
806−-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
807−-- will produce @NULL@s if one of their arguments is @NULL@.
808−--
809−-- >>> printSQL $ true .== null_
810−-- (TRUE = NULL)
811−(.==)
812− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
813− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
814− -> Condition commons schemas params grp from
815−(.==) = unsafeBinaryOp "="
816−infix 4 .==
817−
818−-- | >>> printSQL $ true ./= null_
819−-- (TRUE <> NULL)
820−(./=)
821− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
822− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
823− -> Condition commons schemas params grp from
824−(./=) = unsafeBinaryOp "<>"
825−infix 4 ./=
826−
827−-- | >>> printSQL $ true .>= null_
828−-- (TRUE >= NULL)
829−(.>=)
830− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
831− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
832− -> Condition commons schemas params grp from
833−(.>=) = unsafeBinaryOp ">="
834−infix 4 .>=
835−
836−-- | >>> printSQL $ true .< null_
837−-- (TRUE < NULL)
838−(.<)
839− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
840− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
841− -> Condition commons schemas params grp from
842−(.<) = unsafeBinaryOp "<"
843−infix 4 .<
844−
845−-- | >>> printSQL $ true .<= null_
846−-- (TRUE <= NULL)
847−(.<=)
848− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
849− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
850− -> Condition commons schemas params grp from
851−(.<=) = unsafeBinaryOp "<="
852−infix 4 .<=
853−
854−-- | >>> printSQL $ true .> null_
855−-- (TRUE > NULL)
856−(.>)
857− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
858− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
859− -> Condition commons schemas params grp from
860−(.>) = unsafeBinaryOp ">"
861−infix 4 .>
862−
863−-- | >>> printSQL currentDate
864−-- CURRENT_DATE
865−currentDate
866− :: Expression commons schemas params grp from (nullity 'PGdate)
867−currentDate = UnsafeExpression "CURRENT_DATE"
868−
869−-- | >>> printSQL currentTime
870−-- CURRENT_TIME
871−currentTime
872− :: Expression commons schemas params grp from (nullity 'PGtimetz)
873−currentTime = UnsafeExpression "CURRENT_TIME"
874−
875−-- | >>> printSQL currentTimestamp
876−-- CURRENT_TIMESTAMP
877−currentTimestamp
878− :: Expression commons schemas params grp from (nullity 'PGtimestamptz)
879−currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
880−
881−-- | >>> printSQL localTime
882−-- LOCALTIME
883−localTime
884− :: Expression commons schemas params grp from (nullity 'PGtime)
885−localTime = UnsafeExpression "LOCALTIME"
886−
887−-- | >>> printSQL localTimestamp
888−-- LOCALTIMESTAMP
889−localTimestamp
890− :: Expression commons schemas params grp from (nullity 'PGtimestamp)
891−localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
892−
893−{-----------------------------------------
894−text
895−-----------------------------------------}
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)
896438
897439instance IsString
898− (Expression commons schemas params grp from (nullity 'PGtext)) where
440+ (Expression outer commons grp schemas params from (null 'PGtext)) where
899441 fromString str = UnsafeExpression $
900442 "E\'" <> fromString (escape =<< str) <> "\'"
901− where
902− escape = \case
903− '\NUL' -> "\\0"
904− '\'' -> "''"
905− '"' -> "\\\""
906− '\b' -> "\\b"
907− '\n' -> "\\n"
908− '\r' -> "\\r"
909− '\t' -> "\\t"
910− '\\' -> "\\\\"
911− 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) <> "\'"
912451
913452instance Semigroup
914− (Expression commons schemas params grp from (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
915463 (<>) = unsafeBinaryOp "||"
916464
917465instance Monoid
918− (Expression commons schemas params grp from (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
919471 mempty = fromString ""
920472 mappend = (<>)
921−
922−-- | >>> printSQL $ lower "ARRRGGG"
923−-- lower(E'ARRRGGG')
924−lower
925− :: Expression commons schemas params grp from (nullity 'PGtext)
926− -- ^ string to lower case
927− -> Expression commons schemas params grp from (nullity 'PGtext)
928−lower = unsafeFunction "lower"
929−
930−-- | >>> printSQL $ upper "eeee"
931−-- upper(E'eeee')
932−upper
933− :: Expression commons schemas params grp from (nullity 'PGtext)
934− -- ^ string to upper case
935− -> Expression commons schemas params grp from (nullity 'PGtext)
936−upper = unsafeFunction "upper"
937−
938−-- | >>> printSQL $ charLength "four"
939−-- char_length(E'four')
940−charLength
941− :: Expression commons schemas params grp from (nullity 'PGtext)
942− -- ^ string to measure
943− -> Expression commons schemas params grp from (nullity 'PGint4)
944−charLength = unsafeFunction "char_length"
945−
946−-- | The `like` expression returns true if the @string@ matches
947−-- the supplied @pattern@. If @pattern@ does not contain percent signs
948−-- or underscores, then the pattern only represents the string itself;
949−-- in that case `like` acts like the equals operator. An underscore (_)
950−-- in pattern stands for (matches) any single character; a percent sign (%)
951−-- matches any sequence of zero or more characters.
952−--
953−-- >>> printSQL $ "abc" `like` "a%"
954−-- (E'abc' LIKE E'a%')
955−like
956− :: Expression commons schemas params grp from (nullity 'PGtext)
957− -- ^ string
958− -> Expression commons schemas params grp from (nullity 'PGtext)
959− -- ^ pattern
960− -> Expression commons schemas params grp from (nullity 'PGbool)
961−like = unsafeBinaryOp "LIKE"
962−
963−-- | The key word ILIKE can be used instead of LIKE to make the
964−-- match case-insensitive according to the active locale.
965−--
966−-- >>> printSQL $ "abc" `ilike` "a%"
967−-- (E'abc' ILIKE E'a%')
968−ilike
969− :: Expression commons schemas params grp from (nullity 'PGtext)
970− -- ^ string
971− -> Expression commons schemas params grp from (nullity 'PGtext)
972− -- ^ pattern
973− -> Expression commons schemas params grp from (nullity 'PGbool)
974−ilike = unsafeBinaryOp "ILIKE"
975−
976−{-----------------------------------------
977− -- json and jsonb support
978−
979−See https://www.postgresql.org/docs/10/static/functions-json.html -- most
980−comments lifted directly from this page.
981−
982−Table 9.44: json and jsonb operators
983−-----------------------------------------}
984−
985−-- | Get JSON value (object field or array element) at a key.
986−(.->)
987− :: (json `In` PGJsonType, key `In` PGJsonKey)
988− => Expression commons schemas params grp from (nullity json)
989− -> Expression commons schemas params grp from (nullity key)
990− -> Expression commons schemas params grp from ('Null json)
991−infixl 8 .->
992−(.->) = unsafeBinaryOp "->"
993−
994−-- | Get JSON value (object field or array element) at a key, as text.
995−(.->>)
996− :: (json `In` PGJsonType, key `In` PGJsonKey)
997− => Expression commons schemas params grp from (nullity json)
998− -> Expression commons schemas params grp from (nullity key)
999− -> Expression commons schemas params grp from ('Null 'PGtext)
1000−infixl 8 .->>
1001−(.->>) = unsafeBinaryOp "->>"
1002−
1003−-- | Get JSON value at a specified path.
1004−(.#>)
1005− :: (json `In` PGJsonType, PGTextArray "(.#>)" path)
1006− => Expression commons schemas params grp from (nullity json)
1007− -> Expression commons schemas params grp from (nullity path)
1008− -> Expression commons schemas params grp from ('Null json)
1009−infixl 8 .#>
1010−(.#>) = unsafeBinaryOp "#>"
1011−
1012−-- | Get JSON value at a specified path as text.
1013−(.#>>)
1014− :: (json `In` PGJsonType, PGTextArray "(.#>>)" path)
1015− => Expression commons schemas params grp from (nullity json)
1016− -> Expression commons schemas params grp from (nullity path)
1017− -> Expression commons schemas params grp from ('Null 'PGtext)
1018−infixl 8 .#>>
1019−(.#>>) = unsafeBinaryOp "#>>"
1020−
1021−-- Additional jsonb operators
1022−
1023−-- | Does the left JSON value contain the right JSON path/value entries at the
1024−-- top level?
1025−(.@>)
1026− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1027− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1028− -> Condition commons schemas params grp from
1029−infixl 9 .@>
1030−(.@>) = unsafeBinaryOp "@>"
1031−
1032−-- | Are the left JSON path/value entries contained at the top level within the
1033−-- right JSON value?
1034−(.<@)
1035− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1036− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1037− -> Condition commons schemas params grp from
1038−infixl 9 .<@
1039−(.<@) = unsafeBinaryOp "<@"
1040−
1041−-- | Does the string exist as a top-level key within the JSON value?
1042−(.?)
1043− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1044− -> Expression commons schemas params grp from (nullity 'PGtext)
1045− -> Condition commons schemas params grp from
1046−infixl 9 .?
1047−(.?) = unsafeBinaryOp "?"
1048−
1049−-- | Do any of these array strings exist as top-level keys?
1050−(.?|)
1051− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1052− -> Expression commons schemas params grp from (nullity ('PGvararray ('NotNull 'PGtext)))
1053− -> Condition commons schemas params grp from
1054−infixl 9 .?|
1055−(.?|) = unsafeBinaryOp "?|"
1056−
1057−-- | Do all of these array strings exist as top-level keys?
1058−(.?&)
1059− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1060− -> Expression commons schemas params grp from (nullity ('PGvararray ('NotNull 'PGtext)))
1061− -> Condition commons schemas params grp from
1062−infixl 9 .?&
1063−(.?&) = unsafeBinaryOp "?&"
1064−
1065−-- | Concatenate two jsonb values into a new jsonb value.
1066−instance
1067− Semigroup (Expression commons schemas from grouping param (nullity 'PGjsonb)) where
1068− (<>) = unsafeBinaryOp "||"
1069−
1070−-- | Delete a key or keys from a JSON object, or remove an array element.
1071−--
1072−-- If the right operand is..
1073−--
1074−-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1075−-- are matched based on their key value.
1076−--
1077−-- @ text[] @: Delete multiple key/value pairs or string elements
1078−-- from left operand. Key/value pairs are matched based on their key value.
1079−--
1080−-- @ integer @: Delete the array element with specified index (Negative integers
1081−-- count from the end). Throws an error if top level container is not an array.
1082−(.-.)
1083− :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1084− => Expression commons schemas params grp from (nullity 'PGjsonb)
1085− -> Expression commons schemas params grp from (nullity key)
1086− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1087−infixl 6 .-.
1088−(.-.) = unsafeBinaryOp "-"
1089−
1090−-- | Delete the field or element with specified path (for JSON arrays, negative
1091−-- integers count from the end)
1092−(#-.)
1093− :: PGTextArray "(#-.)" arrayty
1094− => Expression commons schemas params grp from (nullity 'PGjsonb)
1095− -> Expression commons schemas params grp from (nullity arrayty)
1096− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1097−infixl 6 #-.
1098−(#-.) = unsafeBinaryOp "#-"
1099−
1100−{-----------------------------------------
1101−Table 9.45: JSON creation functions
1102−-----------------------------------------}
1103−
1104−-- | Literal binary JSON
1105−jsonbLit
1106− :: JSON.ToJSON x
1107− => x -> Expression commons schemas params grp from (nullity 'PGjsonb)
1108−jsonbLit = cast jsonb . UnsafeExpression
1109− . singleQuotedUtf8 . toStrict . JSON.encode
1110−
1111−-- | Literal JSON
1112−jsonLit
1113− :: JSON.ToJSON x
1114− => x -> Expression commons schemas params grp from (nullity 'PGjson)
1115−jsonLit = cast json . UnsafeExpression
1116− . singleQuotedUtf8 . toStrict . JSON.encode
1117−
1118−-- | Returns the value as json. Arrays and composites are converted
1119−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1120−-- type to json, the cast function will be used to perform the conversion;
1121−-- otherwise, a scalar value is produced. For any scalar type other than a
1122−-- number, a Boolean, or a null value, the text representation will be used, in
1123−-- such a fashion that it is a valid json value.
1124−toJson
1125− :: Expression commons schemas params grp from (nullity ty)
1126− -> Expression commons schemas params grp from (nullity 'PGjson)
1127−toJson = unsafeFunction "to_json"
1128−
1129−-- | Returns the value as jsonb. Arrays and composites are converted
1130−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1131−-- type to json, the cast function will be used to perform the conversion;
1132−-- otherwise, a scalar value is produced. For any scalar type other than a
1133−-- number, a Boolean, or a null value, the text representation will be used, in
1134−-- such a fashion that it is a valid jsonb value.
1135−toJsonb
1136− :: Expression commons schemas params grp from (nullity ty)
1137− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1138−toJsonb = unsafeFunction "to_jsonb"
1139−
1140−-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1141−-- becomes a JSON array of arrays.
1142−arrayToJson
1143− :: PGArray "arrayToJson" arr
1144− => Expression commons schemas params grp from (nullity arr)
1145− -> Expression commons schemas params grp from (nullity 'PGjson)
1146−arrayToJson = unsafeFunction "array_to_json"
1147−
1148−-- | Returns the row as a JSON object.
1149−rowToJson
1150− :: Expression commons schemas params grp from (nullity ('PGcomposite ty))
1151− -> Expression commons schemas params grp from (nullity 'PGjson)
1152−rowToJson = unsafeFunction "row_to_json"
1153−
1154−-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1155−-- argument list.
1156−jsonBuildArray
1157− :: SListI elems
1158− => NP (Expression commons schemas params grp from) elems
1159− -> Expression commons schemas params grp from (nullity 'PGjson)
1160−jsonBuildArray = unsafeVariadicFunction "json_build_array"
1161−
1162−-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1163−-- variadic argument list.
1164−jsonbBuildArray
1165− :: SListI elems
1166− => NP (Expression commons schemas params grp from) elems
1167− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1168−jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1169−
1170−unsafeRowFunction
1171− :: All Top elems
1172− => NP (Aliased (Expression commons schemas params grp from)) elems
1173− -> [ByteString]
1174−unsafeRowFunction =
1175− (`appEndo` []) . hcfoldMap (Proxy :: Proxy Top)
1176− (\(col `As` name) -> Endo $ \xs ->
1177− renderAliasString name : renderSQL col : xs)
1178− where
1179− renderAliasString :: KnownSymbol alias => Alias alias -> ByteString
1180− renderAliasString = singleQuotedText . fromString . symbolVal
1181−
1182−-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1183−-- argument list. The elements of the argument list must alternate between text
1184−-- and values.
1185−jsonBuildObject
1186− :: All Top elems
1187− => NP (Aliased (Expression commons schemas params grp from)) elems
1188− -> Expression commons schemas params grp from (nullity 'PGjson)
1189−jsonBuildObject
1190− = unsafeFunction "json_build_object"
1191− . UnsafeExpression
1192− . commaSeparated
1193− . unsafeRowFunction
1194−
1195−-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1196−-- variadic argument list. The elements of the argument list must alternate
1197−-- between text and values.
1198−jsonbBuildObject
1199− :: All Top elems
1200− => NP (Aliased (Expression commons schemas params grp from)) elems
1201− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1202−jsonbBuildObject
1203− = unsafeFunction "jsonb_build_object"
1204− . UnsafeExpression
1205− . commaSeparated
1206− . unsafeRowFunction
1207−
1208−-- | Builds a JSON object out of a text array. The array must have either
1209−-- exactly one dimension with an even number of members, in which case they are
1210−-- taken as alternating key/value pairs, or two dimensions such that each inner
1211−-- array has exactly two elements, which are taken as a key/value pair.
1212−jsonObject
1213− :: PGArrayOf "jsonObject" arr ('NotNull 'PGtext)
1214− => Expression commons schemas params grp from (nullity arr)
1215− -> Expression commons schemas params grp from (nullity 'PGjson)
1216−jsonObject = unsafeFunction "json_object"
1217−
1218−-- | Builds a binary JSON object out of a text array. The array must have either
1219−-- exactly one dimension with an even number of members, in which case they are
1220−-- taken as alternating key/value pairs, or two dimensions such that each inner
1221−-- array has exactly two elements, which are taken as a key/value pair.
1222−jsonbObject
1223− :: PGArrayOf "jsonbObject" arr ('NotNull 'PGtext)
1224− => Expression commons schemas params grp from (nullity arr)
1225− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1226−jsonbObject = unsafeFunction "jsonb_object"
1227−
1228−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1229−-- keys and one for values, that are zipped pairwise to create a JSON object.
1230−jsonZipObject
1231− :: ( PGArrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1232− , PGArrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
1233− => Expression commons schemas params grp from (nullity keysArray)
1234− -> Expression commons schemas params grp from (nullity valuesArray)
1235− -> Expression commons schemas params grp from (nullity 'PGjson)
1236−jsonZipObject ks vs =
1237− unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1238−
1239−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1240−-- keys and one for values, that are zipped pairwise to create a binary JSON
1241−-- object.
1242−jsonbZipObject
1243− :: ( PGArrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1244− , PGArrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
1245− => Expression commons schemas params grp from (nullity keysArray)
1246− -> Expression commons schemas params grp from (nullity valuesArray)
1247− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1248−jsonbZipObject ks vs =
1249− unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1250−
1251−{-----------------------------------------
1252−Table 9.46: JSON processing functions
1253−-----------------------------------------}
1254−
1255−-- | Returns the number of elements in the outermost JSON array.
1256−jsonArrayLength
1257− :: Expression commons schemas params grp from (nullity 'PGjson)
1258− -> Expression commons schemas params grp from (nullity 'PGint4)
1259−jsonArrayLength = unsafeFunction "json_array_length"
1260−
1261−-- | Returns the number of elements in the outermost binary JSON array.
1262−jsonbArrayLength
1263− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1264− -> Expression commons schemas params grp from (nullity 'PGint4)
1265−jsonbArrayLength = unsafeFunction "jsonb_array_length"
1266−
1267−-- | Returns JSON value pointed to by the given path (equivalent to #>
1268−-- operator).
1269−jsonExtractPath
1270− :: SListI elems
1271− => Expression commons schemas params grp from (nullity 'PGjson)
1272− -> NP (Expression commons schemas params grp from) elems
1273− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1274−jsonExtractPath x xs =
1275− unsafeVariadicFunction "json_extract_path" (x :* xs)
1276−
1277−-- | Returns JSON value pointed to by the given path (equivalent to #>
1278−-- operator).
1279−jsonbExtractPath
1280− :: SListI elems
1281− => Expression commons schemas params grp from (nullity 'PGjsonb)
1282− -> NP (Expression commons schemas params grp from) elems
1283− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1284−jsonbExtractPath x xs =
1285− unsafeVariadicFunction "jsonb_extract_path" (x :* xs)
1286−
1287−-- | Returns JSON value pointed to by the given path (equivalent to #>
1288−-- operator), as text.
1289−jsonExtractPathAsText
1290− :: SListI elems
1291− => Expression commons schemas params grp from (nullity 'PGjson)
1292− -> NP (Expression commons schemas params grp from) elems
1293− -> Expression commons schemas params grp from (nullity 'PGjson)
1294−jsonExtractPathAsText x xs =
1295− unsafeVariadicFunction "json_extract_path_text" (x :* xs)
1296−
1297−-- | Returns JSON value pointed to by the given path (equivalent to #>
1298−-- operator), as text.
1299−jsonbExtractPathAsText
1300− :: SListI elems
1301− => Expression commons schemas params grp from (nullity 'PGjsonb)
1302− -> NP (Expression commons schemas params grp from) elems
1303− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1304−jsonbExtractPathAsText x xs =
1305− unsafeVariadicFunction "jsonb_extract_path_text" (x :* xs)
1306−
1307−-- | Returns the type of the outermost JSON value as a text string. Possible
1308−-- types are object, array, string, number, boolean, and null.
1309−jsonTypeof
1310− :: Expression commons schemas params grp from (nullity 'PGjson)
1311− -> Expression commons schemas params grp from (nullity 'PGtext)
1312−jsonTypeof = unsafeFunction "json_typeof"
1313−
1314−-- | Returns the type of the outermost binary JSON value as a text string.
1315−-- Possible types are object, array, string, number, boolean, and null.
1316−jsonbTypeof
1317− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1318− -> Expression commons schemas params grp from (nullity 'PGtext)
1319−jsonbTypeof = unsafeFunction "jsonb_typeof"
1320−
1321−-- | Returns its argument with all object fields that have null values omitted.
1322−-- Other null values are untouched.
1323−jsonStripNulls
1324− :: Expression commons schemas params grp from (nullity 'PGjson)
1325− -> Expression commons schemas params grp from (nullity 'PGjson)
1326−jsonStripNulls = unsafeFunction "json_strip_nulls"
1327−
1328−-- | Returns its argument with all object fields that have null values omitted.
1329−-- Other null values are untouched.
1330−jsonbStripNulls
1331− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1332− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1333−jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1334−
1335−-- | @ jsonbSet target path new_value create_missing @
1336−--
1337−-- Returns target with the section designated by path replaced by new_value,
1338−-- or with new_value added if create_missing is true ( default is true) and the
1339−-- item designated by path does not exist. As with the path orientated
1340−-- operators, negative integers that appear in path count from the end of JSON
1341−-- arrays.
1342−jsonbSet
1343− :: PGTextArray "jsonbSet" arr
1344− => Expression commons schemas params grp from (nullity 'PGjsonb)
1345− -> Expression commons schemas params grp from (nullity arr)
1346− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1347− -> Maybe (Expression commons schemas params grp from (nullity 'PGbool))
1348− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1349−jsonbSet tgt path val createMissing = case createMissing of
1350− Just m -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* m :* Nil)
1351− Nothing -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* Nil)
1352−
1353−-- | @ jsonbInsert target path new_value insert_after @
1354−--
1355−-- Returns target with new_value inserted. If target section designated by
1356−-- path is in a JSONB array, new_value will be inserted before target or after
1357−-- if insert_after is true (default is false). If target section designated by
1358−-- path is in JSONB object, new_value will be inserted only if target does not
1359−-- exist. As with the path orientated operators, negative integers that appear
1360−-- in path count from the end of JSON arrays.
1361−jsonbInsert
1362− :: PGTextArray "jsonbInsert" arr
1363− => Expression commons schemas params grp from (nullity 'PGjsonb)
1364− -> Expression commons schemas params grp from (nullity arr)
1365− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1366− -> Maybe (Expression commons schemas params grp from (nullity 'PGbool))
1367− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1368−jsonbInsert tgt path val insertAfter = case insertAfter of
1369− Just i -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1370− Nothing -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* Nil)
1371−
1372−-- | Returns its argument as indented JSON text.
1373−jsonbPretty
1374− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1375− -> Expression commons schemas params grp from (nullity 'PGtext)
1376−jsonbPretty = unsafeFunction "jsonb_pretty"
1377−
1378−{-----------------------------------------
1379−aggregation
1380−-----------------------------------------}
1381−
1382−-- | escape hatch to define aggregate functions
1383−unsafeAggregate
1384− :: ByteString -- ^ aggregate function
1385− -> Expression commons schemas from 'Ungrouped params (xty)
1386− -> Expression commons schemas from ('Grouped bys) params (yty)
1387−unsafeAggregate fun x = UnsafeExpression $ mconcat
1388− [fun, "(", renderSQL x, ")"]
1389−
1390−-- | escape hatch to define aggregate functions over distinct values
1391−unsafeAggregateDistinct
1392− :: ByteString -- ^ aggregate function
1393− -> Expression commons schemas from 'Ungrouped params (xty)
1394− -> Expression commons schemas from ('Grouped bys) params (yty)
1395−unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
1396− [fun, "(DISTINCT ", renderSQL x, ")"]
1397−
1398−-- | >>> :{
1399−-- let
1400−-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Null 'PGnumeric)
1401−-- expression = sum_ #col
1402−-- in printSQL expression
1403−-- :}
1404−-- sum("col")
1405−sum_
1406− :: ty `In` PGNum
1407− => Expression commons schemas from 'Ungrouped params (nullity ty)
1408− -- ^ what to sum
1409− -> Expression commons schemas from ('Grouped bys) params (nullity ty)
1410−sum_ = unsafeAggregate "sum"
1411−
1412−-- | >>> :{
1413−-- let
1414−-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: nullity 'PGnumeric]] (nullity 'PGnumeric)
1415−-- expression = sumDistinct #col
1416−-- in printSQL expression
1417−-- :}
1418−-- sum(DISTINCT "col")
1419−sumDistinct
1420− :: ty `In` PGNum
1421− => Expression commons schemas from 'Ungrouped params (nullity ty)
1422− -- ^ what to sum
1423− -> Expression commons schemas from ('Grouped bys) params (nullity ty)
1424−sumDistinct = unsafeAggregateDistinct "sum"
1425−
1426−-- | A constraint for `PGType`s that you can take averages of and the resulting
1427−-- `PGType`.
1428−class PGAvg ty avg | ty -> avg where
1429− avg, avgDistinct
1430− :: Expression commons schemas from 'Ungrouped params (nullity ty)
1431− -- ^ what to average
1432− -> Expression commons schemas from ('Grouped bys) params (nullity avg)
1433− avg = unsafeAggregate "avg"
1434− avgDistinct = unsafeAggregateDistinct "avg"
1435−instance PGAvg 'PGint2 'PGnumeric
1436−instance PGAvg 'PGint4 'PGnumeric
1437−instance PGAvg 'PGint8 'PGnumeric
1438−instance PGAvg 'PGnumeric 'PGnumeric
1439−instance PGAvg 'PGfloat4 'PGfloat8
1440−instance PGAvg 'PGfloat8 'PGfloat8
1441−instance PGAvg 'PGinterval 'PGinterval
1442−
1443−-- | >>> :{
1444−-- let
1445−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1446−-- expression = bitAnd #col
1447−-- in printSQL expression
1448−-- :}
1449−-- bit_and("col")
1450−bitAnd
1451− :: int `In` PGIntegral
1452− => Expression commons schemas from 'Ungrouped params (nullity int)
1453− -- ^ what to aggregate
1454− -> Expression commons schemas from ('Grouped bys) params (nullity int)
1455−bitAnd = unsafeAggregate "bit_and"
1456−
1457−-- | >>> :{
1458−-- let
1459−-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1460−-- expression = bitOr #col
1461−-- in printSQL expression
1462−-- :}
1463−-- bit_or("col")
1464−bitOr
1465− :: int `In` PGIntegral
1466− => Expression commons schemas from 'Ungrouped params (nullity int)
1467− -- ^ what to aggregate
1468− -> Expression commons schemas from ('Grouped bys) params (nullity int)
1469−bitOr = unsafeAggregate "bit_or"
1470−
1471−-- | >>> :{
1472−-- let
1473−-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1474−-- expression = bitAndDistinct #col
1475−-- in printSQL expression
1476−-- :}
1477−-- bit_and(DISTINCT "col")
1478−bitAndDistinct
1479− :: int `In` PGIntegral
1480− => Expression commons schemas from 'Ungrouped params (nullity int)
1481− -- ^ what to aggregate
1482− -> Expression commons schemas from ('Grouped bys) params (nullity int)
1483−bitAndDistinct = unsafeAggregateDistinct "bit_and"
1484−
1485−-- | >>> :{
1486−-- let
1487−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1488−-- expression = bitOrDistinct #col
1489−-- in printSQL expression
1490−-- :}
1491−-- bit_or(DISTINCT "col")
1492−bitOrDistinct
1493− :: int `In` PGIntegral
1494− => Expression commons schemas from 'Ungrouped params (nullity int)
1495− -- ^ what to aggregate
1496− -> Expression commons schemas from ('Grouped bys) params (nullity int)
1497−bitOrDistinct = unsafeAggregateDistinct "bit_or"
1498−
1499−-- | >>> :{
1500−-- let
1501−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1502−-- expression = boolAnd #col
1503−-- in printSQL expression
1504−-- :}
1505−-- bool_and("col")
1506−boolAnd
1507− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1508− -- ^ what to aggregate
1509− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1510−boolAnd = unsafeAggregate "bool_and"
1511−
1512−-- | >>> :{
1513−-- let
1514−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1515−-- expression = boolOr #col
1516−-- in printSQL expression
1517−-- :}
1518−-- bool_or("col")
1519−boolOr
1520− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1521− -- ^ what to aggregate
1522− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1523−boolOr = unsafeAggregate "bool_or"
1524−
1525−-- | >>> :{
1526−-- let
1527−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1528−-- expression = boolAndDistinct #col
1529−-- in printSQL expression
1530−-- :}
1531−-- bool_and(DISTINCT "col")
1532−boolAndDistinct
1533− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1534− -- ^ what to aggregate
1535− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1536−boolAndDistinct = unsafeAggregateDistinct "bool_and"
1537−
1538−-- | >>> :{
1539−-- let
1540−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1541−-- expression = boolOrDistinct #col
1542−-- in printSQL expression
1543−-- :}
1544−-- bool_or(DISTINCT "col")
1545−boolOrDistinct
1546− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1547− -- ^ what to aggregate
1548− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1549−boolOrDistinct = unsafeAggregateDistinct "bool_or"
1550−
1551−-- | A special aggregation that does not require an input
1552−--
1553−-- >>> printSQL countStar
1554−-- count(*)
1555−countStar
1556− :: Expression commons schemas from ('Grouped bys) params ('NotNull 'PGint8)
1557−countStar = UnsafeExpression $ "count(*)"
1558−
1559−-- | >>> :{
1560−-- let
1561−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1562−-- expression = count #col
1563−-- in printSQL expression
1564−-- :}
1565−-- count("col")
1566−count
1567− :: Expression commons schemas from 'Ungrouped params ty
1568− -- ^ what to count
1569− -> Expression commons schemas from ('Grouped bys) params ('NotNull 'PGint8)
1570−count = unsafeAggregate "count"
1571−
1572−-- | >>> :{
1573−-- let
1574−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1575−-- expression = countDistinct #col
1576−-- in printSQL expression
1577−-- :}
1578−-- count(DISTINCT "col")
1579−countDistinct
1580− :: Expression commons schemas from 'Ungrouped params ty
1581− -- ^ what to count
1582− -> Expression commons schemas from ('Grouped bys) params ('NotNull 'PGint8)
1583−countDistinct = unsafeAggregateDistinct "count"
1584−
1585−-- | synonym for `boolAnd`
1586−--
1587−-- >>> :{
1588−-- let
1589−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1590−-- expression = every #col
1591−-- in printSQL expression
1592−-- :}
1593−-- every("col")
1594−every
1595− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1596− -- ^ what to aggregate
1597− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1598−every = unsafeAggregate "every"
1599−
1600−-- | synonym for `boolAndDistinct`
1601−--
1602−-- >>> :{
1603−-- let
1604−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1605−-- expression = everyDistinct #col
1606−-- in printSQL expression
1607−-- :}
1608−-- every(DISTINCT "col")
1609−everyDistinct
1610− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1611− -- ^ what to aggregate
1612− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1613−everyDistinct = unsafeAggregateDistinct "every"
1614−
1615−-- | minimum and maximum aggregation
1616−max_, min_, maxDistinct, minDistinct
1617− :: Expression commons schemas from 'Ungrouped params (nullity ty)
1618− -- ^ what to aggregate
1619− -> Expression commons schemas from ('Grouped bys) params (nullity ty)
1620−max_ = unsafeAggregate "max"
1621−min_ = unsafeAggregate "min"
1622−maxDistinct = unsafeAggregateDistinct "max"
1623−minDistinct = unsafeAggregateDistinct "min"
1624−
1625−{-----------------------------------------
1626−type expressions
1627−-----------------------------------------}
1628−
1629−-- | `TypeExpression`s are used in `cast`s and `createTable` commands.
1630−newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
1631− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1632− deriving (GHC.Generic,Show,Eq,Ord,NFData)
1633−instance RenderSQL (TypeExpression schemas ty) where
1634− renderSQL = renderTypeExpression
1635−
1636−-- | The enum or composite type in a `Typedef` can be expressed by its alias.
1637−typedef
1638− :: (Has sch schemas schema, Has td schema ('Typedef ty))
1639− => QualifiedAlias sch td
1640− -> TypeExpression schemas (nullity ty)
1641−typedef = UnsafeTypeExpression . renderSQL
1642−
1643−-- | The composite type corresponding to a `Table` definition can be expressed
1644−-- by its alias.
1645−typetable
1646− :: (Has sch schemas schema, Has tab schema ('Table table))
1647− => QualifiedAlias sch tab
1648− -> TypeExpression schemas (nullity ('PGcomposite (TableToRow table)))
1649−typetable = UnsafeTypeExpression . renderSQL
1650−
1651−-- | The composite type corresponding to a `View` definition can be expressed
1652−-- by its alias.
1653−typeview
1654− :: (Has sch schemas schema, Has vw schema ('View view))
1655− => QualifiedAlias sch vw
1656− -> TypeExpression schemas (nullity ('PGcomposite view))
1657−typeview = UnsafeTypeExpression . renderSQL
1658−
1659−-- | logical Boolean (true/false)
1660−bool :: TypeExpression schemas (nullity 'PGbool)
1661−bool = UnsafeTypeExpression "bool"
1662−-- | signed two-byte integer
1663−int2, smallint :: TypeExpression schemas (nullity 'PGint2)
1664−int2 = UnsafeTypeExpression "int2"
1665−smallint = UnsafeTypeExpression "smallint"
1666−-- | signed four-byte integer
1667−int4, int, integer :: TypeExpression schemas (nullity 'PGint4)
1668−int4 = UnsafeTypeExpression "int4"
1669−int = UnsafeTypeExpression "int"
1670−integer = UnsafeTypeExpression "integer"
1671−-- | signed eight-byte integer
1672−int8, bigint :: TypeExpression schemas (nullity 'PGint8)
1673−int8 = UnsafeTypeExpression "int8"
1674−bigint = UnsafeTypeExpression "bigint"
1675−-- | arbitrary precision numeric type
1676−numeric :: TypeExpression schemas (nullity 'PGnumeric)
1677−numeric = UnsafeTypeExpression "numeric"
1678−-- | single precision floating-point number (4 bytes)
1679−float4, real :: TypeExpression schemas (nullity 'PGfloat4)
1680−float4 = UnsafeTypeExpression "float4"
1681−real = UnsafeTypeExpression "real"
1682−-- | double precision floating-point number (8 bytes)
1683−float8, doublePrecision :: TypeExpression schemas (nullity 'PGfloat8)
1684−float8 = UnsafeTypeExpression "float8"
1685−doublePrecision = UnsafeTypeExpression "double precision"
1686−-- | variable-length character string
1687−text :: TypeExpression schemas (nullity 'PGtext)
1688−text = UnsafeTypeExpression "text"
1689−-- | fixed-length character string
1690−char, character
1691− :: forall n schemas nullity. (KnownNat n, 1 <= n)
1692− => TypeExpression schemas (nullity ('PGchar n))
1693−char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
1694−character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
1695−-- | variable-length character string
1696−varchar, characterVarying
1697− :: forall n schemas nullity. (KnownNat n, 1 <= n)
1698− => TypeExpression schemas (nullity ('PGvarchar n))
1699−varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
1700−characterVarying = UnsafeTypeExpression $
1701− "character varying(" <> renderNat @n <> ")"
1702−-- | binary data ("byte array")
1703−bytea :: TypeExpression schemas (nullity 'PGbytea)
1704−bytea = UnsafeTypeExpression "bytea"
1705−-- | date and time (no time zone)
1706−timestamp :: TypeExpression schemas (nullity 'PGtimestamp)
1707−timestamp = UnsafeTypeExpression "timestamp"
1708−-- | date and time, including time zone
1709−timestampWithTimeZone :: TypeExpression schemas (nullity 'PGtimestamptz)
1710−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1711−-- | calendar date (year, month, day)
1712−date :: TypeExpression schemas (nullity 'PGdate)
1713−date = UnsafeTypeExpression "date"
1714−-- | time of day (no time zone)
1715−time :: TypeExpression schemas (nullity 'PGtime)
1716−time = UnsafeTypeExpression "time"
1717−-- | time of day, including time zone
1718−timeWithTimeZone :: TypeExpression schemas (nullity 'PGtimetz)
1719−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1720−-- | time span
1721−interval :: TypeExpression schemas (nullity 'PGinterval)
1722−interval = UnsafeTypeExpression "interval"
1723−-- | universally unique identifier
1724−uuid :: TypeExpression schemas (nullity 'PGuuid)
1725−uuid = UnsafeTypeExpression "uuid"
1726−-- | IPv4 or IPv6 host address
1727−inet :: TypeExpression schemas (nullity 'PGinet)
1728−inet = UnsafeTypeExpression "inet"
1729−-- | textual JSON data
1730−json :: TypeExpression schemas (nullity 'PGjson)
1731−json = UnsafeTypeExpression "json"
1732−-- | binary JSON data, decomposed
1733−jsonb :: TypeExpression schemas (nullity 'PGjsonb)
1734−jsonb = UnsafeTypeExpression "jsonb"
1735−-- | variable length array
1736−vararray
1737− :: TypeExpression schemas pg
1738− -> TypeExpression schemas (nullity ('PGvararray pg))
1739−vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
1740−-- | fixed length array
1741−--
1742−-- >>> renderSQL (fixarray @'[2] json)
1743−-- "json[2]"
1744−fixarray
1745− :: forall dims schemas nullity pg. All KnownNat dims
1746− => TypeExpression schemas pg
1747− -> TypeExpression schemas (nullity ('PGfixarray dims pg))
1748−fixarray ty = UnsafeTypeExpression $
1749− renderSQL ty <> renderDims @dims
1750− where
1751− renderDims :: forall ns. All KnownNat ns => ByteString
1752− renderDims =
1753− ("[" <>)
1754− . (<> "]")
1755− . ByteString.intercalate "]["
1756− . hcollapse
1757− $ hcmap (Proxy @KnownNat)
1758− (K . fromString . show . natVal)
1759− (hpure Proxy :: NP Proxy ns)
1760−
1761−-- | `pgtype` is a demoted version of a `PGType`
1762−class PGTyped schemas (ty :: NullityType) where
1763− pgtype :: TypeExpression schemas ty
1764−instance PGTyped schemas (nullity 'PGbool) where pgtype = bool
1765−instance PGTyped schemas (nullity 'PGint2) where pgtype = int2
1766−instance PGTyped schemas (nullity 'PGint4) where pgtype = int4
1767−instance PGTyped schemas (nullity 'PGint8) where pgtype = int8
1768−instance PGTyped schemas (nullity 'PGnumeric) where pgtype = numeric
1769−instance PGTyped schemas (nullity 'PGfloat4) where pgtype = float4
1770−instance PGTyped schemas (nullity 'PGfloat8) where pgtype = float8
1771−instance PGTyped schemas (nullity 'PGtext) where pgtype = text
1772−instance (KnownNat n, 1 <= n)
1773− => PGTyped schemas (nullity ('PGchar n)) where pgtype = char @n
1774−instance (KnownNat n, 1 <= n)
1775− => PGTyped schemas (nullity ('PGvarchar n)) where pgtype = varchar @n
1776−instance PGTyped schemas (nullity 'PGbytea) where pgtype = bytea
1777−instance PGTyped schemas (nullity 'PGtimestamp) where pgtype = timestamp
1778−instance PGTyped schemas (nullity 'PGtimestamptz) where pgtype = timestampWithTimeZone
1779−instance PGTyped schemas (nullity 'PGdate) where pgtype = date
1780−instance PGTyped schemas (nullity 'PGtime) where pgtype = time
1781−instance PGTyped schemas (nullity 'PGtimetz) where pgtype = timeWithTimeZone
1782−instance PGTyped schemas (nullity 'PGinterval) where pgtype = interval
1783−instance PGTyped schemas (nullity 'PGuuid) where pgtype = uuid
1784−instance PGTyped schemas (nullity 'PGjson) where pgtype = json
1785−instance PGTyped schemas (nullity 'PGjsonb) where pgtype = jsonb
1786−instance PGTyped schemas ty
1787− => PGTyped schemas (nullity ('PGvararray ty)) where
1788− pgtype = vararray (pgtype @schemas @ty)
1789−instance (All KnownNat dims, PGTyped schemas ty)
1790− => PGTyped schemas (nullity ('PGfixarray dims ty)) where
1791− pgtype = fixarray @dims (pgtype @schemas @ty)