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