@@ -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
@@ -34,558 +33,350 @@ Squeal expressions are the atoms used to build statements.
3433module Squeal.PostgreSQL.Expression
3534 ( -- * Expression
3635 Expression (..)
37− , HasParameter (parameter)
38− , param
39− -- ** Null
40− , null_
41− , notNull
42− , coalesce
43− , fromNull
44− , isNull
45− , isNotNull
46− , matchNull
47− , nullIf
48− -- ** Collections
49− , array
50− , index
51− , row
52− , field
53− -- ** Functions
54− , unsafeBinaryOp
55− , unsafeUnaryOp
36+ , Expr
37+ , type (-->)
38+ , FunctionDB
5639 , unsafeFunction
57− , unsafeVariadicFunction
58− , atan2_
59− , cast
60− , quot_
61− , rem_
62− , trunc
63− , round_
64− , ceiling_
65− , greatest
66− , least
67− -- ** Conditions
68− , true
69− , false
70− , not_
71− , (.&&)
72− , (.||)
73− , Condition
74− , caseWhenThenElse
75− , ifThenElse
76− , (.==)
77− , (./=)
78− , (.>=)
79− , (.<)
80− , (.<=)
81− , (.>)
82− -- ** Time
83− , currentDate
84− , currentTime
85− , currentTimestamp
86− , localTime
87− , localTimestamp
88− -- ** Text
89− , lower
90− , upper
91− , charLength
92− , like
93− , ilike
94− -- ** Json
95− -- *** Json and Jsonb operators
96− , (.->)
97− , (.->>)
98− , (.#>)
99− , (.#>>)
100− -- *** Jsonb operators
101− , (.@>)
102− , (.<@)
103− , (.?)
104− , (.?|)
105− , (.?&)
106− , (.-.)
107− , (#-.)
108− -- *** Functions
109− , jsonLit
110− , jsonbLit
111− , toJson
112− , toJsonb
113− , arrayToJson
114− , rowToJson
115− , jsonBuildArray
116− , jsonbBuildArray
117− , jsonBuildObject
118− , jsonbBuildObject
119− , jsonObject
120− , jsonbObject
121− , jsonZipObject
122− , jsonbZipObject
123− , jsonArrayLength
124− , jsonbArrayLength
125− , jsonExtractPath
126− , jsonbExtractPath
127− , jsonExtractPathAsText
128− , jsonbExtractPathAsText
129− , jsonTypeof
130− , jsonbTypeof
131− , jsonStripNulls
132− , jsonbStripNulls
133− , jsonbSet
134− , jsonbInsert
135− , jsonbPretty
136− -- ** Aggregation
137− , unsafeAggregate, unsafeAggregateDistinct
138− , sum_, sumDistinct
139− , PGAvg (avg, avgDistinct)
140− , bitAnd, bitOr, boolAnd, boolOr
141− , bitAndDistinct, bitOrDistinct, boolAndDistinct, boolOrDistinct
142− , countStar
143− , count, countDistinct
144− , every, everyDistinct
145− , max_, maxDistinct, min_, minDistinct
146− -- * Window Functions
147− , WindowDefinition (..)
148− , partitionBy
149− , WindowFunction (..)
150− , rank
151− , rowNumber
152− , denseRank
153− , percentRank
154− , cumeDist
155− -- * Sorting
156− , SortExpression (..)
157− , OrderBy (..)
158− -- * Types
159− , TypeExpression (..)
160− , PGTyped (..)
161− , typedef
162− , typetable
163− , typeview
164− , bool
165− , int2
166− , smallint
167− , int4
168− , int
169− , integer
170− , int8
171− , bigint
172− , numeric
173− , float4
174− , real
175− , float8
176− , doublePrecision
177− , text
178− , char
179− , character
180− , varchar
181− , characterVarying
182− , bytea
183− , timestamp
184− , timestampWithTimeZone
185− , date
186− , time
187− , timeWithTimeZone
188− , interval
189− , uuid
190− , inet
191− , json
192− , jsonb
193− , vararray
194− , 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 (..)
19557 -- * Re-export
19658 , (&)
197− , NP ((:*), Nil)
59+ , K (..)
60+ , unK
19861 ) where
19962
20063import Control.Category
20164import Control.DeepSeq
20265import Data.ByteString (ByteString)
203−import Data.ByteString.Lazy (toStrict)
20466import Data.Function ((&))
20567import Data.Semigroup hiding (All)
206−import qualified Data.Aeson as JSON
207−import Data.Ratio
20868import Data.String
209−import Data.Word
210−import Generics.SOP hiding (from)
69+import Generics.SOP hiding (All, from)
21170import GHC.OverloadedLabels
21271import GHC.TypeLits
72+import Numeric
21373import Prelude hiding (id, (.))
21474
21575import qualified GHC.Generics as GHC
21676
77+import Squeal.PostgreSQL.Alias
78+import Squeal.PostgreSQL.List
21779import Squeal.PostgreSQL.Render
21880import Squeal.PostgreSQL.Schema
21981
82+-- $setup
83+-- >>> import Squeal.PostgreSQL
84+
22085{-----------------------------------------
22186column expressions
22287-----------------------------------------}
22388
22489{- | `Expression`s are used in a variety of contexts,
225−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,
22692as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
22793`Squeal.PostgreSQL.Manipulation.update`,
228−or in search `Condition`s in a number of commands.
94+or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
22995
23096The expression syntax allows the calculation of
23197values from primitive expression using arithmetic, logical,
23298and 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`.
233113-}
234114newtype Expression
115+ (outer :: FromType)
235116 (commons :: FromType)
117+ (grp :: Grouping)
236118 (schemas :: SchemasType)
237119 (params :: [NullityType])
238− (grp :: Grouping)
239120 (from :: FromType)
240121 (ty :: NullityType)
241122 = UnsafeExpression { renderExpression :: ByteString }
242123 deriving (GHC.Generic,Show,Eq,Ord,NFData)
243−
244−instance RenderSQL (Expression commons schemas params grp from ty) where
124+instance RenderSQL (Expression outer commons grp schemas params from ty) where
245125 renderSQL = renderExpression
246126
247−{- | A `HasParameter` constraint is used to indicate a value that is
248−supplied externally to a SQL statement.
249−`Squeal.PostgreSQL.PQ.manipulateParams`,
250−`Squeal.PostgreSQL.PQ.queryParams` and
251−`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
252−separately from the SQL command string, in which case `param`s are used to
253−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)
254181-}
255−class KnownNat n => HasParameter
256− (n :: Nat)
257− (params :: [NullityType])
258− (ty :: NullityType)
259− | n params -> ty where
260− -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
261− --
262− -- >>> let expr = parameter @1 int4 :: Expression '[] schemas '[ 'Null 'PGint4] grp from ('Null 'PGint4)
263− -- >>> printSQL expr
264− -- ($1 :: int4)
265− parameter
266− :: TypeExpression schemas ty
267− -> Expression commons schemas params grp from ty
268− parameter ty = UnsafeExpression $ parenthesized $
269− "$" <> renderNat @n <+> "::"
270− <+> renderSQL ty
271−instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
272−instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
273− => HasParameter n (ty' : params) ty
274−
275−-- | `param` takes a `Nat` using type application and for basic types,
276−-- infers a `TypeExpression`.
277−--
278−-- >>> let expr = param @1 :: Expression commons schemas '[ 'Null 'PGint4] grp from ('Null 'PGint4)
279−-- >>> printSQL expr
280−-- ($1 :: int4)
281−param
282− :: forall n commons schemas params from grp ty
283− . (PGTyped schemas ty, HasParameter n params ty)
284− => Expression commons schemas params grp from ty -- ^ param
285−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)
286214
287−instance (HasUnique tab from row, Has col row ty)
288− => 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
289217 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
290−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))
291222 => IsLabel col
292− (Aliased (Expression commons schemas params 'Ungrouped from) column) where
223+ (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
293224 fromLabel = fromLabel @col `As` Alias
294−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])
295226 => IsLabel col
296− (NP (Aliased (Expression commons schemas params 'Ungrouped from)) columns) where
227+ (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
297228 fromLabel = fromLabel @col :* Nil
298229
299−instance (Has tab from row, Has col row ty)
300− => 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
301232 tab ! col = UnsafeExpression $
302233 renderSQL tab <> "." <> renderSQL col
303−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))
304238 => IsQualified tab col
305− (Aliased (Expression commons schemas params 'Ungrouped from) column) where
239+ (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
306240 tab ! col = tab ! col `As` col
307−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])
308242 => IsQualified tab col
309− (NP (Aliased (Expression commons schemas params 'Ungrouped from)) columns) where
243+ (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
310244 tab ! col = tab ! col :* Nil
311245
312246instance
313− ( HasUnique tab from row
247+ ( HasUnique tab (Join outer from) row
314248 , Has col row ty
315249 , GroupedBy tab col bys
316250 ) => IsLabel col
317− (Expression commons schemas params ('Grouped bys) from ty) where
251+ (Expression outer commons ('Grouped bys) schemas params from ty) where
318252 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
319253instance
320− ( 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
321263 , Has col row ty
322264 , GroupedBy tab col bys
323265 , column ~ (col ::: ty)
324266 ) => IsLabel col
325− (Aliased (Expression commons schemas params ('Grouped bys) from) column) where
267+ (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
326268 fromLabel = fromLabel @col `As` Alias
327269instance
328− ( HasUnique tab from row
270+ ( HasUnique tab (Join outer from) row
329271 , Has col row ty
330272 , GroupedBy tab col bys
331273 , columns ~ '[col ::: ty]
332274 ) => IsLabel col
333− (NP (Aliased (Expression commons schemas params ('Grouped bys) from)) columns) where
275+ (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
334276 fromLabel = fromLabel @col :* Nil
335277
336278instance
337− ( Has tab from row
279+ ( Has tab (Join outer from) row
338280 , Has col row ty
339281 , GroupedBy tab col bys
340282 ) => IsQualified tab col
341− (Expression commons schemas params ('Grouped bys) from ty) where
283+ (Expression outer commons ('Grouped bys) schemas params from ty) where
342284 tab ! col = UnsafeExpression $
343285 renderSQL tab <> "." <> renderSQL col
344286instance
345− ( 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
346296 , Has col row ty
347297 , GroupedBy tab col bys
348298 , column ~ (col ::: ty)
349299 ) => IsQualified tab col
350− (Aliased (Expression commons schemas params ('Grouped bys) from) column) where
300+ (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
351301 tab ! col = tab ! col `As` col
352302instance
353− ( Has tab from row
303+ ( Has tab (Join outer from) row
354304 , Has col row ty
355305 , GroupedBy tab col bys
356306 , columns ~ '[col ::: ty]
357307 ) => IsQualified tab col
358− (NP (Aliased (Expression commons schemas params ('Grouped bys) from)) columns) where
308+ (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
359309 tab ! col = tab ! col :* Nil
360310
361−-- | analagous to `Nothing`
362−--
363−-- >>> printSQL null_
364−-- NULL
365−null_ :: Expression commons schemas rels grouping params ('Null ty)
366−null_ = UnsafeExpression "NULL"
367−
368−-- | analagous to `Just`
369−--
370−-- >>> printSQL $ notNull true
371−-- TRUE
372−notNull
373− :: Expression commons schemas rels grouping params ('NotNull ty)
374− -> Expression commons schemas rels grouping params ('Null ty)
375−notNull = UnsafeExpression . renderSQL
376−
377−-- | return the leftmost value which is not NULL
378−--
379−-- >>> printSQL $ coalesce [null_, true] false
380−-- COALESCE(NULL, TRUE, FALSE)
381−coalesce
382− :: [Expression commons schemas params grp from ('Null ty)]
383− -- ^ @NULL@s may be present
384− -> Expression commons schemas params grp from ('NotNull ty)
385− -- ^ @NULL@ is absent
386− -> Expression commons schemas params grp from ('NotNull ty)
387−coalesce nullxs notNullx = UnsafeExpression $
388− "COALESCE" <> parenthesized (commaSeparated
389− ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
390−
391−-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
392−--
393−-- >>> printSQL $ fromNull true null_
394−-- COALESCE(NULL, TRUE)
395−fromNull
396− :: Expression commons schemas params grp from ('NotNull ty)
397− -- ^ what to convert @NULL@ to
398− -> Expression commons schemas params grp from ('Null ty)
399− -> Expression commons schemas params grp from ('NotNull ty)
400−fromNull notNullx nullx = coalesce [nullx] notNullx
401−
402−-- | >>> printSQL $ null_ & isNull
403−-- NULL IS NULL
404−isNull
405− :: Expression commons schemas params grp from ('Null ty)
406− -- ^ possibly @NULL@
407− -> Condition commons schemas params grp from
408−isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
409−
410−-- | >>> printSQL $ null_ & isNotNull
411−-- NULL IS NOT NULL
412−isNotNull
413− :: Expression commons schemas params grp from ('Null ty)
414− -- ^ possibly @NULL@
415− -> Condition commons schemas params grp from
416−isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
417−
418−-- | analagous to `maybe` using @IS NULL@
419−--
420−-- >>> printSQL $ matchNull true not_ null_
421−-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
422−matchNull
423− :: Expression commons schemas params grp from (nullty)
424− -- ^ what to convert @NULL@ to
425− -> ( Expression commons schemas params grp from ('NotNull ty)
426− -> Expression commons schemas params grp from (nullty) )
427− -- ^ function to perform when @NULL@ is absent
428− -> Expression commons schemas params grp from ('Null ty)
429− -> Expression commons schemas params grp from (nullty)
430−matchNull y f x = ifThenElse (isNull x) y
431− (f (UnsafeExpression (renderSQL x)))
432−
433−{-| right inverse to `fromNull`, if its arguments are equal then
434−`nullIf` gives @NULL@.
435−
436−>>> :set -XTypeApplications -XDataKinds
437−>>> let expr = nullIf false (param @1) :: Expression commons schemas '[ 'NotNull 'PGbool] grp from ('Null 'PGbool)
438−>>> printSQL expr
439−NULL IF (FALSE, ($1 :: bool))
440−-}
441−nullIf
442− :: Expression commons schemas params grp from ('NotNull ty)
443− -- ^ @NULL@ is absent
444− -> Expression commons schemas params grp from ('NotNull ty)
445− -- ^ @NULL@ is absent
446− -> Expression commons schemas params grp from ('Null ty)
447−nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
448− (renderSQL x <> ", " <> renderSQL y)
449−
450−-- | >>> printSQL $ array [null_, false, true]
451−-- ARRAY[NULL, FALSE, TRUE]
452−array
453− :: [Expression commons schemas params grp from ty]
454− -- ^ array elements
455− -> Expression commons schemas params grp from (nullity ('PGvararray ty))
456−array xs = UnsafeExpression $
457− "ARRAY[" <> commaSeparated (renderSQL <$> xs) <> "]"
458−
459−-- | >>> printSQL $ array [null_, false, true] & index 2
460−-- (ARRAY[NULL, FALSE, TRUE])[2]
461−index
462− :: Word64 -- ^ index
463− -> Expression commons schemas params grp from (nullity ('PGvararray ty)) -- ^ array
464− -> Expression commons schemas params grp from (NullifyType ty)
465−index n expr = UnsafeExpression $
466− parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
467−
468311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
469− (Expression commons schemas params grp from (nullity ('PGenum labels))) where
312+ (Expression outer commons grp schemas params from (null ('PGenum labels))) where
470313 label = UnsafeExpression $ renderSQL (PGlabel @label)
471314
472−-- | A row constructor is an expression that builds a row value
473−-- (also called a composite value) using values for its member fields.
474−--
475−-- >>> :{
476−-- type Complex = 'PGcomposite
477−-- '[ "real" ::: 'NotNull 'PGfloat8
478−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
479−-- :}
480−--
481−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression commons schemas from grp params ('NotNull Complex)
482−-- >>> printSQL i
483−-- ROW(0, 1)
484−row
485− :: SListI row
486− => NP (Aliased (Expression commons schemas params grp from)) row
487− -- ^ zero or more expressions for the row field values
488− -> Expression commons schemas params grp from (nullity ('PGcomposite row))
489−row exprs = UnsafeExpression $ "ROW" <> parenthesized
490− (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
491−
492−-- | >>> :{
493−-- type Complex = 'PGcomposite
494−-- '[ "real" ::: 'NotNull 'PGfloat8
495−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
496−-- type Schema = '["complex" ::: 'Typedef Complex]
497−-- :}
498−--
499−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression '[] (Public Schema) from grp params ('NotNull Complex)
500−-- >>> printSQL $ i & field #complex #imaginary
501−-- (ROW(0, 1)::"complex")."imaginary"
502−field
503− :: ( Has sch schemas schema
504− , Has tydef schema ('Typedef ('PGcomposite row))
505− , Has field row ty)
506− => QualifiedAlias sch tydef -- ^ row type
507− -> Alias field -- ^ field name
508− -> Expression commons schemas params grp from ('NotNull ('PGcomposite row))
509− -> Expression commons schemas params grp from ty
510−field td fld expr = UnsafeExpression $
511− parenthesized (renderSQL expr <> "::" <> renderSQL td)
512− <> "." <> renderSQL fld
513−
514−instance Semigroup
515− (Expression commons schemas params grp from (nullity ('PGvararray ty))) where
516− (<>) = unsafeBinaryOp "||"
517−
518−instance Monoid
519− (Expression commons schemas params grp from (nullity ('PGvararray ty))) where
520− mempty = array []
521− mappend = (<>)
522−
523−-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression commons schemas '[ 'NotNull 'PGtimestamptz] grp from ('NotNull 'PGtimestamptz)
524−-- >>> printSQL expr
525−-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
526−greatest
527− :: Expression commons schemas params grp from (nullty)
528− -- ^ needs at least 1 argument
529− -> [Expression commons schemas params grp from (nullty)]
530− -- ^ or more
531− -> Expression commons schemas params grp from (nullty)
532−greatest x xs = UnsafeExpression $ "GREATEST("
533− <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
534−
535−-- | >>> printSQL $ least currentTimestamp [null_]
536−-- LEAST(CURRENT_TIMESTAMP, NULL)
537−least
538− :: Expression commons schemas params grp from (nullty)
539− -- ^ needs at least 1 argument
540− -> [Expression commons schemas params grp from (nullty)]
541− -- ^ or more
542− -> Expression commons schemas params grp from (nullty)
543−least x xs = UnsafeExpression $ "LEAST("
544− <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
545−
546315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
547316-- (TRUE OR FALSE)
548−unsafeBinaryOp
549− :: ByteString
550− -- ^ operator
551− -> Expression commons schemas params grp from (ty0)
552− -> Expression commons schemas params grp from (ty1)
553− -> Expression commons schemas params grp from (ty2)
317+unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
554318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
555319 renderSQL x <+> op <+> renderSQL y
556320
557−-- | >>> 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
558329-- (NOT TRUE)
559−unsafeUnaryOp
560− :: ByteString
561− -- ^ operator
562− -> Expression commons schemas params grp from (ty0)
563− -> Expression commons schemas params grp from (ty1)
564−unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
565− 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
566351
567352-- | >>> printSQL $ unsafeFunction "f" true
568353-- f(TRUE)
569−unsafeFunction
570− :: ByteString
571− -- ^ function
572− -> Expression commons schemas params grp from (xty)
573− -> Expression commons schemas params grp from (yty)
354+unsafeFunction :: ByteString -> x --> y
574355unsafeFunction fun x = UnsafeExpression $
575356 fun <> parenthesized (renderSQL x)
576357
577−-- | Helper for defining variadic functions.
578−unsafeVariadicFunction
579− :: SListI elems
580− => ByteString
581− -- ^ function
582− -> NP (Expression commons schemas params grp from) elems
583− -> Expression commons schemas params grp from ret
584−unsafeVariadicFunction fun x = UnsafeExpression $
585− 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
586377
587378instance ty `In` PGNum
588− => Num (Expression commons schemas params grp from (nullity ty)) where
379+ => Num (Expression outer commons grp schemas params from (null ty)) where
589380 (+) = unsafeBinaryOp "+"
590381 (-) = unsafeBinaryOp "-"
591382 (*) = unsafeBinaryOp "*"
@@ -597,12 +388,17 @@ instance ty `In` PGNum
597388 . show
598389
599390instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
600− (Expression commons schemas params grp from (nullity ty)) where
391+ (Expression outer commons grp schemas params from (null ty)) where
601392 (/) = unsafeBinaryOp "/"
602− fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
393+ fromRational
394+ = UnsafeExpression
395+ . fromString
396+ . ($ "")
397+ . showFFloat Nothing
398+ . fromRat @Double
603399
604400instance (ty `In` PGNum, ty `In` PGFloating) => Floating
605− (Expression commons schemas params grp from (nullity ty)) where
401+ (Expression outer commons grp schemas params from (null ty)) where
606402 pi = UnsafeExpression "pi()"
607403 exp = unsafeFunction "exp"
608404 log = unsafeFunction "ln"
@@ -623,1301 +419,54 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
623419 acosh x = log (x + sqrt (x*x - 1))
624420 atanh x = log ((1 + x) / (1 - x)) / 2
625421
626−-- | >>> :{
627−-- let
628−-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
629−-- expression = atan2_ pi 2
630−-- in printSQL expression
631−-- :}
632−-- atan2(pi(), 2)
633−atan2_
634− :: float `In` PGFloating
635− => Expression commons schemas params grp from (nullity float)
636− -- ^ numerator
637− -> Expression commons schemas params grp from (nullity float)
638− -- ^ denominator
639− -> Expression commons schemas params grp from (nullity float)
640−atan2_ y x = UnsafeExpression $
641− "atan2(" <> renderSQL y <> ", " <> renderSQL x <> ")"
642−
643−-- When a `cast` is applied to an `Expression` of a known type, it
644−-- represents a run-time type conversion. The cast will succeed only if a
645−-- suitable type conversion operation has been defined.
646−--
647−-- | >>> printSQL $ true & cast int4
648−-- (TRUE :: int4)
649−cast
650− :: TypeExpression schemas ty1
651− -- ^ type to cast as
652− -> Expression commons schemas params grp from ty0
653− -- ^ value to convert
654− -> Expression commons schemas params grp from ty1
655−cast ty x = UnsafeExpression $ parenthesized $
656− renderSQL x <+> "::" <+> renderSQL ty
657−
658−-- | integer division, truncates the result
659−--
660−-- >>> :{
661−-- let
662−-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
663−-- expression = 5 `quot_` 2
664−-- in printSQL expression
665−-- :}
666−-- (5 / 2)
667−quot_
668− :: int `In` PGIntegral
669− => Expression commons schemas params grp from (nullity int)
670− -- ^ numerator
671− -> Expression commons schemas params grp from (nullity int)
672− -- ^ denominator
673− -> Expression commons schemas params grp from (nullity int)
674−quot_ = unsafeBinaryOp "/"
675−
676−-- | remainder upon integer division
677−--
678−-- >>> :{
679−-- let
680−-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
681−-- expression = 5 `rem_` 2
682−-- in printSQL expression
683−-- :}
684−-- (5 % 2)
685−rem_
686− :: int `In` PGIntegral
687− => Expression commons schemas params grp from (nullity int)
688− -- ^ numerator
689− -> Expression commons schemas params grp from (nullity int)
690− -- ^ denominator
691− -> Expression commons schemas params grp from (nullity int)
692−rem_ = unsafeBinaryOp "%"
693−
694−-- | >>> :{
695−-- let
696−-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
697−-- expression = trunc pi
698−-- in printSQL expression
699−-- :}
700−-- trunc(pi())
701−trunc
702− :: frac `In` PGFloating
703− => Expression commons schemas params grp from (nullity frac)
704− -- ^ fractional number
705− -> Expression commons schemas params grp from (nullity frac)
706−trunc = unsafeFunction "trunc"
707−
708−-- | >>> :{
709−-- let
710−-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
711−-- expression = round_ pi
712−-- in printSQL expression
713−-- :}
714−-- round(pi())
715−round_
716− :: frac `In` PGFloating
717− => Expression commons schemas params grp from (nullity frac)
718− -- ^ fractional number
719− -> Expression commons schemas params grp from (nullity frac)
720−round_ = unsafeFunction "round"
721−
722−-- | >>> :{
723−-- let
724−-- expression :: Expression commons schemas params grp from (nullity 'PGfloat4)
725−-- expression = ceiling_ pi
726−-- in printSQL expression
727−-- :}
728−-- ceiling(pi())
729−ceiling_
730− :: frac `In` PGFloating
731− => Expression commons schemas params grp from (nullity frac)
732− -- ^ fractional number
733− -> Expression commons schemas params grp from (nullity frac)
734−ceiling_ = unsafeFunction "ceiling"
735−
736−-- | A `Condition` is an `Expression`, which can evaluate
737−-- to `true`, `false` or `null_`. This is because SQL uses
738−-- a three valued logic.
739−type Condition commons schemas params grp from =
740− Expression commons schemas params grp from ('Null 'PGbool)
741−
742−-- | >>> printSQL true
743−-- TRUE
744−true :: Expression commons schemas params grp from (nullity 'PGbool)
745−true = UnsafeExpression "TRUE"
746−
747−-- | >>> printSQL false
748−-- FALSE
749−false :: Expression commons schemas params grp from (nullity 'PGbool)
750−false = UnsafeExpression "FALSE"
751−
752−-- | >>> printSQL $ not_ true
753−-- (NOT TRUE)
754−not_
755− :: Expression commons schemas params grp from (nullity 'PGbool)
756− -> Expression commons schemas params grp from (nullity 'PGbool)
757−not_ = unsafeUnaryOp "NOT"
758−
759−-- | >>> printSQL $ true .&& false
760−-- (TRUE AND FALSE)
761−(.&&)
762− :: Expression commons schemas params grp from (nullity 'PGbool)
763− -> Expression commons schemas params grp from (nullity 'PGbool)
764− -> Expression commons schemas params grp from (nullity 'PGbool)
765−infixr 3 .&&
766−(.&&) = unsafeBinaryOp "AND"
767−
768−-- | >>> printSQL $ true .|| false
769−-- (TRUE OR FALSE)
770−(.||)
771− :: Expression commons schemas params grp from (nullity 'PGbool)
772− -> Expression commons schemas params grp from (nullity 'PGbool)
773− -> Expression commons schemas params grp from (nullity 'PGbool)
774−infixr 2 .||
775−(.||) = unsafeBinaryOp "OR"
776−
777−-- | >>> :{
778−-- let
779−-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
780−-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
781−-- in printSQL expression
782−-- :}
783−-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
784−caseWhenThenElse
785− :: [ ( Condition commons schemas params grp from
786− , Expression commons schemas params grp from ty
787− ) ]
788− -- ^ whens and thens
789− -> Expression commons schemas params grp from ty
790− -- ^ else
791− -> Expression commons schemas params grp from ty
792−caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
793− [ "CASE"
794− , mconcat
795− [ mconcat
796− [ " WHEN ", renderSQL when_
797− , " THEN ", renderSQL then_
798− ]
799− | (when_,then_) <- whenThens
800− ]
801− , " ELSE ", renderSQL else_
802− , " END"
803− ]
804−
805−-- | >>> :{
806−-- let
807−-- expression :: Expression commons schemas params grp from (nullity 'PGint2)
808−-- expression = ifThenElse true 1 0
809−-- in printSQL expression
810−-- :}
811−-- CASE WHEN TRUE THEN 1 ELSE 0 END
812−ifThenElse
813− :: Condition commons schemas params grp from
814− -> Expression commons schemas params grp from ty -- ^ then
815− -> Expression commons schemas params grp from ty -- ^ else
816− -> Expression commons schemas params grp from ty
817−ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
818−
819−-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
820−-- will produce @NULL@s if one of their arguments is @NULL@.
821−--
822−-- >>> printSQL $ true .== null_
823−-- (TRUE = NULL)
824−(.==)
825− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
826− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
827− -> Condition commons schemas params grp from
828−(.==) = unsafeBinaryOp "="
829−infix 4 .==
830−
831−-- | >>> printSQL $ true ./= null_
832−-- (TRUE <> NULL)
833−(./=)
834− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
835− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
836− -> Condition commons schemas params grp from
837−(./=) = unsafeBinaryOp "<>"
838−infix 4 ./=
839−
840−-- | >>> printSQL $ true .>= null_
841−-- (TRUE >= NULL)
842−(.>=)
843− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
844− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
845− -> Condition commons schemas params grp from
846−(.>=) = unsafeBinaryOp ">="
847−infix 4 .>=
848−
849−-- | >>> printSQL $ true .< null_
850−-- (TRUE < NULL)
851−(.<)
852− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
853− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
854− -> Condition commons schemas params grp from
855−(.<) = unsafeBinaryOp "<"
856−infix 4 .<
857−
858−-- | >>> printSQL $ true .<= null_
859−-- (TRUE <= NULL)
860−(.<=)
861− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
862− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
863− -> Condition commons schemas params grp from
864−(.<=) = unsafeBinaryOp "<="
865−infix 4 .<=
866−
867−-- | >>> printSQL $ true .> null_
868−-- (TRUE > NULL)
869−(.>)
870− :: Expression commons schemas params grp from (nullity0 ty) -- ^ lhs
871− -> Expression commons schemas params grp from (nullity1 ty) -- ^ rhs
872− -> Condition commons schemas params grp from
873−(.>) = unsafeBinaryOp ">"
874−infix 4 .>
875−
876−-- | >>> printSQL currentDate
877−-- CURRENT_DATE
878−currentDate
879− :: Expression commons schemas params grp from (nullity 'PGdate)
880−currentDate = UnsafeExpression "CURRENT_DATE"
881−
882−-- | >>> printSQL currentTime
883−-- CURRENT_TIME
884−currentTime
885− :: Expression commons schemas params grp from (nullity 'PGtimetz)
886−currentTime = UnsafeExpression "CURRENT_TIME"
887−
888−-- | >>> printSQL currentTimestamp
889−-- CURRENT_TIMESTAMP
890−currentTimestamp
891− :: Expression commons schemas params grp from (nullity 'PGtimestamptz)
892−currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
893−
894−-- | >>> printSQL localTime
895−-- LOCALTIME
896−localTime
897− :: Expression commons schemas params grp from (nullity 'PGtime)
898−localTime = UnsafeExpression "LOCALTIME"
899−
900−-- | >>> printSQL localTimestamp
901−-- LOCALTIMESTAMP
902−localTimestamp
903− :: Expression commons schemas params grp from (nullity 'PGtimestamp)
904−localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
905−
906−{-----------------------------------------
907−text
908−-----------------------------------------}
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)
909438
910439instance IsString
911− (Expression commons schemas params grp from (nullity 'PGtext)) where
440+ (Expression outer commons grp schemas params from (null 'PGtext)) where
912441 fromString str = UnsafeExpression $
913442 "E\'" <> fromString (escape =<< str) <> "\'"
914− where
915− escape = \case
916− '\NUL' -> "\\0"
917− '\'' -> "''"
918− '"' -> "\\\""
919− '\b' -> "\\b"
920− '\n' -> "\\n"
921− '\r' -> "\\r"
922− '\t' -> "\\t"
923− '\\' -> "\\\\"
924− 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) <> "\'"
925451
926452instance Semigroup
927− (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
928463 (<>) = unsafeBinaryOp "||"
929464
930465instance Monoid
931− (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
932471 mempty = fromString ""
933472 mappend = (<>)
934−
935−-- | >>> printSQL $ lower "ARRRGGG"
936−-- lower(E'ARRRGGG')
937−lower
938− :: Expression commons schemas params grp from (nullity 'PGtext)
939− -- ^ string to lower case
940− -> Expression commons schemas params grp from (nullity 'PGtext)
941−lower = unsafeFunction "lower"
942−
943−-- | >>> printSQL $ upper "eeee"
944−-- upper(E'eeee')
945−upper
946− :: Expression commons schemas params grp from (nullity 'PGtext)
947− -- ^ string to upper case
948− -> Expression commons schemas params grp from (nullity 'PGtext)
949−upper = unsafeFunction "upper"
950−
951−-- | >>> printSQL $ charLength "four"
952−-- char_length(E'four')
953−charLength
954− :: Expression commons schemas params grp from (nullity 'PGtext)
955− -- ^ string to measure
956− -> Expression commons schemas params grp from (nullity 'PGint4)
957−charLength = unsafeFunction "char_length"
958−
959−-- | The `like` expression returns true if the @string@ matches
960−-- the supplied @pattern@. If @pattern@ does not contain percent signs
961−-- or underscores, then the pattern only represents the string itself;
962−-- in that case `like` acts like the equals operator. An underscore (_)
963−-- in pattern stands for (matches) any single character; a percent sign (%)
964−-- matches any sequence of zero or more characters.
965−--
966−-- >>> printSQL $ "abc" `like` "a%"
967−-- (E'abc' LIKE E'a%')
968−like
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−like = unsafeBinaryOp "LIKE"
975−
976−-- | The key word ILIKE can be used instead of LIKE to make the
977−-- match case-insensitive according to the active locale.
978−--
979−-- >>> printSQL $ "abc" `ilike` "a%"
980−-- (E'abc' ILIKE E'a%')
981−ilike
982− :: Expression commons schemas params grp from (nullity 'PGtext)
983− -- ^ string
984− -> Expression commons schemas params grp from (nullity 'PGtext)
985− -- ^ pattern
986− -> Expression commons schemas params grp from (nullity 'PGbool)
987−ilike = unsafeBinaryOp "ILIKE"
988−
989−{-----------------------------------------
990− -- json and jsonb support
991−
992−See https://www.postgresql.org/docs/10/static/functions-json.html -- most
993−comments lifted directly from this page.
994−
995−Table 9.44: json and jsonb operators
996−-----------------------------------------}
997−
998−-- | Get JSON value (object field or array element) at a key.
999−(.->)
1000− :: (json `In` PGJsonType, key `In` PGJsonKey)
1001− => Expression commons schemas params grp from (nullity json)
1002− -> Expression commons schemas params grp from (nullity key)
1003− -> Expression commons schemas params grp from ('Null json)
1004−infixl 8 .->
1005−(.->) = unsafeBinaryOp "->"
1006−
1007−-- | Get JSON value (object field or array element) at a key, as text.
1008−(.->>)
1009− :: (json `In` PGJsonType, key `In` PGJsonKey)
1010− => Expression commons schemas params grp from (nullity json)
1011− -> Expression commons schemas params grp from (nullity key)
1012− -> Expression commons schemas params grp from ('Null 'PGtext)
1013−infixl 8 .->>
1014−(.->>) = unsafeBinaryOp "->>"
1015−
1016−-- | Get JSON value at a specified path.
1017−(.#>)
1018− :: (json `In` PGJsonType, PGTextArray "(.#>)" path)
1019− => Expression commons schemas params grp from (nullity json)
1020− -> Expression commons schemas params grp from (nullity path)
1021− -> Expression commons schemas params grp from ('Null json)
1022−infixl 8 .#>
1023−(.#>) = unsafeBinaryOp "#>"
1024−
1025−-- | Get JSON value at a specified path as text.
1026−(.#>>)
1027− :: (json `In` PGJsonType, PGTextArray "(.#>>)" path)
1028− => Expression commons schemas params grp from (nullity json)
1029− -> Expression commons schemas params grp from (nullity path)
1030− -> Expression commons schemas params grp from ('Null 'PGtext)
1031−infixl 8 .#>>
1032−(.#>>) = unsafeBinaryOp "#>>"
1033−
1034−-- Additional jsonb operators
1035−
1036−-- | Does the left JSON value contain the right JSON path/value entries at the
1037−-- top level?
1038−(.@>)
1039− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1040− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1041− -> Condition commons schemas params grp from
1042−infixl 9 .@>
1043−(.@>) = unsafeBinaryOp "@>"
1044−
1045−-- | Are the left JSON path/value entries contained at the top level within the
1046−-- right JSON value?
1047−(.<@)
1048− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1049− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1050− -> Condition commons schemas params grp from
1051−infixl 9 .<@
1052−(.<@) = unsafeBinaryOp "<@"
1053−
1054−-- | Does the string exist as a top-level key within the JSON value?
1055−(.?)
1056− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1057− -> Expression commons schemas params grp from (nullity 'PGtext)
1058− -> Condition commons schemas params grp from
1059−infixl 9 .?
1060−(.?) = unsafeBinaryOp "?"
1061−
1062−-- | Do any of these array strings exist as top-level keys?
1063−(.?|)
1064− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1065− -> Expression commons schemas params grp from (nullity ('PGvararray ('NotNull 'PGtext)))
1066− -> Condition commons schemas params grp from
1067−infixl 9 .?|
1068−(.?|) = unsafeBinaryOp "?|"
1069−
1070−-- | Do all of these array strings exist as top-level keys?
1071−(.?&)
1072− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1073− -> Expression commons schemas params grp from (nullity ('PGvararray ('NotNull 'PGtext)))
1074− -> Condition commons schemas params grp from
1075−infixl 9 .?&
1076−(.?&) = unsafeBinaryOp "?&"
1077−
1078−-- | Concatenate two jsonb values into a new jsonb value.
1079−instance
1080− Semigroup (Expression commons schemas from grouping param (nullity 'PGjsonb)) where
1081− (<>) = unsafeBinaryOp "||"
1082−
1083−-- | Delete a key or keys from a JSON object, or remove an array element.
1084−--
1085−-- If the right operand is..
1086−--
1087−-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1088−-- are matched based on their key value.
1089−--
1090−-- @ text[] @: Delete multiple key/value pairs or string elements
1091−-- from left operand. Key/value pairs are matched based on their key value.
1092−--
1093−-- @ integer @: Delete the array element with specified index (Negative integers
1094−-- count from the end). Throws an error if top level container is not an array.
1095−(.-.)
1096− :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1097− => Expression commons schemas params grp from (nullity 'PGjsonb)
1098− -> Expression commons schemas params grp from (nullity key)
1099− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1100−infixl 6 .-.
1101−(.-.) = unsafeBinaryOp "-"
1102−
1103−-- | Delete the field or element with specified path (for JSON arrays, negative
1104−-- integers count from the end)
1105−(#-.)
1106− :: PGTextArray "(#-.)" arrayty
1107− => Expression commons schemas params grp from (nullity 'PGjsonb)
1108− -> Expression commons schemas params grp from (nullity arrayty)
1109− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1110−infixl 6 #-.
1111−(#-.) = unsafeBinaryOp "#-"
1112−
1113−{-----------------------------------------
1114−Table 9.45: JSON creation functions
1115−-----------------------------------------}
1116−
1117−-- | Literal binary JSON
1118−jsonbLit
1119− :: JSON.ToJSON x
1120− => x -> Expression commons schemas params grp from (nullity 'PGjsonb)
1121−jsonbLit = cast jsonb . UnsafeExpression
1122− . singleQuotedUtf8 . toStrict . JSON.encode
1123−
1124−-- | Literal JSON
1125−jsonLit
1126− :: JSON.ToJSON x
1127− => x -> Expression commons schemas params grp from (nullity 'PGjson)
1128−jsonLit = cast json . UnsafeExpression
1129− . singleQuotedUtf8 . toStrict . JSON.encode
1130−
1131−-- | Returns the value as json. Arrays and composites are converted
1132−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1133−-- type to json, the cast function will be used to perform the conversion;
1134−-- otherwise, a scalar value is produced. For any scalar type other than a
1135−-- number, a Boolean, or a null value, the text representation will be used, in
1136−-- such a fashion that it is a valid json value.
1137−toJson
1138− :: Expression commons schemas params grp from (nullity ty)
1139− -> Expression commons schemas params grp from (nullity 'PGjson)
1140−toJson = unsafeFunction "to_json"
1141−
1142−-- | Returns the value as jsonb. Arrays and composites are converted
1143−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1144−-- type to json, the cast function will be used to perform the conversion;
1145−-- otherwise, a scalar value is produced. For any scalar type other than a
1146−-- number, a Boolean, or a null value, the text representation will be used, in
1147−-- such a fashion that it is a valid jsonb value.
1148−toJsonb
1149− :: Expression commons schemas params grp from (nullity ty)
1150− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1151−toJsonb = unsafeFunction "to_jsonb"
1152−
1153−-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1154−-- becomes a JSON array of arrays.
1155−arrayToJson
1156− :: PGArray "arrayToJson" arr
1157− => Expression commons schemas params grp from (nullity arr)
1158− -> Expression commons schemas params grp from (nullity 'PGjson)
1159−arrayToJson = unsafeFunction "array_to_json"
1160−
1161−-- | Returns the row as a JSON object.
1162−rowToJson
1163− :: Expression commons schemas params grp from (nullity ('PGcomposite ty))
1164− -> Expression commons schemas params grp from (nullity 'PGjson)
1165−rowToJson = unsafeFunction "row_to_json"
1166−
1167−-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1168−-- argument list.
1169−jsonBuildArray
1170− :: SListI elems
1171− => NP (Expression commons schemas params grp from) elems
1172− -> Expression commons schemas params grp from (nullity 'PGjson)
1173−jsonBuildArray = unsafeVariadicFunction "json_build_array"
1174−
1175−-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1176−-- variadic argument list.
1177−jsonbBuildArray
1178− :: SListI elems
1179− => NP (Expression commons schemas params grp from) elems
1180− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1181−jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1182−
1183−unsafeRowFunction
1184− :: All Top elems
1185− => NP (Aliased (Expression commons schemas params grp from)) elems
1186− -> [ByteString]
1187−unsafeRowFunction =
1188− (`appEndo` []) . hcfoldMap (Proxy :: Proxy Top)
1189− (\(col `As` name) -> Endo $ \xs ->
1190− renderAliasString name : renderSQL col : xs)
1191− where
1192− renderAliasString :: KnownSymbol alias => Alias alias -> ByteString
1193− renderAliasString = singleQuotedText . fromString . symbolVal
1194−
1195−-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1196−-- argument list. The elements of the argument list must alternate between text
1197−-- and values.
1198−jsonBuildObject
1199− :: All Top elems
1200− => NP (Aliased (Expression commons schemas params grp from)) elems
1201− -> Expression commons schemas params grp from (nullity 'PGjson)
1202−jsonBuildObject
1203− = unsafeFunction "json_build_object"
1204− . UnsafeExpression
1205− . commaSeparated
1206− . unsafeRowFunction
1207−
1208−-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1209−-- variadic argument list. The elements of the argument list must alternate
1210−-- between text and values.
1211−jsonbBuildObject
1212− :: All Top elems
1213− => NP (Aliased (Expression commons schemas params grp from)) elems
1214− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1215−jsonbBuildObject
1216− = unsafeFunction "jsonb_build_object"
1217− . UnsafeExpression
1218− . commaSeparated
1219− . unsafeRowFunction
1220−
1221−-- | Builds a JSON object out of a text array. The array must have either
1222−-- exactly one dimension with an even number of members, in which case they are
1223−-- taken as alternating key/value pairs, or two dimensions such that each inner
1224−-- array has exactly two elements, which are taken as a key/value pair.
1225−jsonObject
1226− :: PGArrayOf "jsonObject" arr ('NotNull 'PGtext)
1227− => Expression commons schemas params grp from (nullity arr)
1228− -> Expression commons schemas params grp from (nullity 'PGjson)
1229−jsonObject = unsafeFunction "json_object"
1230−
1231−-- | Builds a binary JSON object out of a text array. The array must have either
1232−-- exactly one dimension with an even number of members, in which case they are
1233−-- taken as alternating key/value pairs, or two dimensions such that each inner
1234−-- array has exactly two elements, which are taken as a key/value pair.
1235−jsonbObject
1236− :: PGArrayOf "jsonbObject" arr ('NotNull 'PGtext)
1237− => Expression commons schemas params grp from (nullity arr)
1238− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1239−jsonbObject = unsafeFunction "jsonb_object"
1240−
1241−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1242−-- keys and one for values, that are zipped pairwise to create a JSON object.
1243−jsonZipObject
1244− :: ( PGArrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1245− , PGArrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
1246− => Expression commons schemas params grp from (nullity keysArray)
1247− -> Expression commons schemas params grp from (nullity valuesArray)
1248− -> Expression commons schemas params grp from (nullity 'PGjson)
1249−jsonZipObject ks vs =
1250− unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1251−
1252−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1253−-- keys and one for values, that are zipped pairwise to create a binary JSON
1254−-- object.
1255−jsonbZipObject
1256− :: ( PGArrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1257− , PGArrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
1258− => Expression commons schemas params grp from (nullity keysArray)
1259− -> Expression commons schemas params grp from (nullity valuesArray)
1260− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1261−jsonbZipObject ks vs =
1262− unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1263−
1264−{-----------------------------------------
1265−Table 9.46: JSON processing functions
1266−-----------------------------------------}
1267−
1268−-- | Returns the number of elements in the outermost JSON array.
1269−jsonArrayLength
1270− :: Expression commons schemas params grp from (nullity 'PGjson)
1271− -> Expression commons schemas params grp from (nullity 'PGint4)
1272−jsonArrayLength = unsafeFunction "json_array_length"
1273−
1274−-- | Returns the number of elements in the outermost binary JSON array.
1275−jsonbArrayLength
1276− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1277− -> Expression commons schemas params grp from (nullity 'PGint4)
1278−jsonbArrayLength = unsafeFunction "jsonb_array_length"
1279−
1280−-- | Returns JSON value pointed to by the given path (equivalent to #>
1281−-- operator).
1282−jsonExtractPath
1283− :: SListI elems
1284− => Expression commons schemas params grp from (nullity 'PGjson)
1285− -> NP (Expression commons schemas params grp from) elems
1286− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1287−jsonExtractPath x xs =
1288− unsafeVariadicFunction "json_extract_path" (x :* xs)
1289−
1290−-- | Returns JSON value pointed to by the given path (equivalent to #>
1291−-- operator).
1292−jsonbExtractPath
1293− :: SListI elems
1294− => Expression commons schemas params grp from (nullity 'PGjsonb)
1295− -> NP (Expression commons schemas params grp from) elems
1296− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1297−jsonbExtractPath x xs =
1298− unsafeVariadicFunction "jsonb_extract_path" (x :* xs)
1299−
1300−-- | Returns JSON value pointed to by the given path (equivalent to #>
1301−-- operator), as text.
1302−jsonExtractPathAsText
1303− :: SListI elems
1304− => Expression commons schemas params grp from (nullity 'PGjson)
1305− -> NP (Expression commons schemas params grp from) elems
1306− -> Expression commons schemas params grp from (nullity 'PGjson)
1307−jsonExtractPathAsText x xs =
1308− unsafeVariadicFunction "json_extract_path_text" (x :* xs)
1309−
1310−-- | Returns JSON value pointed to by the given path (equivalent to #>
1311−-- operator), as text.
1312−jsonbExtractPathAsText
1313− :: SListI elems
1314− => Expression commons schemas params grp from (nullity 'PGjsonb)
1315− -> NP (Expression commons schemas params grp from) elems
1316− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1317−jsonbExtractPathAsText x xs =
1318− unsafeVariadicFunction "jsonb_extract_path_text" (x :* xs)
1319−
1320−-- | Returns the type of the outermost JSON value as a text string. Possible
1321−-- types are object, array, string, number, boolean, and null.
1322−jsonTypeof
1323− :: Expression commons schemas params grp from (nullity 'PGjson)
1324− -> Expression commons schemas params grp from (nullity 'PGtext)
1325−jsonTypeof = unsafeFunction "json_typeof"
1326−
1327−-- | Returns the type of the outermost binary JSON value as a text string.
1328−-- Possible types are object, array, string, number, boolean, and null.
1329−jsonbTypeof
1330− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1331− -> Expression commons schemas params grp from (nullity 'PGtext)
1332−jsonbTypeof = unsafeFunction "jsonb_typeof"
1333−
1334−-- | Returns its argument with all object fields that have null values omitted.
1335−-- Other null values are untouched.
1336−jsonStripNulls
1337− :: Expression commons schemas params grp from (nullity 'PGjson)
1338− -> Expression commons schemas params grp from (nullity 'PGjson)
1339−jsonStripNulls = unsafeFunction "json_strip_nulls"
1340−
1341−-- | Returns its argument with all object fields that have null values omitted.
1342−-- Other null values are untouched.
1343−jsonbStripNulls
1344− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1345− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1346−jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1347−
1348−-- | @ jsonbSet target path new_value create_missing @
1349−--
1350−-- Returns target with the section designated by path replaced by new_value,
1351−-- or with new_value added if create_missing is true ( default is true) and the
1352−-- item designated by path does not exist. As with the path orientated
1353−-- operators, negative integers that appear in path count from the end of JSON
1354−-- arrays.
1355−jsonbSet
1356− :: PGTextArray "jsonbSet" arr
1357− => Expression commons schemas params grp from (nullity 'PGjsonb)
1358− -> Expression commons schemas params grp from (nullity arr)
1359− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1360− -> Maybe (Expression commons schemas params grp from (nullity 'PGbool))
1361− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1362−jsonbSet tgt path val createMissing = case createMissing of
1363− Just m -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* m :* Nil)
1364− Nothing -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* Nil)
1365−
1366−-- | @ jsonbInsert target path new_value insert_after @
1367−--
1368−-- Returns target with new_value inserted. If target section designated by
1369−-- path is in a JSONB array, new_value will be inserted before target or after
1370−-- if insert_after is true (default is false). If target section designated by
1371−-- path is in JSONB object, new_value will be inserted only if target does not
1372−-- exist. As with the path orientated operators, negative integers that appear
1373−-- in path count from the end of JSON arrays.
1374−jsonbInsert
1375− :: PGTextArray "jsonbInsert" arr
1376− => Expression commons schemas params grp from (nullity 'PGjsonb)
1377− -> Expression commons schemas params grp from (nullity arr)
1378− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1379− -> Maybe (Expression commons schemas params grp from (nullity 'PGbool))
1380− -> Expression commons schemas params grp from (nullity 'PGjsonb)
1381−jsonbInsert tgt path val insertAfter = case insertAfter of
1382− Just i -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1383− Nothing -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* Nil)
1384−
1385−-- | Returns its argument as indented JSON text.
1386−jsonbPretty
1387− :: Expression commons schemas params grp from (nullity 'PGjsonb)
1388− -> Expression commons schemas params grp from (nullity 'PGtext)
1389−jsonbPretty = unsafeFunction "jsonb_pretty"
1390−
1391−{-----------------------------------------
1392−aggregation
1393−-----------------------------------------}
1394−
1395−-- | escape hatch to define aggregate functions
1396−unsafeAggregate
1397− :: ByteString -- ^ aggregate function
1398− -> Expression commons schemas from 'Ungrouped params (xty)
1399− -> Expression commons schemas from ('Grouped bys) params (yty)
1400−unsafeAggregate fun x = UnsafeExpression $ mconcat
1401− [fun, "(", renderSQL x, ")"]
1402−
1403−-- | escape hatch to define aggregate functions over distinct values
1404−unsafeAggregateDistinct
1405− :: ByteString -- ^ aggregate function
1406− -> Expression commons schemas from 'Ungrouped params (xty)
1407− -> Expression commons schemas from ('Grouped bys) params (yty)
1408−unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
1409− [fun, "(DISTINCT ", renderSQL x, ")"]
1410−
1411−-- | >>> :{
1412−-- let
1413−-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Null 'PGnumeric)
1414−-- expression = sum_ #col
1415−-- in printSQL expression
1416−-- :}
1417−-- sum("col")
1418−sum_
1419− :: ty `In` PGNum
1420− => Expression commons schemas from 'Ungrouped params (nullity ty)
1421− -- ^ what to sum
1422− -> Expression commons schemas from ('Grouped bys) params (nullity ty)
1423−sum_ = unsafeAggregate "sum"
1424−
1425−-- | >>> :{
1426−-- let
1427−-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: nullity 'PGnumeric]] (nullity 'PGnumeric)
1428−-- expression = sumDistinct #col
1429−-- in printSQL expression
1430−-- :}
1431−-- sum(DISTINCT "col")
1432−sumDistinct
1433− :: ty `In` PGNum
1434− => Expression commons schemas from 'Ungrouped params (nullity ty)
1435− -- ^ what to sum
1436− -> Expression commons schemas from ('Grouped bys) params (nullity ty)
1437−sumDistinct = unsafeAggregateDistinct "sum"
1438−
1439−-- | A constraint for `PGType`s that you can take averages of and the resulting
1440−-- `PGType`.
1441−class PGAvg ty avg | ty -> avg where
1442− avg, avgDistinct
1443− :: Expression commons schemas from 'Ungrouped params (nullity ty)
1444− -- ^ what to average
1445− -> Expression commons schemas from ('Grouped bys) params (nullity avg)
1446− avg = unsafeAggregate "avg"
1447− avgDistinct = unsafeAggregateDistinct "avg"
1448−instance PGAvg 'PGint2 'PGnumeric
1449−instance PGAvg 'PGint4 'PGnumeric
1450−instance PGAvg 'PGint8 'PGnumeric
1451−instance PGAvg 'PGnumeric 'PGnumeric
1452−instance PGAvg 'PGfloat4 'PGfloat8
1453−instance PGAvg 'PGfloat8 'PGfloat8
1454−instance PGAvg 'PGinterval 'PGinterval
1455−
1456−-- | >>> :{
1457−-- let
1458−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1459−-- expression = bitAnd #col
1460−-- in printSQL expression
1461−-- :}
1462−-- bit_and("col")
1463−bitAnd
1464− :: int `In` PGIntegral
1465− => Expression commons schemas from 'Ungrouped params (nullity int)
1466− -- ^ what to aggregate
1467− -> Expression commons schemas from ('Grouped bys) params (nullity int)
1468−bitAnd = unsafeAggregate "bit_and"
1469−
1470−-- | >>> :{
1471−-- let
1472−-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1473−-- expression = bitOr #col
1474−-- in printSQL expression
1475−-- :}
1476−-- bit_or("col")
1477−bitOr
1478− :: int `In` PGIntegral
1479− => Expression commons schemas from 'Ungrouped params (nullity int)
1480− -- ^ what to aggregate
1481− -> Expression commons schemas from ('Grouped bys) params (nullity int)
1482−bitOr = unsafeAggregate "bit_or"
1483−
1484−-- | >>> :{
1485−-- let
1486−-- expression :: Expression commons schemas params ('Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1487−-- expression = bitAndDistinct #col
1488−-- in printSQL expression
1489−-- :}
1490−-- bit_and(DISTINCT "col")
1491−bitAndDistinct
1492− :: int `In` PGIntegral
1493− => Expression commons schemas from 'Ungrouped params (nullity int)
1494− -- ^ what to aggregate
1495− -> Expression commons schemas from ('Grouped bys) params (nullity int)
1496−bitAndDistinct = unsafeAggregateDistinct "bit_and"
1497−
1498−-- | >>> :{
1499−-- let
1500−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1501−-- expression = bitOrDistinct #col
1502−-- in printSQL expression
1503−-- :}
1504−-- bit_or(DISTINCT "col")
1505−bitOrDistinct
1506− :: int `In` PGIntegral
1507− => Expression commons schemas from 'Ungrouped params (nullity int)
1508− -- ^ what to aggregate
1509− -> Expression commons schemas from ('Grouped bys) params (nullity int)
1510−bitOrDistinct = unsafeAggregateDistinct "bit_or"
1511−
1512−-- | >>> :{
1513−-- let
1514−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1515−-- expression = boolAnd #col
1516−-- in printSQL expression
1517−-- :}
1518−-- bool_and("col")
1519−boolAnd
1520− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1521− -- ^ what to aggregate
1522− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1523−boolAnd = unsafeAggregate "bool_and"
1524−
1525−-- | >>> :{
1526−-- let
1527−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1528−-- expression = boolOr #col
1529−-- in printSQL expression
1530−-- :}
1531−-- bool_or("col")
1532−boolOr
1533− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1534− -- ^ what to aggregate
1535− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1536−boolOr = unsafeAggregate "bool_or"
1537−
1538−-- | >>> :{
1539−-- let
1540−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1541−-- expression = boolAndDistinct #col
1542−-- in printSQL expression
1543−-- :}
1544−-- bool_and(DISTINCT "col")
1545−boolAndDistinct
1546− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1547− -- ^ what to aggregate
1548− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1549−boolAndDistinct = unsafeAggregateDistinct "bool_and"
1550−
1551−-- | >>> :{
1552−-- let
1553−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1554−-- expression = boolOrDistinct #col
1555−-- in printSQL expression
1556−-- :}
1557−-- bool_or(DISTINCT "col")
1558−boolOrDistinct
1559− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1560− -- ^ what to aggregate
1561− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1562−boolOrDistinct = unsafeAggregateDistinct "bool_or"
1563−
1564−-- | A special aggregation that does not require an input
1565−--
1566−-- >>> printSQL countStar
1567−-- count(*)
1568−countStar
1569− :: Expression commons schemas from ('Grouped bys) params ('NotNull 'PGint8)
1570−countStar = UnsafeExpression $ "count(*)"
1571−
1572−-- | >>> :{
1573−-- let
1574−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1575−-- expression = count #col
1576−-- in printSQL expression
1577−-- :}
1578−-- count("col")
1579−count
1580− :: Expression commons schemas from 'Ungrouped params ty
1581− -- ^ what to count
1582− -> Expression commons schemas from ('Grouped bys) params ('NotNull 'PGint8)
1583−count = unsafeAggregate "count"
1584−
1585−-- | >>> :{
1586−-- let
1587−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1588−-- expression = countDistinct #col
1589−-- in printSQL expression
1590−-- :}
1591−-- count(DISTINCT "col")
1592−countDistinct
1593− :: Expression commons schemas from 'Ungrouped params ty
1594− -- ^ what to count
1595− -> Expression commons schemas from ('Grouped bys) params ('NotNull 'PGint8)
1596−countDistinct = unsafeAggregateDistinct "count"
1597−
1598−-- | synonym for `boolAnd`
1599−--
1600−-- >>> :{
1601−-- let
1602−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1603−-- expression = every #col
1604−-- in printSQL expression
1605−-- :}
1606−-- every("col")
1607−every
1608− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1609− -- ^ what to aggregate
1610− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1611−every = unsafeAggregate "every"
1612−
1613−-- | synonym for `boolAndDistinct`
1614−--
1615−-- >>> :{
1616−-- let
1617−-- expression :: Expression commons schemas params (Grouped bys) '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1618−-- expression = everyDistinct #col
1619−-- in printSQL expression
1620−-- :}
1621−-- every(DISTINCT "col")
1622−everyDistinct
1623− :: Expression commons schemas from 'Ungrouped params (nullity 'PGbool)
1624− -- ^ what to aggregate
1625− -> Expression commons schemas from ('Grouped bys) params (nullity 'PGbool)
1626−everyDistinct = unsafeAggregateDistinct "every"
1627−
1628−-- | minimum and maximum aggregation
1629−max_, min_, maxDistinct, minDistinct
1630− :: Expression commons schemas from 'Ungrouped params (nullity ty)
1631− -- ^ what to aggregate
1632− -> Expression commons schemas from ('Grouped bys) params (nullity ty)
1633−max_ = unsafeAggregate "max"
1634−min_ = unsafeAggregate "min"
1635−maxDistinct = unsafeAggregateDistinct "max"
1636−minDistinct = unsafeAggregateDistinct "min"
1637−
1638−{-----------------------------------------
1639−type expressions
1640−-----------------------------------------}
1641−
1642−-- | `TypeExpression`s are used in `cast`s and `createTable` commands.
1643−newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
1644− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1645− deriving (GHC.Generic,Show,Eq,Ord,NFData)
1646−instance RenderSQL (TypeExpression schemas ty) where
1647− renderSQL = renderTypeExpression
1648−
1649−-- | The enum or composite type in a `Typedef` can be expressed by its alias.
1650−typedef
1651− :: (Has sch schemas schema, Has td schema ('Typedef ty))
1652− => QualifiedAlias sch td
1653− -> TypeExpression schemas (nullity ty)
1654−typedef = UnsafeTypeExpression . renderSQL
1655−
1656−-- | The composite type corresponding to a `Table` definition can be expressed
1657−-- by its alias.
1658−typetable
1659− :: (Has sch schemas schema, Has tab schema ('Table table))
1660− => QualifiedAlias sch tab
1661− -> TypeExpression schemas (nullity ('PGcomposite (TableToRow table)))
1662−typetable = UnsafeTypeExpression . renderSQL
1663−
1664−-- | The composite type corresponding to a `View` definition can be expressed
1665−-- by its alias.
1666−typeview
1667− :: (Has sch schemas schema, Has vw schema ('View view))
1668− => QualifiedAlias sch vw
1669− -> TypeExpression schemas (nullity ('PGcomposite view))
1670−typeview = UnsafeTypeExpression . renderSQL
1671−
1672−-- | logical Boolean (true/false)
1673−bool :: TypeExpression schemas (nullity 'PGbool)
1674−bool = UnsafeTypeExpression "bool"
1675−-- | signed two-byte integer
1676−int2, smallint :: TypeExpression schemas (nullity 'PGint2)
1677−int2 = UnsafeTypeExpression "int2"
1678−smallint = UnsafeTypeExpression "smallint"
1679−-- | signed four-byte integer
1680−int4, int, integer :: TypeExpression schemas (nullity 'PGint4)
1681−int4 = UnsafeTypeExpression "int4"
1682−int = UnsafeTypeExpression "int"
1683−integer = UnsafeTypeExpression "integer"
1684−-- | signed eight-byte integer
1685−int8, bigint :: TypeExpression schemas (nullity 'PGint8)
1686−int8 = UnsafeTypeExpression "int8"
1687−bigint = UnsafeTypeExpression "bigint"
1688−-- | arbitrary precision numeric type
1689−numeric :: TypeExpression schemas (nullity 'PGnumeric)
1690−numeric = UnsafeTypeExpression "numeric"
1691−-- | single precision floating-point number (4 bytes)
1692−float4, real :: TypeExpression schemas (nullity 'PGfloat4)
1693−float4 = UnsafeTypeExpression "float4"
1694−real = UnsafeTypeExpression "real"
1695−-- | double precision floating-point number (8 bytes)
1696−float8, doublePrecision :: TypeExpression schemas (nullity 'PGfloat8)
1697−float8 = UnsafeTypeExpression "float8"
1698−doublePrecision = UnsafeTypeExpression "double precision"
1699−-- | variable-length character string
1700−text :: TypeExpression schemas (nullity 'PGtext)
1701−text = UnsafeTypeExpression "text"
1702−-- | fixed-length character string
1703−char, character
1704− :: forall n schemas nullity. (KnownNat n, 1 <= n)
1705− => TypeExpression schemas (nullity ('PGchar n))
1706−char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
1707−character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
1708−-- | variable-length character string
1709−varchar, characterVarying
1710− :: forall n schemas nullity. (KnownNat n, 1 <= n)
1711− => TypeExpression schemas (nullity ('PGvarchar n))
1712−varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
1713−characterVarying = UnsafeTypeExpression $
1714− "character varying(" <> renderNat @n <> ")"
1715−-- | binary data ("byte array")
1716−bytea :: TypeExpression schemas (nullity 'PGbytea)
1717−bytea = UnsafeTypeExpression "bytea"
1718−-- | date and time (no time zone)
1719−timestamp :: TypeExpression schemas (nullity 'PGtimestamp)
1720−timestamp = UnsafeTypeExpression "timestamp"
1721−-- | date and time, including time zone
1722−timestampWithTimeZone :: TypeExpression schemas (nullity 'PGtimestamptz)
1723−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1724−-- | calendar date (year, month, day)
1725−date :: TypeExpression schemas (nullity 'PGdate)
1726−date = UnsafeTypeExpression "date"
1727−-- | time of day (no time zone)
1728−time :: TypeExpression schemas (nullity 'PGtime)
1729−time = UnsafeTypeExpression "time"
1730−-- | time of day, including time zone
1731−timeWithTimeZone :: TypeExpression schemas (nullity 'PGtimetz)
1732−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1733−-- | time span
1734−interval :: TypeExpression schemas (nullity 'PGinterval)
1735−interval = UnsafeTypeExpression "interval"
1736−-- | universally unique identifier
1737−uuid :: TypeExpression schemas (nullity 'PGuuid)
1738−uuid = UnsafeTypeExpression "uuid"
1739−-- | IPv4 or IPv6 host address
1740−inet :: TypeExpression schemas (nullity 'PGinet)
1741−inet = UnsafeTypeExpression "inet"
1742−-- | textual JSON data
1743−json :: TypeExpression schemas (nullity 'PGjson)
1744−json = UnsafeTypeExpression "json"
1745−-- | binary JSON data, decomposed
1746−jsonb :: TypeExpression schemas (nullity 'PGjsonb)
1747−jsonb = UnsafeTypeExpression "jsonb"
1748−-- | variable length array
1749−vararray
1750− :: TypeExpression schemas pg
1751− -> TypeExpression schemas (nullity ('PGvararray pg))
1752−vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
1753−-- | fixed length array
1754−--
1755−-- >>> renderSQL (fixarray @2 json)
1756−-- "json[2]"
1757−fixarray
1758− :: forall n schemas nullity pg. KnownNat n
1759− => TypeExpression schemas pg
1760− -> TypeExpression schemas (nullity ('PGfixarray n pg))
1761−fixarray ty = UnsafeTypeExpression $
1762− renderSQL ty <> "[" <> renderNat @n <> "]"
1763−
1764−-- | `pgtype` is a demoted version of a `PGType`
1765−class PGTyped schemas (ty :: NullityType) where
1766− pgtype :: TypeExpression schemas ty
1767−instance PGTyped schemas (nullity 'PGbool) where pgtype = bool
1768−instance PGTyped schemas (nullity 'PGint2) where pgtype = int2
1769−instance PGTyped schemas (nullity 'PGint4) where pgtype = int4
1770−instance PGTyped schemas (nullity 'PGint8) where pgtype = int8
1771−instance PGTyped schemas (nullity 'PGnumeric) where pgtype = numeric
1772−instance PGTyped schemas (nullity 'PGfloat4) where pgtype = float4
1773−instance PGTyped schemas (nullity 'PGfloat8) where pgtype = float8
1774−instance PGTyped schemas (nullity 'PGtext) where pgtype = text
1775−instance (KnownNat n, 1 <= n)
1776− => PGTyped schemas (nullity ('PGchar n)) where pgtype = char @n
1777−instance (KnownNat n, 1 <= n)
1778− => PGTyped schemas (nullity ('PGvarchar n)) where pgtype = varchar @n
1779−instance PGTyped schemas (nullity 'PGbytea) where pgtype = bytea
1780−instance PGTyped schemas (nullity 'PGtimestamp) where pgtype = timestamp
1781−instance PGTyped schemas (nullity 'PGtimestamptz) where pgtype = timestampWithTimeZone
1782−instance PGTyped schemas (nullity 'PGdate) where pgtype = date
1783−instance PGTyped schemas (nullity 'PGtime) where pgtype = time
1784−instance PGTyped schemas (nullity 'PGtimetz) where pgtype = timeWithTimeZone
1785−instance PGTyped schemas (nullity 'PGinterval) where pgtype = interval
1786−instance PGTyped schemas (nullity 'PGuuid) where pgtype = uuid
1787−instance PGTyped schemas (nullity 'PGjson) where pgtype = json
1788−instance PGTyped schemas (nullity 'PGjsonb) where pgtype = jsonb
1789−instance PGTyped schemas ty
1790− => PGTyped schemas (nullity ('PGvararray ty)) where
1791− pgtype = vararray (pgtype @schemas @ty)
1792−instance (KnownNat n, PGTyped schemas ty)
1793− => PGTyped schemas (nullity ('PGfixarray n ty)) where
1794− pgtype = fixarray @n (pgtype @schemas @ty)
1795−
1796−{-----------------------------------------
1797−Sorting
1798−-----------------------------------------}
1799−
1800−-- | `SortExpression`s are used by `sortBy` to optionally sort the results
1801−-- of a `Query`. `Asc` or `Desc` set the sort direction of a `NotNull` result
1802−-- column to ascending or descending. Ascending order puts smaller values
1803−-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
1804−-- descending order is determined with the `.>` operator. `AscNullsFirst`,
1805−-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
1806−-- determine whether nulls appear before or after non-null values in the sort
1807−-- ordering of a `Null` result column.
1808−data SortExpression commons schemas params grp from where
1809− Asc
1810− :: Expression commons schemas params grp from ('NotNull ty)
1811− -> SortExpression commons schemas params grp from
1812− Desc
1813− :: Expression commons schemas params grp from ('NotNull ty)
1814− -> SortExpression commons schemas params grp from
1815− AscNullsFirst
1816− :: Expression commons schemas params grp from ('Null ty)
1817− -> SortExpression commons schemas params grp from
1818− AscNullsLast
1819− :: Expression commons schemas params grp from ('Null ty)
1820− -> SortExpression commons schemas params grp from
1821− DescNullsFirst
1822− :: Expression commons schemas params grp from ('Null ty)
1823− -> SortExpression commons schemas params grp from
1824− DescNullsLast
1825− :: Expression commons schemas params grp from ('Null ty)
1826− -> SortExpression commons schemas params grp from
1827−deriving instance Show (SortExpression commons schemas params grp from)
1828−
1829−class OrderBy expr where
1830− orderBy
1831− :: [SortExpression commons schemas params grp from]
1832− -> expr commons schemas params grp from
1833− -> expr commons schemas params grp from
1834−
1835−-- | Render a `SortExpression`.
1836−instance RenderSQL (SortExpression commons schemas params grp from) where
1837− renderSQL = \case
1838− Asc expression -> renderSQL expression <+> "ASC"
1839− Desc expression -> renderSQL expression <+> "DESC"
1840− AscNullsFirst expression -> renderSQL expression
1841− <+> "ASC NULLS FIRST"
1842− DescNullsFirst expression -> renderSQL expression
1843− <+> "DESC NULLS FIRST"
1844− AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
1845− DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
1846−
1847−data WindowDefinition commons schemas params grp from where
1848− WindowDefinition
1849− :: SListI bys
1850− => NP (Expression commons schemas params grp from) bys
1851− -> [SortExpression commons schemas params grp from]
1852− -> WindowDefinition commons schemas params grp from
1853−
1854−instance OrderBy WindowDefinition where
1855− orderBy sortsR (WindowDefinition parts sortsL)
1856− = WindowDefinition parts (sortsL ++ sortsR)
1857−
1858−instance RenderSQL (WindowDefinition commons schemas from grp params) where
1859− renderSQL (WindowDefinition part ord) =
1860− renderPartitionByClause part <> renderOrderByClause ord
1861− where
1862− renderPartitionByClause = \case
1863− Nil -> ""
1864− parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
1865− renderOrderByClause = \case
1866− [] -> ""
1867− srts -> " ORDER" <+> "BY"
1868− <+> commaSeparated (renderSQL <$> srts)
1869−
1870−partitionBy
1871− :: SListI bys
1872− => NP (Expression commons schemas params grp from) bys
1873− -> WindowDefinition commons schemas params grp from
1874−partitionBy bys = WindowDefinition bys []
1875−
1876−newtype WindowFunction
1877− (commons :: FromType)
1878− (schemas :: SchemasType)
1879− (params :: [NullityType])
1880− (grp :: Grouping)
1881− (from :: FromType)
1882− (ty :: NullityType)
1883− = UnsafeWindowFunction { renderWindowFunction :: ByteString }
1884− deriving (GHC.Generic,Show,Eq,Ord,NFData)
1885−
1886−instance RenderSQL (WindowFunction commons schemas params grp from ty) where
1887− renderSQL = renderWindowFunction
1888−
1889−{- | rank of the current row with gaps; same as `rowNumber` of its first peer
1890−>>> printSQL rank
1891−rank()
1892−-}
1893−rank :: WindowFunction commons schemas from grp params ('NotNull 'PGint8)
1894−rank = UnsafeWindowFunction "rank()"
1895−
1896−{- | number of the current row within its partition, counting from 1
1897−>>> printSQL rowNumber
1898−row_number()
1899−-}
1900−rowNumber :: WindowFunction commons schemas from grp params ('NotNull 'PGint8)
1901−rowNumber = UnsafeWindowFunction "row_number()"
1902−
1903−{- | rank of the current row without gaps; this function counts peer groups
1904−>>> printSQL denseRank
1905−dense_rank()
1906−-}
1907−denseRank :: WindowFunction commons schemas from grp params ('NotNull 'PGint8)
1908−denseRank = UnsafeWindowFunction "dense_rank()"
1909−
1910−{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
1911−>>> printSQL percentRank
1912−percent_rank()
1913−-}
1914−percentRank :: WindowFunction commons schemas from grp params ('NotNull 'PGfloat8)
1915−percentRank = UnsafeWindowFunction "percent_rank()"
1916−
1917−{- | cumulative distribution: (number of partition rows
1918−preceding or peer with current row) / total partition rows
1919−>>> printSQL cumeDist
1920−cume_dist()
1921−-}
1922−cumeDist :: WindowFunction commons schemas from grp params ('NotNull 'PGfloat8)
1923−cumeDist = UnsafeWindowFunction "cume_dist()"