@@ -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,585 +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− , Distinction (..)
139− , PGAvg
140− -- * Window Functions
141− , WindowDefinition (..)
142− , partitionBy
143− , WindowFunction (..)
144− , rank
145− , rowNumber
146− , denseRank
147− , percentRank
148− , cumeDist
149− , ntile
150− , lag
151− , lead
152− , firstValue
153− , lastValue
154− , nthValue
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 (..)
198− , (:*:) (..)
199− , I (..)
20059 , K (..)
60+ , unK
20161 ) where
20262
20363import Control.Category
20464import Control.DeepSeq
20565import Data.ByteString (ByteString)
206−import Data.ByteString.Lazy (toStrict)
20766import Data.Function ((&))
20867import Data.Semigroup hiding (All)
209−import qualified Data.Aeson as JSON
210−import Data.Ratio
21168import Data.String
212−import Data.Word
213−import Generics.SOP hiding (from)
214−import GHC.Generics ((:*:) (..))
69+import Generics.SOP hiding (All, from)
21570import GHC.OverloadedLabels
21671import GHC.TypeLits
72+import Numeric
21773import Prelude hiding (id, (.))
21874
219−import qualified Data.ByteString as ByteString
22075import qualified GHC.Generics as GHC
22176
77+import Squeal.PostgreSQL.Alias
78+import Squeal.PostgreSQL.List
22279import Squeal.PostgreSQL.Render
22380import Squeal.PostgreSQL.Schema
22481
82+-- $setup
83+-- >>> import Squeal.PostgreSQL
84+
22585{-----------------------------------------
22686column expressions
22787-----------------------------------------}
22888
22989{- | `Expression`s are used in a variety of contexts,
230−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,
23192as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
23293`Squeal.PostgreSQL.Manipulation.update`,
233−or in search `Condition`s in a number of commands.
94+or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
23495
23596The expression syntax allows the calculation of
23697values from primitive expression using arithmetic, logical,
23798and 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`.
238113-}
239114newtype Expression
240− (grp :: Grouping)
115+ (outer :: FromType)
241116 (commons :: FromType)
117+ (grp :: Grouping)
242118 (schemas :: SchemasType)
243119 (params :: [NullityType])
244120 (from :: FromType)
245121 (ty :: NullityType)
246122 = UnsafeExpression { renderExpression :: ByteString }
247123 deriving (GHC.Generic,Show,Eq,Ord,NFData)
248−
249−instance RenderSQL (Expression grp commons schemas params from ty) where
124+instance RenderSQL (Expression outer commons grp schemas params from ty) where
250125 renderSQL = renderExpression
251126
252−{- | A `HasParameter` constraint is used to indicate a value that is
253−supplied externally to a SQL statement.
254−`Squeal.PostgreSQL.PQ.manipulateParams`,
255−`Squeal.PostgreSQL.PQ.queryParams` and
256−`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
257−separately from the SQL command string, in which case `param`s are used to
258−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)
259181-}
260−class KnownNat n => HasParameter
261− (n :: Nat)
262− (params :: [NullityType])
263− (ty :: NullityType)
264− | n params -> ty where
265− -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
266− --
267− -- >>> let expr = parameter @1 int4 :: Expression grp '[] schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
268− -- >>> printSQL expr
269− -- ($1 :: int4)
270− parameter
271− :: TypeExpression schemas ty
272− -> Expression grp commons schemas params from ty
273− parameter ty = UnsafeExpression $ parenthesized $
274− "$" <> renderNat @n <+> "::"
275− <+> renderSQL ty
276−instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
277−instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
278− => HasParameter n (ty' : params) ty
279−
280−-- | `param` takes a `Nat` using type application and for basic types,
281−-- infers a `TypeExpression`.
282−--
283−-- >>> let expr = param @1 :: Expression grp commons schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
284−-- >>> printSQL expr
285−-- ($1 :: int4)
286−param
287− :: forall n commons schemas params from grp ty
288− . (PGTyped schemas ty, HasParameter n params ty)
289− => Expression grp commons schemas params from ty -- ^ param
290−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)
291214
292−instance (HasUnique tab from row, Has col row ty)
293− => 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
294217 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
295−instance (HasUnique tab from row, Has col row ty, tys ~ '[ty])
296− => IsLabel col (NP (Expression 'Ungrouped commons schemas params from) tys) where
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
297220 fromLabel = fromLabel @col :* Nil
298−instance (HasUnique tab from row, Has col row ty, column ~ (col ::: ty))
221+instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
299222 => IsLabel col
300− (Aliased (Expression 'Ungrouped commons schemas params from) column) where
223+ (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
301224 fromLabel = fromLabel @col `As` Alias
302−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])
303226 => IsLabel col
304− (NP (Aliased (Expression 'Ungrouped commons schemas params from)) columns) where
227+ (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
305228 fromLabel = fromLabel @col :* Nil
306229
307−instance (Has tab from row, Has col row ty)
308− => 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
309232 tab ! col = UnsafeExpression $
310233 renderSQL tab <> "." <> renderSQL col
311−instance (Has tab from row, Has col row ty, tys ~ '[ty])
312− => IsQualified tab col (NP (Expression 'Ungrouped commons schemas params from) tys) where
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
313236 tab ! col = tab ! col :* Nil
314−instance (Has tab from row, Has col row ty, column ~ (col ::: ty))
237+instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
315238 => IsQualified tab col
316− (Aliased (Expression 'Ungrouped commons schemas params from) column) where
239+ (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
317240 tab ! col = tab ! col `As` col
318−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])
319242 => IsQualified tab col
320− (NP (Aliased (Expression 'Ungrouped commons schemas params from)) columns) where
243+ (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
321244 tab ! col = tab ! col :* Nil
322245
323246instance
324− ( HasUnique tab from row
247+ ( HasUnique tab (Join outer from) row
325248 , Has col row ty
326249 , GroupedBy tab col bys
327250 ) => IsLabel col
328− (Expression ('Grouped bys) commons schemas params from ty) where
251+ (Expression outer commons ('Grouped bys) schemas params from ty) where
329252 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
330253instance
331− ( HasUnique tab from row
254+ ( HasUnique tab (Join outer from) row
332255 , Has col row ty
333256 , GroupedBy tab col bys
334257 , tys ~ '[ty]
335258 ) => IsLabel col
336− (NP (Expression ('Grouped bys) commons schemas params from) tys) where
259+ (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
337260 fromLabel = fromLabel @col :* Nil
338261instance
339− ( HasUnique tab from row
262+ ( HasUnique tab (Join outer from) row
340263 , Has col row ty
341264 , GroupedBy tab col bys
342265 , column ~ (col ::: ty)
343266 ) => IsLabel col
344− (Aliased (Expression ('Grouped bys) commons schemas params from) column) where
267+ (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
345268 fromLabel = fromLabel @col `As` Alias
346269instance
347− ( HasUnique tab from row
270+ ( HasUnique tab (Join outer from) row
348271 , Has col row ty
349272 , GroupedBy tab col bys
350273 , columns ~ '[col ::: ty]
351274 ) => IsLabel col
352− (NP (Aliased (Expression ('Grouped bys) commons schemas params from)) columns) where
275+ (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
353276 fromLabel = fromLabel @col :* Nil
354277
355278instance
356− ( Has tab from row
279+ ( Has tab (Join outer from) row
357280 , Has col row ty
358281 , GroupedBy tab col bys
359282 ) => IsQualified tab col
360− (Expression ('Grouped bys) commons schemas params from ty) where
283+ (Expression outer commons ('Grouped bys) schemas params from ty) where
361284 tab ! col = UnsafeExpression $
362285 renderSQL tab <> "." <> renderSQL col
363286instance
364− ( Has tab from row
287+ ( Has tab (Join outer from) row
365288 , Has col row ty
366289 , GroupedBy tab col bys
367290 , tys ~ '[ty]
368291 ) => IsQualified tab col
369− (NP (Expression ('Grouped bys) commons schemas params from) tys) where
292+ (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
370293 tab ! col = tab ! col :* Nil
371294instance
372− ( Has tab from row
295+ ( Has tab (Join outer from) row
373296 , Has col row ty
374297 , GroupedBy tab col bys
375298 , column ~ (col ::: ty)
376299 ) => IsQualified tab col
377− (Aliased (Expression ('Grouped bys) commons schemas params from) column) where
300+ (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
378301 tab ! col = tab ! col `As` col
379302instance
380− ( Has tab from row
303+ ( Has tab (Join outer from) row
381304 , Has col row ty
382305 , GroupedBy tab col bys
383306 , columns ~ '[col ::: ty]
384307 ) => IsQualified tab col
385− (NP (Aliased (Expression ('Grouped bys) commons schemas params from)) columns) where
308+ (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
386309 tab ! col = tab ! col :* Nil
387310
388−-- | analagous to `Nothing`
389−--
390−-- >>> printSQL null_
391−-- NULL
392−null_ :: Expression commons schemas rels grouping params ('Null ty)
393−null_ = UnsafeExpression "NULL"
394−
395−-- | analagous to `Just`
396−--
397−-- >>> printSQL $ notNull true
398−-- TRUE
399−notNull
400− :: Expression commons schemas rels grouping params ('NotNull ty)
401− -> Expression commons schemas rels grouping params ('Null ty)
402−notNull = UnsafeExpression . renderSQL
403−
404−-- | return the leftmost value which is not NULL
405−--
406−-- >>> printSQL $ coalesce [null_, true] false
407−-- COALESCE(NULL, TRUE, FALSE)
408−coalesce
409− :: [Expression grp commons schemas params from ('Null ty)]
410− -- ^ @NULL@s may be present
411− -> Expression grp commons schemas params from ('NotNull ty)
412− -- ^ @NULL@ is absent
413− -> Expression grp commons schemas params from ('NotNull ty)
414−coalesce nullxs notNullx = UnsafeExpression $
415− "COALESCE" <> parenthesized (commaSeparated
416− ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
417−
418−-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
419−--
420−-- >>> printSQL $ fromNull true null_
421−-- COALESCE(NULL, TRUE)
422−fromNull
423− :: Expression grp commons schemas params from ('NotNull ty)
424− -- ^ what to convert @NULL@ to
425− -> Expression grp commons schemas params from ('Null ty)
426− -> Expression grp commons schemas params from ('NotNull ty)
427−fromNull notNullx nullx = coalesce [nullx] notNullx
428−
429−-- | >>> printSQL $ null_ & isNull
430−-- NULL IS NULL
431−isNull
432− :: Expression grp commons schemas params from ('Null ty)
433− -- ^ possibly @NULL@
434− -> Condition grp commons schemas params from
435−isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
436−
437−-- | >>> printSQL $ null_ & isNotNull
438−-- NULL IS NOT NULL
439−isNotNull
440− :: Expression grp commons schemas params from ('Null ty)
441− -- ^ possibly @NULL@
442− -> Condition grp commons schemas params from
443−isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
444−
445−-- | analagous to `maybe` using @IS NULL@
446−--
447−-- >>> printSQL $ matchNull true not_ null_
448−-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
449−matchNull
450− :: Expression grp commons schemas params from (nullty)
451− -- ^ what to convert @NULL@ to
452− -> ( Expression grp commons schemas params from ('NotNull ty)
453− -> Expression grp commons schemas params from (nullty) )
454− -- ^ function to perform when @NULL@ is absent
455− -> Expression grp commons schemas params from ('Null ty)
456− -> Expression grp commons schemas params from (nullty)
457−matchNull y f x = ifThenElse (isNull x) y
458− (f (UnsafeExpression (renderSQL x)))
459−
460−{-| right inverse to `fromNull`, if its arguments are equal then
461−`nullIf` gives @NULL@.
462−
463−>>> :set -XTypeApplications -XDataKinds
464−>>> let expr = nullIf false (param @1) :: Expression grp commons schemas '[ 'NotNull 'PGbool] from ('Null 'PGbool)
465−>>> printSQL expr
466−NULL IF (FALSE, ($1 :: bool))
467−-}
468−nullIf
469− :: Expression grp commons schemas params from ('NotNull ty)
470− -- ^ @NULL@ is absent
471− -> Expression grp commons schemas params from ('NotNull ty)
472− -- ^ @NULL@ is absent
473− -> Expression grp commons schemas params from ('Null ty)
474−nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
475− (renderSQL x <> ", " <> renderSQL y)
476−
477−-- | >>> printSQL $ array [null_, false, true]
478−-- ARRAY[NULL, FALSE, TRUE]
479−array
480− :: [Expression grp commons schemas params from ty]
481− -- ^ array elements
482− -> Expression grp commons schemas params from (nullity ('PGvararray ty))
483−array xs = UnsafeExpression $
484− "ARRAY[" <> commaSeparated (renderSQL <$> xs) <> "]"
485−
486−-- | >>> printSQL $ array [null_, false, true] & index 2
487−-- (ARRAY[NULL, FALSE, TRUE])[2]
488−index
489− :: Word64 -- ^ index
490− -> Expression grp commons schemas params from (nullity ('PGvararray ty)) -- ^ array
491− -> Expression grp commons schemas params from (NullifyType ty)
492−index n expr = UnsafeExpression $
493− parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
494−
495311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
496− (Expression grp commons schemas params from (nullity ('PGenum labels))) where
312+ (Expression outer commons grp schemas params from (null ('PGenum labels))) where
497313 label = UnsafeExpression $ renderSQL (PGlabel @label)
498314
499−-- | A row constructor is an expression that builds a row value
500−-- (also called a composite value) using values for its member fields.
501−--
502−-- >>> :{
503−-- type Complex = 'PGcomposite
504−-- '[ "real" ::: 'NotNull 'PGfloat8
505−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
506−-- :}
507−--
508−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression grp commons schemas params from ('NotNull Complex)
509−-- >>> printSQL i
510−-- ROW(0, 1)
511−row
512− :: SListI row
513− => NP (Aliased (Expression grp commons schemas params from)) row
514− -- ^ zero or more expressions for the row field values
515− -> Expression grp commons schemas params from (nullity ('PGcomposite row))
516−row exprs = UnsafeExpression $ "ROW" <> parenthesized
517− (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
518−
519−-- | >>> :{
520−-- type Complex = 'PGcomposite
521−-- '[ "real" ::: 'NotNull 'PGfloat8
522−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
523−-- type Schema = '["complex" ::: 'Typedef Complex]
524−-- :}
525−--
526−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression grp '[] (Public Schema) from params ('NotNull Complex)
527−-- >>> printSQL $ i & field #complex #imaginary
528−-- (ROW(0, 1)::"complex")."imaginary"
529−field
530− :: ( Has sch schemas schema
531− , Has tydef schema ('Typedef ('PGcomposite row))
532− , Has field row ty)
533− => QualifiedAlias sch tydef -- ^ row type
534− -> Alias field -- ^ field name
535− -> Expression grp commons schemas params from ('NotNull ('PGcomposite row))
536− -> Expression grp commons schemas params from ty
537−field td fld expr = UnsafeExpression $
538− parenthesized (renderSQL expr <> "::" <> renderSQL td)
539− <> "." <> renderSQL fld
540−
541−instance Semigroup
542− (Expression grp commons schemas params from (nullity ('PGvararray ty))) where
543− (<>) = unsafeBinaryOp "||"
544−
545−instance Monoid
546− (Expression grp commons schemas params from (nullity ('PGvararray ty))) where
547− mempty = array []
548− mappend = (<>)
549−
550−-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression grp commons schemas '[ 'NotNull 'PGtimestamptz] from ('NotNull 'PGtimestamptz)
551−-- >>> printSQL expr
552−-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
553−greatest
554− :: Expression grp commons schemas params from (nullty)
555− -- ^ needs at least 1 argument
556− -> [Expression grp commons schemas params from (nullty)]
557− -- ^ or more
558− -> Expression grp commons schemas params from (nullty)
559−greatest x xs = UnsafeExpression $ "GREATEST("
560− <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
561−
562−-- | >>> printSQL $ least currentTimestamp [null_]
563−-- LEAST(CURRENT_TIMESTAMP, NULL)
564−least
565− :: Expression grp commons schemas params from (nullty)
566− -- ^ needs at least 1 argument
567− -> [Expression grp commons schemas params from (nullty)]
568− -- ^ or more
569− -> Expression grp commons schemas params from (nullty)
570−least x xs = UnsafeExpression $ "LEAST("
571− <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
572−
573315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
574316-- (TRUE OR FALSE)
575−unsafeBinaryOp
576− :: ByteString
577− -- ^ operator
578− -> Expression grp commons schemas params from (ty0)
579− -> Expression grp commons schemas params from (ty1)
580− -> Expression grp commons schemas params from (ty2)
317+unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
581318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
582319 renderSQL x <+> op <+> renderSQL y
583320
584−-- | >>> 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
585329-- (NOT TRUE)
586−unsafeUnaryOp
587− :: ByteString
588− -- ^ operator
589− -> Expression grp commons schemas params from (ty0)
590− -> Expression grp commons schemas params from (ty1)
591−unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
592− 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
593351
594352-- | >>> printSQL $ unsafeFunction "f" true
595353-- f(TRUE)
596−unsafeFunction
597− :: ByteString
598− -- ^ function
599− -> Expression grp commons schemas params from (xty)
600− -> Expression grp commons schemas params from (yty)
354+unsafeFunction :: ByteString -> x --> y
601355unsafeFunction fun x = UnsafeExpression $
602356 fun <> parenthesized (renderSQL x)
603357
604−-- | Helper for defining variadic functions.
605−unsafeVariadicFunction
606− :: SListI elems
607− => ByteString
608− -- ^ function
609− -> NP (Expression grp commons schemas params from) elems
610− -> Expression grp commons schemas params from ret
611−unsafeVariadicFunction fun x = UnsafeExpression $
612− 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
613377
614378instance ty `In` PGNum
615− => Num (Expression grp commons schemas params from (nullity ty)) where
379+ => Num (Expression outer commons grp schemas params from (null ty)) where
616380 (+) = unsafeBinaryOp "+"
617381 (-) = unsafeBinaryOp "-"
618382 (*) = unsafeBinaryOp "*"
@@ -624,12 +388,17 @@ instance ty `In` PGNum
624388 . show
625389
626390instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
627− (Expression grp commons schemas params from (nullity ty)) where
391+ (Expression outer commons grp schemas params from (null ty)) where
628392 (/) = unsafeBinaryOp "/"
629− fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
393+ fromRational
394+ = UnsafeExpression
395+ . fromString
396+ . ($ "")
397+ . showFFloat Nothing
398+ . fromRat @Double
630399
631400instance (ty `In` PGNum, ty `In` PGFloating) => Floating
632− (Expression grp commons schemas params from (nullity ty)) where
401+ (Expression outer commons grp schemas params from (null ty)) where
633402 pi = UnsafeExpression "pi()"
634403 exp = unsafeFunction "exp"
635404 log = unsafeFunction "ln"
@@ -650,1542 +419,54 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
650419 acosh x = log (x + sqrt (x*x - 1))
651420 atanh x = log ((1 + x) / (1 - x)) / 2
652421
653−-- | >>> :{
654−-- let
655−-- expression :: Expression grp commons schemas params from (nullity 'PGfloat4)
656−-- expression = atan2_ pi 2
657−-- in printSQL expression
658−-- :}
659−-- atan2(pi(), 2)
660−atan2_
661− :: float `In` PGFloating
662− => Expression grp commons schemas params from (nullity float)
663− -- ^ numerator
664− -> Expression grp commons schemas params from (nullity float)
665− -- ^ denominator
666− -> Expression grp commons schemas params from (nullity float)
667−atan2_ y x = UnsafeExpression $
668− "atan2(" <> renderSQL y <> ", " <> renderSQL x <> ")"
669−
670−-- When a `cast` is applied to an `Expression` of a known type, it
671−-- represents a run-time type conversion. The cast will succeed only if a
672−-- suitable type conversion operation has been defined.
673−--
674−-- | >>> printSQL $ true & cast int4
675−-- (TRUE :: int4)
676−cast
677− :: TypeExpression schemas ty1
678− -- ^ type to cast as
679− -> Expression grp commons schemas params from ty0
680− -- ^ value to convert
681− -> Expression grp commons schemas params from ty1
682−cast ty x = UnsafeExpression $ parenthesized $
683− renderSQL x <+> "::" <+> renderSQL ty
684−
685−-- | integer division, truncates the result
686−--
687−-- >>> :{
688−-- let
689−-- expression :: Expression grp commons schemas params from (nullity 'PGint2)
690−-- expression = 5 `quot_` 2
691−-- in printSQL expression
692−-- :}
693−-- (5 / 2)
694−quot_
695− :: int `In` PGIntegral
696− => Expression grp commons schemas params from (nullity int)
697− -- ^ numerator
698− -> Expression grp commons schemas params from (nullity int)
699− -- ^ denominator
700− -> Expression grp commons schemas params from (nullity int)
701−quot_ = unsafeBinaryOp "/"
702−
703−-- | remainder upon integer division
704−--
705−-- >>> :{
706−-- let
707−-- expression :: Expression grp commons schemas params from (nullity 'PGint2)
708−-- expression = 5 `rem_` 2
709−-- in printSQL expression
710−-- :}
711−-- (5 % 2)
712−rem_
713− :: int `In` PGIntegral
714− => Expression grp commons schemas params from (nullity int)
715− -- ^ numerator
716− -> Expression grp commons schemas params from (nullity int)
717− -- ^ denominator
718− -> Expression grp commons schemas params from (nullity int)
719−rem_ = unsafeBinaryOp "%"
720−
721−-- | >>> :{
722−-- let
723−-- expression :: Expression grp commons schemas params from (nullity 'PGfloat4)
724−-- expression = trunc pi
725−-- in printSQL expression
726−-- :}
727−-- trunc(pi())
728−trunc
729− :: frac `In` PGFloating
730− => Expression grp commons schemas params from (nullity frac)
731− -- ^ fractional number
732− -> Expression grp commons schemas params from (nullity frac)
733−trunc = unsafeFunction "trunc"
734−
735−-- | >>> :{
736−-- let
737−-- expression :: Expression grp commons schemas params from (nullity 'PGfloat4)
738−-- expression = round_ pi
739−-- in printSQL expression
740−-- :}
741−-- round(pi())
742−round_
743− :: frac `In` PGFloating
744− => Expression grp commons schemas params from (nullity frac)
745− -- ^ fractional number
746− -> Expression grp commons schemas params from (nullity frac)
747−round_ = unsafeFunction "round"
748−
749−-- | >>> :{
750−-- let
751−-- expression :: Expression grp commons schemas params from (nullity 'PGfloat4)
752−-- expression = ceiling_ pi
753−-- in printSQL expression
754−-- :}
755−-- ceiling(pi())
756−ceiling_
757− :: frac `In` PGFloating
758− => Expression grp commons schemas params from (nullity frac)
759− -- ^ fractional number
760− -> Expression grp commons schemas params from (nullity frac)
761−ceiling_ = unsafeFunction "ceiling"
762−
763−-- | A `Condition` is an `Expression`, which can evaluate
764−-- to `true`, `false` or `null_`. This is because SQL uses
765−-- a three valued logic.
766−type Condition grp commons schemas params from =
767− Expression grp commons schemas params from ('Null 'PGbool)
768−
769−-- | >>> printSQL true
770−-- TRUE
771−true :: Expression grp commons schemas params from (nullity 'PGbool)
772−true = UnsafeExpression "TRUE"
773−
774−-- | >>> printSQL false
775−-- FALSE
776−false :: Expression grp commons schemas params from (nullity 'PGbool)
777−false = UnsafeExpression "FALSE"
778−
779−-- | >>> printSQL $ not_ true
780−-- (NOT TRUE)
781−not_
782− :: Expression grp commons schemas params from (nullity 'PGbool)
783− -> Expression grp commons schemas params from (nullity 'PGbool)
784−not_ = unsafeUnaryOp "NOT"
785−
786−-- | >>> printSQL $ true .&& false
787−-- (TRUE AND FALSE)
788−(.&&)
789− :: Expression grp commons schemas params from (nullity 'PGbool)
790− -> Expression grp commons schemas params from (nullity 'PGbool)
791− -> Expression grp commons schemas params from (nullity 'PGbool)
792−infixr 3 .&&
793−(.&&) = unsafeBinaryOp "AND"
794−
795−-- | >>> printSQL $ true .|| false
796−-- (TRUE OR FALSE)
797−(.||)
798− :: Expression grp commons schemas params from (nullity 'PGbool)
799− -> Expression grp commons schemas params from (nullity 'PGbool)
800− -> Expression grp commons schemas params from (nullity 'PGbool)
801−infixr 2 .||
802−(.||) = unsafeBinaryOp "OR"
803−
804−-- | >>> :{
805−-- let
806−-- expression :: Expression grp commons schemas params from (nullity 'PGint2)
807−-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
808−-- in printSQL expression
809−-- :}
810−-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
811−caseWhenThenElse
812− :: [ ( Condition grp commons schemas params from
813− , Expression grp commons schemas params from ty
814− ) ]
815− -- ^ whens and thens
816− -> Expression grp commons schemas params from ty
817− -- ^ else
818− -> Expression grp commons schemas params from ty
819−caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
820− [ "CASE"
821− , mconcat
822− [ mconcat
823− [ " WHEN ", renderSQL when_
824− , " THEN ", renderSQL then_
825− ]
826− | (when_,then_) <- whenThens
827− ]
828− , " ELSE ", renderSQL else_
829− , " END"
830− ]
831−
832−-- | >>> :{
833−-- let
834−-- expression :: Expression grp commons schemas params from (nullity 'PGint2)
835−-- expression = ifThenElse true 1 0
836−-- in printSQL expression
837−-- :}
838−-- CASE WHEN TRUE THEN 1 ELSE 0 END
839−ifThenElse
840− :: Condition grp commons schemas params from
841− -> Expression grp commons schemas params from ty -- ^ then
842− -> Expression grp commons schemas params from ty -- ^ else
843− -> Expression grp commons schemas params from ty
844−ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
845−
846−-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
847−-- will produce @NULL@s if one of their arguments is @NULL@.
848−--
849−-- >>> printSQL $ true .== null_
850−-- (TRUE = NULL)
851−(.==)
852− :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
853− -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
854− -> Condition grp commons schemas params from
855−(.==) = unsafeBinaryOp "="
856−infix 4 .==
857−
858−-- | >>> printSQL $ true ./= null_
859−-- (TRUE <> NULL)
860−(./=)
861− :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
862− -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
863− -> Condition grp commons schemas params from
864−(./=) = unsafeBinaryOp "<>"
865−infix 4 ./=
866−
867−-- | >>> printSQL $ true .>= null_
868−-- (TRUE >= NULL)
869−(.>=)
870− :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
871− -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
872− -> Condition grp commons schemas params from
873−(.>=) = unsafeBinaryOp ">="
874−infix 4 .>=
875−
876−-- | >>> printSQL $ true .< null_
877−-- (TRUE < NULL)
878−(.<)
879− :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
880− -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
881− -> Condition grp commons schemas params from
882−(.<) = unsafeBinaryOp "<"
883−infix 4 .<
884−
885−-- | >>> printSQL $ true .<= null_
886−-- (TRUE <= NULL)
887−(.<=)
888− :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
889− -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
890− -> Condition grp commons schemas params from
891−(.<=) = unsafeBinaryOp "<="
892−infix 4 .<=
893−
894−-- | >>> printSQL $ true .> null_
895−-- (TRUE > NULL)
896−(.>)
897− :: Expression grp commons schemas params from (nullity0 ty) -- ^ lhs
898− -> Expression grp commons schemas params from (nullity1 ty) -- ^ rhs
899− -> Condition grp commons schemas params from
900−(.>) = unsafeBinaryOp ">"
901−infix 4 .>
902−
903−-- | >>> printSQL currentDate
904−-- CURRENT_DATE
905−currentDate
906− :: Expression grp commons schemas params from (nullity 'PGdate)
907−currentDate = UnsafeExpression "CURRENT_DATE"
908−
909−-- | >>> printSQL currentTime
910−-- CURRENT_TIME
911−currentTime
912− :: Expression grp commons schemas params from (nullity 'PGtimetz)
913−currentTime = UnsafeExpression "CURRENT_TIME"
914−
915−-- | >>> printSQL currentTimestamp
916−-- CURRENT_TIMESTAMP
917−currentTimestamp
918− :: Expression grp commons schemas params from (nullity 'PGtimestamptz)
919−currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
920−
921−-- | >>> printSQL localTime
922−-- LOCALTIME
923−localTime
924− :: Expression grp commons schemas params from (nullity 'PGtime)
925−localTime = UnsafeExpression "LOCALTIME"
926−
927−-- | >>> printSQL localTimestamp
928−-- LOCALTIMESTAMP
929−localTimestamp
930− :: Expression grp commons schemas params from (nullity 'PGtimestamp)
931−localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
932−
933−{-----------------------------------------
934−text
935−-----------------------------------------}
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)
936438
937439instance IsString
938− (Expression grp commons schemas params from (nullity 'PGtext)) where
440+ (Expression outer commons grp schemas params from (null 'PGtext)) where
939441 fromString str = UnsafeExpression $
940442 "E\'" <> fromString (escape =<< str) <> "\'"
941− where
942− escape = \case
943− '\NUL' -> "\\0"
944− '\'' -> "''"
945− '"' -> "\\\""
946− '\b' -> "\\b"
947− '\n' -> "\\n"
948− '\r' -> "\\r"
949− '\t' -> "\\t"
950− '\\' -> "\\\\"
951− 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) <> "\'"
952451
953452instance Semigroup
954− (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
955463 (<>) = unsafeBinaryOp "||"
956464
957465instance Monoid
958− (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
959471 mempty = fromString ""
960472 mappend = (<>)
961−
962−-- | >>> printSQL $ lower "ARRRGGG"
963−-- lower(E'ARRRGGG')
964−lower
965− :: Expression grp commons schemas params from (nullity 'PGtext)
966− -- ^ string to lower case
967− -> Expression grp commons schemas params from (nullity 'PGtext)
968−lower = unsafeFunction "lower"
969−
970−-- | >>> printSQL $ upper "eeee"
971−-- upper(E'eeee')
972−upper
973− :: Expression grp commons schemas params from (nullity 'PGtext)
974− -- ^ string to upper case
975− -> Expression grp commons schemas params from (nullity 'PGtext)
976−upper = unsafeFunction "upper"
977−
978−-- | >>> printSQL $ charLength "four"
979−-- char_length(E'four')
980−charLength
981− :: Expression grp commons schemas params from (nullity 'PGtext)
982− -- ^ string to measure
983− -> Expression grp commons schemas params from (nullity 'PGint4)
984−charLength = unsafeFunction "char_length"
985−
986−-- | The `like` expression returns true if the @string@ matches
987−-- the supplied @pattern@. If @pattern@ does not contain percent signs
988−-- or underscores, then the pattern only represents the string itself;
989−-- in that case `like` acts like the equals operator. An underscore (_)
990−-- in pattern stands for (matches) any single character; a percent sign (%)
991−-- matches any sequence of zero or more characters.
992−--
993−-- >>> printSQL $ "abc" `like` "a%"
994−-- (E'abc' LIKE E'a%')
995−like
996− :: Expression grp commons schemas params from (nullity 'PGtext)
997− -- ^ string
998− -> Expression grp commons schemas params from (nullity 'PGtext)
999− -- ^ pattern
1000− -> Expression grp commons schemas params from (nullity 'PGbool)
1001−like = unsafeBinaryOp "LIKE"
1002−
1003−-- | The key word ILIKE can be used instead of LIKE to make the
1004−-- match case-insensitive according to the active locale.
1005−--
1006−-- >>> printSQL $ "abc" `ilike` "a%"
1007−-- (E'abc' ILIKE E'a%')
1008−ilike
1009− :: Expression grp commons schemas params from (nullity 'PGtext)
1010− -- ^ string
1011− -> Expression grp commons schemas params from (nullity 'PGtext)
1012− -- ^ pattern
1013− -> Expression grp commons schemas params from (nullity 'PGbool)
1014−ilike = unsafeBinaryOp "ILIKE"
1015−
1016−{-----------------------------------------
1017− -- json and jsonb support
1018−
1019−See https://www.postgresql.org/docs/10/static/functions-json.html -- most
1020−comments lifted directly from this page.
1021−
1022−Table 9.44: json and jsonb operators
1023−-----------------------------------------}
1024−
1025−-- | Get JSON value (object field or array element) at a key.
1026−(.->)
1027− :: (json `In` PGJsonType, key `In` PGJsonKey)
1028− => Expression grp commons schemas params from (nullity json)
1029− -> Expression grp commons schemas params from (nullity key)
1030− -> Expression grp commons schemas params from ('Null json)
1031−infixl 8 .->
1032−(.->) = unsafeBinaryOp "->"
1033−
1034−-- | Get JSON value (object field or array element) at a key, as text.
1035−(.->>)
1036− :: (json `In` PGJsonType, key `In` PGJsonKey)
1037− => Expression grp commons schemas params from (nullity json)
1038− -> Expression grp commons schemas params from (nullity key)
1039− -> Expression grp commons schemas params from ('Null 'PGtext)
1040−infixl 8 .->>
1041−(.->>) = unsafeBinaryOp "->>"
1042−
1043−-- | Get JSON value at a specified path.
1044−(.#>)
1045− :: (json `In` PGJsonType, PGTextArray "(.#>)" path)
1046− => Expression grp commons schemas params from (nullity json)
1047− -> Expression grp commons schemas params from (nullity path)
1048− -> Expression grp commons schemas params from ('Null json)
1049−infixl 8 .#>
1050−(.#>) = unsafeBinaryOp "#>"
1051−
1052−-- | Get JSON value at a specified path as text.
1053−(.#>>)
1054− :: (json `In` PGJsonType, PGTextArray "(.#>>)" path)
1055− => Expression grp commons schemas params from (nullity json)
1056− -> Expression grp commons schemas params from (nullity path)
1057− -> Expression grp commons schemas params from ('Null 'PGtext)
1058−infixl 8 .#>>
1059−(.#>>) = unsafeBinaryOp "#>>"
1060−
1061−-- Additional jsonb operators
1062−
1063−-- | Does the left JSON value contain the right JSON path/value entries at the
1064−-- top level?
1065−(.@>)
1066− :: Expression grp commons schemas params from (nullity 'PGjsonb)
1067− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1068− -> Condition grp commons schemas params from
1069−infixl 9 .@>
1070−(.@>) = unsafeBinaryOp "@>"
1071−
1072−-- | Are the left JSON path/value entries contained at the top level within the
1073−-- right JSON value?
1074−(.<@)
1075− :: Expression grp commons schemas params from (nullity 'PGjsonb)
1076− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1077− -> Condition grp commons schemas params from
1078−infixl 9 .<@
1079−(.<@) = unsafeBinaryOp "<@"
1080−
1081−-- | Does the string exist as a top-level key within the JSON value?
1082−(.?)
1083− :: Expression grp commons schemas params from (nullity 'PGjsonb)
1084− -> Expression grp commons schemas params from (nullity 'PGtext)
1085− -> Condition grp commons schemas params from
1086−infixl 9 .?
1087−(.?) = unsafeBinaryOp "?"
1088−
1089−-- | Do any of these array strings exist as top-level keys?
1090−(.?|)
1091− :: Expression grp commons schemas params from (nullity 'PGjsonb)
1092− -> Expression grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1093− -> Condition grp commons schemas params from
1094−infixl 9 .?|
1095−(.?|) = unsafeBinaryOp "?|"
1096−
1097−-- | Do all of these array strings exist as top-level keys?
1098−(.?&)
1099− :: Expression grp commons schemas params from (nullity 'PGjsonb)
1100− -> Expression grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1101− -> Condition grp commons schemas params from
1102−infixl 9 .?&
1103−(.?&) = unsafeBinaryOp "?&"
1104−
1105−-- | Concatenate two jsonb values into a new jsonb value.
1106−instance
1107− Semigroup (Expression commons schemas from grouping param (nullity 'PGjsonb)) where
1108− (<>) = unsafeBinaryOp "||"
1109−
1110−-- | Delete a key or keys from a JSON object, or remove an array element.
1111−--
1112−-- If the right operand is..
1113−--
1114−-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1115−-- are matched based on their key value.
1116−--
1117−-- @ text[] @: Delete multiple key/value pairs or string elements
1118−-- from left operand. Key/value pairs are matched based on their key value.
1119−--
1120−-- @ integer @: Delete the array element with specified index (Negative integers
1121−-- count from the end). Throws an error if top level container is not an array.
1122−(.-.)
1123− :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1124− => Expression grp commons schemas params from (nullity 'PGjsonb)
1125− -> Expression grp commons schemas params from (nullity key)
1126− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1127−infixl 6 .-.
1128−(.-.) = unsafeBinaryOp "-"
1129−
1130−-- | Delete the field or element with specified path (for JSON arrays, negative
1131−-- integers count from the end)
1132−(#-.)
1133− :: PGTextArray "(#-.)" arrayty
1134− => Expression grp commons schemas params from (nullity 'PGjsonb)
1135− -> Expression grp commons schemas params from (nullity arrayty)
1136− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1137−infixl 6 #-.
1138−(#-.) = unsafeBinaryOp "#-"
1139−
1140−{-----------------------------------------
1141−Table 9.45: JSON creation functions
1142−-----------------------------------------}
1143−
1144−-- | Literal binary JSON
1145−jsonbLit
1146− :: JSON.ToJSON x
1147− => x -> Expression grp commons schemas params from (nullity 'PGjsonb)
1148−jsonbLit = cast jsonb . UnsafeExpression
1149− . singleQuotedUtf8 . toStrict . JSON.encode
1150−
1151−-- | Literal JSON
1152−jsonLit
1153− :: JSON.ToJSON x
1154− => x -> Expression grp commons schemas params from (nullity 'PGjson)
1155−jsonLit = cast json . UnsafeExpression
1156− . singleQuotedUtf8 . toStrict . JSON.encode
1157−
1158−-- | Returns the value as json. Arrays and composites are converted
1159−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1160−-- type to json, the cast function will be used to perform the conversion;
1161−-- otherwise, a scalar value is produced. For any scalar type other than a
1162−-- number, a Boolean, or a null value, the text representation will be used, in
1163−-- such a fashion that it is a valid json value.
1164−toJson
1165− :: Expression grp commons schemas params from (nullity ty)
1166− -> Expression grp commons schemas params from (nullity 'PGjson)
1167−toJson = unsafeFunction "to_json"
1168−
1169−-- | Returns the value as jsonb. Arrays and composites are converted
1170−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1171−-- type to json, the cast function will be used to perform the conversion;
1172−-- otherwise, a scalar value is produced. For any scalar type other than a
1173−-- number, a Boolean, or a null value, the text representation will be used, in
1174−-- such a fashion that it is a valid jsonb value.
1175−toJsonb
1176− :: Expression grp commons schemas params from (nullity ty)
1177− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1178−toJsonb = unsafeFunction "to_jsonb"
1179−
1180−-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1181−-- becomes a JSON array of arrays.
1182−arrayToJson
1183− :: PGArray "arrayToJson" arr
1184− => Expression grp commons schemas params from (nullity arr)
1185− -> Expression grp commons schemas params from (nullity 'PGjson)
1186−arrayToJson = unsafeFunction "array_to_json"
1187−
1188−-- | Returns the row as a JSON object.
1189−rowToJson
1190− :: Expression grp commons schemas params from (nullity ('PGcomposite ty))
1191− -> Expression grp commons schemas params from (nullity 'PGjson)
1192−rowToJson = unsafeFunction "row_to_json"
1193−
1194−-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1195−-- argument list.
1196−jsonBuildArray
1197− :: SListI elems
1198− => NP (Expression grp commons schemas params from) elems
1199− -> Expression grp commons schemas params from (nullity 'PGjson)
1200−jsonBuildArray = unsafeVariadicFunction "json_build_array"
1201−
1202−-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1203−-- variadic argument list.
1204−jsonbBuildArray
1205− :: SListI elems
1206− => NP (Expression grp commons schemas params from) elems
1207− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1208−jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1209−
1210−unsafeRowFunction
1211− :: All Top elems
1212− => NP (Aliased (Expression grp commons schemas params from)) elems
1213− -> [ByteString]
1214−unsafeRowFunction =
1215− (`appEndo` []) . hcfoldMap (Proxy :: Proxy Top)
1216− (\(col `As` name) -> Endo $ \xs ->
1217− renderAliasString name : renderSQL col : xs)
1218− where
1219− renderAliasString :: KnownSymbol alias => Alias alias -> ByteString
1220− renderAliasString = singleQuotedText . fromString . symbolVal
1221−
1222−-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1223−-- argument list. The elements of the argument list must alternate between text
1224−-- and values.
1225−jsonBuildObject
1226− :: All Top elems
1227− => NP (Aliased (Expression grp commons schemas params from)) elems
1228− -> Expression grp commons schemas params from (nullity 'PGjson)
1229−jsonBuildObject
1230− = unsafeFunction "json_build_object"
1231− . UnsafeExpression
1232− . commaSeparated
1233− . unsafeRowFunction
1234−
1235−-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1236−-- variadic argument list. The elements of the argument list must alternate
1237−-- between text and values.
1238−jsonbBuildObject
1239− :: All Top elems
1240− => NP (Aliased (Expression grp commons schemas params from)) elems
1241− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1242−jsonbBuildObject
1243− = unsafeFunction "jsonb_build_object"
1244− . UnsafeExpression
1245− . commaSeparated
1246− . unsafeRowFunction
1247−
1248−-- | Builds a JSON object out of a text array. The array must have either
1249−-- exactly one dimension with an even number of members, in which case they are
1250−-- taken as alternating key/value pairs, or two dimensions such that each inner
1251−-- array has exactly two elements, which are taken as a key/value pair.
1252−jsonObject
1253− :: PGArrayOf "jsonObject" arr ('NotNull 'PGtext)
1254− => Expression grp commons schemas params from (nullity arr)
1255− -> Expression grp commons schemas params from (nullity 'PGjson)
1256−jsonObject = unsafeFunction "json_object"
1257−
1258−-- | Builds a binary JSON object out of a text array. The array must have either
1259−-- exactly one dimension with an even number of members, in which case they are
1260−-- taken as alternating key/value pairs, or two dimensions such that each inner
1261−-- array has exactly two elements, which are taken as a key/value pair.
1262−jsonbObject
1263− :: PGArrayOf "jsonbObject" arr ('NotNull 'PGtext)
1264− => Expression grp commons schemas params from (nullity arr)
1265− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1266−jsonbObject = unsafeFunction "jsonb_object"
1267−
1268−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1269−-- keys and one for values, that are zipped pairwise to create a JSON object.
1270−jsonZipObject
1271− :: ( PGArrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1272− , PGArrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
1273− => Expression grp commons schemas params from (nullity keysArray)
1274− -> Expression grp commons schemas params from (nullity valuesArray)
1275− -> Expression grp commons schemas params from (nullity 'PGjson)
1276−jsonZipObject ks vs =
1277− unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1278−
1279−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1280−-- keys and one for values, that are zipped pairwise to create a binary JSON
1281−-- object.
1282−jsonbZipObject
1283− :: ( PGArrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1284− , PGArrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
1285− => Expression grp commons schemas params from (nullity keysArray)
1286− -> Expression grp commons schemas params from (nullity valuesArray)
1287− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1288−jsonbZipObject ks vs =
1289− unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1290−
1291−{-----------------------------------------
1292−Table 9.46: JSON processing functions
1293−-----------------------------------------}
1294−
1295−-- | Returns the number of elements in the outermost JSON array.
1296−jsonArrayLength
1297− :: Expression grp commons schemas params from (nullity 'PGjson)
1298− -> Expression grp commons schemas params from (nullity 'PGint4)
1299−jsonArrayLength = unsafeFunction "json_array_length"
1300−
1301−-- | Returns the number of elements in the outermost binary JSON array.
1302−jsonbArrayLength
1303− :: Expression grp commons schemas params from (nullity 'PGjsonb)
1304− -> Expression grp commons schemas params from (nullity 'PGint4)
1305−jsonbArrayLength = unsafeFunction "jsonb_array_length"
1306−
1307−-- | Returns JSON value pointed to by the given path (equivalent to #>
1308−-- operator).
1309−jsonExtractPath
1310− :: SListI elems
1311− => Expression grp commons schemas params from (nullity 'PGjson)
1312− -> NP (Expression grp commons schemas params from) elems
1313− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1314−jsonExtractPath x xs =
1315− unsafeVariadicFunction "json_extract_path" (x :* xs)
1316−
1317−-- | Returns JSON value pointed to by the given path (equivalent to #>
1318−-- operator).
1319−jsonbExtractPath
1320− :: SListI elems
1321− => Expression grp commons schemas params from (nullity 'PGjsonb)
1322− -> NP (Expression grp commons schemas params from) elems
1323− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1324−jsonbExtractPath x xs =
1325− unsafeVariadicFunction "jsonb_extract_path" (x :* xs)
1326−
1327−-- | Returns JSON value pointed to by the given path (equivalent to #>
1328−-- operator), as text.
1329−jsonExtractPathAsText
1330− :: SListI elems
1331− => Expression grp commons schemas params from (nullity 'PGjson)
1332− -> NP (Expression grp commons schemas params from) elems
1333− -> Expression grp commons schemas params from (nullity 'PGjson)
1334−jsonExtractPathAsText x xs =
1335− unsafeVariadicFunction "json_extract_path_text" (x :* xs)
1336−
1337−-- | Returns JSON value pointed to by the given path (equivalent to #>
1338−-- operator), as text.
1339−jsonbExtractPathAsText
1340− :: SListI elems
1341− => Expression grp commons schemas params from (nullity 'PGjsonb)
1342− -> NP (Expression grp commons schemas params from) elems
1343− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1344−jsonbExtractPathAsText x xs =
1345− unsafeVariadicFunction "jsonb_extract_path_text" (x :* xs)
1346−
1347−-- | Returns the type of the outermost JSON value as a text string. Possible
1348−-- types are object, array, string, number, boolean, and null.
1349−jsonTypeof
1350− :: Expression grp commons schemas params from (nullity 'PGjson)
1351− -> Expression grp commons schemas params from (nullity 'PGtext)
1352−jsonTypeof = unsafeFunction "json_typeof"
1353−
1354−-- | Returns the type of the outermost binary JSON value as a text string.
1355−-- Possible types are object, array, string, number, boolean, and null.
1356−jsonbTypeof
1357− :: Expression grp commons schemas params from (nullity 'PGjsonb)
1358− -> Expression grp commons schemas params from (nullity 'PGtext)
1359−jsonbTypeof = unsafeFunction "jsonb_typeof"
1360−
1361−-- | Returns its argument with all object fields that have null values omitted.
1362−-- Other null values are untouched.
1363−jsonStripNulls
1364− :: Expression grp commons schemas params from (nullity 'PGjson)
1365− -> Expression grp commons schemas params from (nullity 'PGjson)
1366−jsonStripNulls = unsafeFunction "json_strip_nulls"
1367−
1368−-- | Returns its argument with all object fields that have null values omitted.
1369−-- Other null values are untouched.
1370−jsonbStripNulls
1371− :: Expression grp commons schemas params from (nullity 'PGjsonb)
1372− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1373−jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1374−
1375−-- | @ jsonbSet target path new_value create_missing @
1376−--
1377−-- Returns target with the section designated by path replaced by new_value,
1378−-- or with new_value added if create_missing is true ( default is true) and the
1379−-- item designated by path does not exist. As with the path orientated
1380−-- operators, negative integers that appear in path count from the end of JSON
1381−-- arrays.
1382−jsonbSet
1383− :: PGTextArray "jsonbSet" arr
1384− => Expression grp commons schemas params from (nullity 'PGjsonb)
1385− -> Expression grp commons schemas params from (nullity arr)
1386− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1387− -> Maybe (Expression grp commons schemas params from (nullity 'PGbool))
1388− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1389−jsonbSet tgt path val createMissing = case createMissing of
1390− Just m -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* m :* Nil)
1391− Nothing -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* Nil)
1392−
1393−-- | @ jsonbInsert target path new_value insert_after @
1394−--
1395−-- Returns target with new_value inserted. If target section designated by
1396−-- path is in a JSONB array, new_value will be inserted before target or after
1397−-- if insert_after is true (default is false). If target section designated by
1398−-- path is in JSONB object, new_value will be inserted only if target does not
1399−-- exist. As with the path orientated operators, negative integers that appear
1400−-- in path count from the end of JSON arrays.
1401−jsonbInsert
1402− :: PGTextArray "jsonbInsert" arr
1403− => Expression grp commons schemas params from (nullity 'PGjsonb)
1404− -> Expression grp commons schemas params from (nullity arr)
1405− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1406− -> Maybe (Expression grp commons schemas params from (nullity 'PGbool))
1407− -> Expression grp commons schemas params from (nullity 'PGjsonb)
1408−jsonbInsert tgt path val insertAfter = case insertAfter of
1409− Just i -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1410− Nothing -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* Nil)
1411−
1412−-- | Returns its argument as indented JSON text.
1413−jsonbPretty
1414− :: Expression grp commons schemas params from (nullity 'PGjsonb)
1415− -> Expression grp commons schemas params from (nullity 'PGtext)
1416−jsonbPretty = unsafeFunction "jsonb_pretty"
1417−
1418−{-----------------------------------------
1419−aggregation
1420−-----------------------------------------}
1421−
1422−class Aggregate expr1 expr2 aggr
1423− | aggr -> expr1, aggr -> expr2 where
1424−
1425− -- | A special aggregation that does not require an input
1426− --
1427− -- >>> :{
1428− -- let
1429− -- expression :: Expression (Grouped bys) commons schemas params from ('NotNull 'PGint8)
1430− -- expression = countStar
1431− -- in printSQL expression
1432− -- :}
1433− -- count(*)
1434− countStar :: aggr ('NotNull 'PGint8)
1435−
1436− -- | >>> :{
1437− -- let
1438− -- expression :: Expression (Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1439− -- expression = count (All #col)
1440− -- in printSQL expression
1441− -- :}
1442− -- count(ALL "col")
1443− count
1444− :: expr1 ty
1445− -- ^ what to count
1446− -> aggr ('NotNull 'PGint8)
1447−
1448− -- | >>> :{
1449− -- let
1450− -- expression :: Expression ('Grouped bys) commons schemas params '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Null 'PGnumeric)
1451− -- expression = sum_ (Distinct #col)
1452− -- in printSQL expression
1453− -- :}
1454− -- sum(DISTINCT "col")
1455− sum_
1456− :: ty `In` PGNum
1457− => expr1 (nullity ty)
1458− -> aggr (nullity ty)
1459−
1460− -- | >>> :{
1461− -- let
1462− -- expression :: Expression ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1463− -- expression = bitAnd (Distinct #col)
1464− -- in printSQL expression
1465− -- :}
1466− -- bit_and(DISTINCT "col")
1467− bitAnd
1468− :: int `In` PGIntegral
1469− => expr1 (nullity int)
1470− -- ^ what to aggregate
1471− -> aggr (nullity int)
1472−
1473− -- | >>> :{
1474− -- let
1475− -- expression :: Expression ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] (nullity 'PGint4)
1476− -- expression = bitOr (All #col)
1477− -- in printSQL expression
1478− -- :}
1479− -- bit_or(ALL "col")
1480− bitOr
1481− :: int `In` PGIntegral
1482− => expr1 (nullity int)
1483− -- ^ what to aggregate
1484− -> aggr (nullity int)
1485−
1486− -- | >>> :{
1487− -- let
1488− -- winFun :: WindowFunction 'Ungrouped commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1489− -- winFun = boolAnd #col
1490− -- in printSQL winFun
1491− -- :}
1492− -- bool_and("col")
1493− boolAnd
1494− :: expr1 (nullity 'PGbool)
1495− -- ^ what to aggregate
1496− -> aggr (nullity 'PGbool)
1497−
1498− -- | >>> :{
1499− -- let
1500− -- expression :: Expression (Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1501− -- expression = boolOr (All #col)
1502− -- in printSQL expression
1503− -- :}
1504− -- bool_or(ALL "col")
1505− boolOr
1506− :: expr1(nullity 'PGbool)
1507− -- ^ what to aggregate
1508− -> aggr (nullity 'PGbool)
1509−
1510− -- | synonym for `boolAnd`
1511− --
1512− -- >>> :{
1513− -- let
1514− -- expression :: Expression ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] (nullity 'PGbool)
1515− -- expression = every (Distinct #col)
1516− -- in printSQL expression
1517− -- :}
1518− -- every(DISTINCT "col")
1519− every
1520− :: expr1 (nullity 'PGbool)
1521− -- ^ what to aggregate
1522− -> aggr (nullity 'PGbool)
1523−
1524− -- | maximum value of expression across all input values
1525− max_
1526− :: expr1 (nullity ty)
1527− -- ^ what to maximize
1528− -> aggr (nullity ty)
1529−
1530− -- | minimum value of expression across all input values
1531− min_
1532− :: expr1 (nullity ty)
1533− -- ^ what to minimize
1534− -> aggr (nullity ty)
1535−
1536− -- | average aggregation
1537− avg
1538− :: expr1 (nullity ty)
1539− -- ^ what to average
1540− -> aggr (nullity (PGAvg ty))
1541−
1542− {- | correlation coefficient
1543− >>> :{
1544− let
1545− expression :: Expression ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('NotNull 'PGfloat8)
1546− expression = corr (All (#y :*: #x))
1547− in printSQL expression
1548− :}
1549− corr(ALL "y", "x")
1550− -}
1551− corr
1552− :: expr2 (nullity 'PGfloat8)
1553− -> aggr (nullity 'PGfloat8)
1554−
1555− {- | population covariance
1556− >>> :{
1557− let
1558− expression :: Expression ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('NotNull 'PGfloat8)
1559− expression = covarPop (All (#y :*: #x))
1560− in printSQL expression
1561− :}
1562− covar_pop(ALL "y", "x")
1563− -}
1564− covarPop
1565− :: expr2 (nullity 'PGfloat8)
1566− -> aggr (nullity 'PGfloat8)
1567−
1568− {- | sample covariance
1569− >>> :{
1570− let
1571− winFun :: WindowFunction 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('NotNull 'PGfloat8)
1572− winFun = covarSamp (#y :*: #x)
1573− in printSQL winFun
1574− :}
1575− covar_samp("y", "x")
1576− -}
1577− covarSamp
1578− :: expr2 (nullity 'PGfloat8)
1579− -> aggr (nullity 'PGfloat8)
1580−
1581− {- | average of the independent variable (sum(X)/N)
1582− >>> :{
1583− let
1584− expression :: Expression ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('NotNull 'PGfloat8)
1585− expression = regrAvgX (All (#y :*: #x))
1586− in printSQL expression
1587− :}
1588− regr_avgx(ALL "y", "x")
1589− -}
1590− regrAvgX
1591− :: expr2 (nullity 'PGfloat8)
1592− -> aggr (nullity 'PGfloat8)
1593−
1594− {- | average of the dependent variable (sum(Y)/N)
1595− >>> :{
1596− let
1597− winFun :: WindowFunction 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('NotNull 'PGfloat8)
1598− winFun = regrAvgY (#y :*: #x)
1599− in printSQL winFun
1600− :}
1601− regr_avgy("y", "x")
1602− -}
1603− regrAvgY
1604− :: expr2 (nullity 'PGfloat8)
1605− -> aggr (nullity 'PGfloat8)
1606−
1607− {- | number of input rows in which both expressions are nonnull
1608− >>> :{
1609− let
1610− winFun :: WindowFunction 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('NotNull 'PGint8)
1611− winFun = regrCount (#y :*: #x)
1612− in printSQL winFun
1613− :}
1614− regr_count("y", "x")
1615− -}
1616− regrCount
1617− :: expr2 (nullity 'PGfloat8)
1618− -> aggr (nullity 'PGint8)
1619−
1620− {- | y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs
1621− >>> :{
1622− let
1623− expression :: Expression ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('NotNull 'PGfloat8)
1624− expression = regrIntercept (All (#y :*: #x))
1625− in printSQL expression
1626− :}
1627− regr_intercept(ALL "y", "x")
1628− -}
1629− regrIntercept
1630− :: expr2 (nullity 'PGfloat8)
1631− -> aggr (nullity 'PGfloat8)
1632−
1633− -- | @regr_r2(Y, X)@, square of the correlation coefficient
1634− regrR2
1635− :: expr2 (nullity 'PGfloat8)
1636− -> aggr (nullity 'PGfloat8)
1637−
1638− -- | @regr_slope(Y, X)@, slope of the least-squares-fit linear equation
1639− -- determined by the (X, Y) pairs
1640− regrSlope
1641− :: expr2 (nullity 'PGfloat8)
1642− -> aggr (nullity 'PGfloat8)
1643−
1644− -- | @regr_sxx(Y, X)@, sum(X^2) - sum(X)^2/N
1645− -- (“sum of squares” of the independent variable)
1646− regrSxx
1647− :: expr2 (nullity 'PGfloat8)
1648− -> aggr (nullity 'PGfloat8)
1649−
1650− -- | @regr_sxy(Y, X)@, sum(X*Y) - sum(X) * sum(Y)/N
1651− -- (“sum of products” of independent times dependent variable)
1652− regrSxy
1653− :: expr2 (nullity 'PGfloat8)
1654− -> aggr (nullity 'PGfloat8)
1655−
1656− -- | @regr_syy(Y, X)@, sum(Y^2) - sum(Y)^2/N
1657− -- (“sum of squares” of the dependent variable)
1658− regrSyy
1659− :: expr2 (nullity 'PGfloat8)
1660− -> aggr (nullity 'PGfloat8)
1661−
1662− -- | historical alias for `stddevSamp`
1663− stddev
1664− :: expr1 (nullity ty)
1665− -> aggr (nullity (PGAvg ty))
1666−
1667− -- | population standard deviation of the input values
1668− stddevPop
1669− :: expr1 (nullity ty)
1670− -> aggr (nullity (PGAvg ty))
1671−
1672− -- | sample standard deviation of the input values
1673− stddevSamp
1674− :: expr1 (nullity ty)
1675− -> aggr (nullity (PGAvg ty))
1676−
1677− -- | historical alias for `varSamp`
1678− variance
1679− :: expr1 (nullity ty)
1680− -> aggr (nullity (PGAvg ty))
1681−
1682− -- | population variance of the input values
1683− -- (square of the population standard deviation)
1684− varPop
1685− :: expr1 (nullity ty)
1686− -> aggr (nullity (PGAvg ty))
1687−
1688− -- | sample variance of the input values
1689− -- (square of the sample standard deviation)
1690− varSamp
1691− :: expr1 (nullity ty)
1692− -> aggr (nullity (PGAvg ty))
1693−
1694−data Distinction expr ty
1695− = All (expr ty)
1696− | Distinct (expr ty)
1697− deriving (GHC.Generic,Show,Eq,Ord)
1698−instance NFData (Distinction (Expression grp commons schemas params from) ty)
1699−instance RenderSQL (Distinction (Expression grp commons schemas params from) ty) where
1700− renderSQL = \case
1701− All x -> "ALL" <+> renderSQL x
1702− Distinct x -> "DISTINCT" <+> renderSQL x
1703−instance RenderSQL
1704− (Distinction
1705− ( Expression grp commons schemas params from
1706− :*:
1707− Expression grp commons schemas params from) xty ) where
1708− renderSQL = \case
1709− All (x :*: x') ->
1710− "ALL" <+> renderSQL x <> ", " <> renderSQL x'
1711− Distinct (x :*: x') ->
1712− "DISTINCT" <+> renderSQL x <> ", " <> renderSQL x'
1713−
1714−instance Aggregate
1715− (Distinction (Expression 'Ungrouped commons schemas params from))
1716− (Distinction (Expression 'Ungrouped commons schemas params from :*: Expression 'Ungrouped commons schemas params from))
1717− (Expression ('Grouped bys) commons schemas params from) where
1718− countStar = UnsafeExpression "count(*)"
1719− count = unsafeAggregate1 "count"
1720− sum_ = unsafeAggregate1 "sum"
1721− bitAnd = unsafeAggregate1 "bit_and"
1722− bitOr = unsafeAggregate1 "bit_or"
1723− boolAnd = unsafeAggregate1 "bool_and"
1724− boolOr = unsafeAggregate1 "bool_or"
1725− every = unsafeAggregate1 "every"
1726− max_ = unsafeAggregate1 "max"
1727− min_ = unsafeAggregate1 "min"
1728− avg = unsafeAggregate1 "avg"
1729− corr = unsafeAggregate2 "corr"
1730− covarPop = unsafeAggregate2 "covar_pop"
1731− covarSamp = unsafeAggregate2 "covar_samp"
1732− regrAvgX = unsafeAggregate2 "regr_avgx"
1733− regrAvgY = unsafeAggregate2 "regr_avgy"
1734− regrCount = unsafeAggregate2 "regr_count"
1735− regrIntercept = unsafeAggregate2 "regr_intercept"
1736− regrR2 = unsafeAggregate2 "regr_r2"
1737− regrSlope = unsafeAggregate2 "regr_slope"
1738− regrSxx = unsafeAggregate2 "regr_sxx"
1739− regrSxy = unsafeAggregate2 "regr_sxy"
1740− regrSyy = unsafeAggregate2 "regr_syy"
1741− stddev = unsafeAggregate1 "stddev"
1742− stddevPop = unsafeAggregate1 "stddev_pop"
1743− stddevSamp = unsafeAggregate1 "stddev_samp"
1744− variance = unsafeAggregate1 "variance"
1745− varPop = unsafeAggregate1 "var_pop"
1746− varSamp = unsafeAggregate1 "var_samp"
1747−instance Aggregate
1748− (Expression grp commons schemas params from)
1749− (Expression grp commons schemas params from :*: Expression grp commons schemas params from)
1750− (WindowFunction grp commons schemas params from) where
1751− countStar = UnsafeWindowFunction "count(*)"
1752− count = unsafeWindowFunction1 "count"
1753− sum_ = unsafeWindowFunction1 "sum"
1754− bitAnd = unsafeWindowFunction1 "bit_and"
1755− bitOr = unsafeWindowFunction1 "bit_or"
1756− boolAnd = unsafeWindowFunction1 "bool_and"
1757− boolOr = unsafeWindowFunction1 "bool_or"
1758− every = unsafeWindowFunction1 "every"
1759− max_ = unsafeWindowFunction1 "max"
1760− min_ = unsafeWindowFunction1 "min"
1761− avg = unsafeWindowFunction1 "avg"
1762− corr = unsafeWindowFunction2 "corr"
1763− covarPop = unsafeWindowFunction2 "covar_pop"
1764− covarSamp = unsafeWindowFunction2 "covar_samp"
1765− regrAvgX = unsafeWindowFunction2 "regr_avgx"
1766− regrAvgY = unsafeWindowFunction2 "regr_avgy"
1767− regrCount = unsafeWindowFunction2 "regr_count"
1768− regrIntercept = unsafeWindowFunction2 "regr_intercept"
1769− regrR2 = unsafeWindowFunction2 "regr_r2"
1770− regrSlope = unsafeWindowFunction2 "regr_slope"
1771− regrSxx = unsafeWindowFunction2 "regr_sxx"
1772− regrSxy = unsafeWindowFunction2 "regr_sxy"
1773− regrSyy = unsafeWindowFunction2 "regr_syy"
1774− stddev = unsafeWindowFunction1 "stddev"
1775− stddevPop = unsafeWindowFunction1 "stddev_pop"
1776− stddevSamp = unsafeWindowFunction1 "stddev_samp"
1777− variance = unsafeWindowFunction1 "variance"
1778− varPop = unsafeWindowFunction1 "var_pop"
1779− varSamp = unsafeWindowFunction1 "var_samp"
1780−
1781−-- | escape hatch to define aggregate functions
1782−unsafeAggregate1
1783− :: ByteString -- ^ aggregate function
1784− -> Distinction (Expression 'Ungrouped commons schemas params from) xty
1785− -> Expression ('Grouped bys) commons schemas params from yty
1786−unsafeAggregate1 fun x = UnsafeExpression $ mconcat
1787− [fun, "(", renderSQL x, ")"]
1788−
1789−-- | escape hatch to define aggregate binary functions
1790−unsafeAggregate2
1791− :: ByteString -- ^ aggregate function
1792− -> Distinction (Expression 'Ungrouped commons schemas params from :*: Expression 'Ungrouped commons schemas params from) xty
1793− -> Expression ('Grouped bys) commons schemas params from yty
1794−unsafeAggregate2 fun xx = UnsafeExpression $ mconcat
1795− [fun, "(", renderSQL xx, ")"]
1796−
1797−-- | A type family that calculates `PGAvg` type of a `PGType`.
1798−type family PGAvg ty where
1799− PGAvg 'PGint2 = 'PGnumeric
1800− PGAvg 'PGint4 = 'PGnumeric
1801− PGAvg 'PGint8 = 'PGnumeric
1802− PGAvg 'PGnumeric = 'PGnumeric
1803− PGAvg 'PGfloat4 = 'PGfloat8
1804− PGAvg 'PGfloat8 = 'PGfloat8
1805− PGAvg 'PGinterval = 'PGinterval
1806− PGAvg pg = TypeError
1807− ('Text "Squeal type error: No average for " ':<>: 'ShowType pg)
1808−
1809−{-----------------------------------------
1810−type expressions
1811−-----------------------------------------}
1812−
1813−-- | `TypeExpression`s are used in `cast`s and `createTable` commands.
1814−newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
1815− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1816− deriving (GHC.Generic,Show,Eq,Ord,NFData)
1817−instance RenderSQL (TypeExpression schemas ty) where
1818− renderSQL = renderTypeExpression
1819−
1820−-- | The enum or composite type in a `Typedef` can be expressed by its alias.
1821−typedef
1822− :: (Has sch schemas schema, Has td schema ('Typedef ty))
1823− => QualifiedAlias sch td
1824− -> TypeExpression schemas (nullity ty)
1825−typedef = UnsafeTypeExpression . renderSQL
1826−
1827−-- | The composite type corresponding to a `Table` definition can be expressed
1828−-- by its alias.
1829−typetable
1830− :: (Has sch schemas schema, Has tab schema ('Table table))
1831− => QualifiedAlias sch tab
1832− -> TypeExpression schemas (nullity ('PGcomposite (TableToRow table)))
1833−typetable = UnsafeTypeExpression . renderSQL
1834−
1835−-- | The composite type corresponding to a `View` definition can be expressed
1836−-- by its alias.
1837−typeview
1838− :: (Has sch schemas schema, Has vw schema ('View view))
1839− => QualifiedAlias sch vw
1840− -> TypeExpression schemas (nullity ('PGcomposite view))
1841−typeview = UnsafeTypeExpression . renderSQL
1842−
1843−-- | logical Boolean (true/false)
1844−bool :: TypeExpression schemas (nullity 'PGbool)
1845−bool = UnsafeTypeExpression "bool"
1846−-- | signed two-byte integer
1847−int2, smallint :: TypeExpression schemas (nullity 'PGint2)
1848−int2 = UnsafeTypeExpression "int2"
1849−smallint = UnsafeTypeExpression "smallint"
1850−-- | signed four-byte integer
1851−int4, int, integer :: TypeExpression schemas (nullity 'PGint4)
1852−int4 = UnsafeTypeExpression "int4"
1853−int = UnsafeTypeExpression "int"
1854−integer = UnsafeTypeExpression "integer"
1855−-- | signed eight-byte integer
1856−int8, bigint :: TypeExpression schemas (nullity 'PGint8)
1857−int8 = UnsafeTypeExpression "int8"
1858−bigint = UnsafeTypeExpression "bigint"
1859−-- | arbitrary precision numeric type
1860−numeric :: TypeExpression schemas (nullity 'PGnumeric)
1861−numeric = UnsafeTypeExpression "numeric"
1862−-- | single precision floating-point number (4 bytes)
1863−float4, real :: TypeExpression schemas (nullity 'PGfloat4)
1864−float4 = UnsafeTypeExpression "float4"
1865−real = UnsafeTypeExpression "real"
1866−-- | double precision floating-point number (8 bytes)
1867−float8, doublePrecision :: TypeExpression schemas (nullity 'PGfloat8)
1868−float8 = UnsafeTypeExpression "float8"
1869−doublePrecision = UnsafeTypeExpression "double precision"
1870−-- | variable-length character string
1871−text :: TypeExpression schemas (nullity 'PGtext)
1872−text = UnsafeTypeExpression "text"
1873−-- | fixed-length character string
1874−char, character
1875− :: forall n schemas nullity. (KnownNat n, 1 <= n)
1876− => TypeExpression schemas (nullity ('PGchar n))
1877−char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
1878−character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
1879−-- | variable-length character string
1880−varchar, characterVarying
1881− :: forall n schemas nullity. (KnownNat n, 1 <= n)
1882− => TypeExpression schemas (nullity ('PGvarchar n))
1883−varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
1884−characterVarying = UnsafeTypeExpression $
1885− "character varying(" <> renderNat @n <> ")"
1886−-- | binary data ("byte array")
1887−bytea :: TypeExpression schemas (nullity 'PGbytea)
1888−bytea = UnsafeTypeExpression "bytea"
1889−-- | date and time (no time zone)
1890−timestamp :: TypeExpression schemas (nullity 'PGtimestamp)
1891−timestamp = UnsafeTypeExpression "timestamp"
1892−-- | date and time, including time zone
1893−timestampWithTimeZone :: TypeExpression schemas (nullity 'PGtimestamptz)
1894−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
1895−-- | calendar date (year, month, day)
1896−date :: TypeExpression schemas (nullity 'PGdate)
1897−date = UnsafeTypeExpression "date"
1898−-- | time of day (no time zone)
1899−time :: TypeExpression schemas (nullity 'PGtime)
1900−time = UnsafeTypeExpression "time"
1901−-- | time of day, including time zone
1902−timeWithTimeZone :: TypeExpression schemas (nullity 'PGtimetz)
1903−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
1904−-- | time span
1905−interval :: TypeExpression schemas (nullity 'PGinterval)
1906−interval = UnsafeTypeExpression "interval"
1907−-- | universally unique identifier
1908−uuid :: TypeExpression schemas (nullity 'PGuuid)
1909−uuid = UnsafeTypeExpression "uuid"
1910−-- | IPv4 or IPv6 host address
1911−inet :: TypeExpression schemas (nullity 'PGinet)
1912−inet = UnsafeTypeExpression "inet"
1913−-- | textual JSON data
1914−json :: TypeExpression schemas (nullity 'PGjson)
1915−json = UnsafeTypeExpression "json"
1916−-- | binary JSON data, decomposed
1917−jsonb :: TypeExpression schemas (nullity 'PGjsonb)
1918−jsonb = UnsafeTypeExpression "jsonb"
1919−-- | variable length array
1920−vararray
1921− :: TypeExpression schemas pg
1922− -> TypeExpression schemas (nullity ('PGvararray pg))
1923−vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
1924−-- | fixed length array
1925−--
1926−-- >>> renderSQL (fixarray @'[2] json)
1927−-- "json[2]"
1928−fixarray
1929− :: forall dims schemas nullity pg. All KnownNat dims
1930− => TypeExpression schemas pg
1931− -> TypeExpression schemas (nullity ('PGfixarray dims pg))
1932−fixarray ty = UnsafeTypeExpression $
1933− renderSQL ty <> renderDims @dims
1934− where
1935− renderDims :: forall ns. All KnownNat ns => ByteString
1936− renderDims =
1937− ("[" <>)
1938− . (<> "]")
1939− . ByteString.intercalate "]["
1940− . hcollapse
1941− $ hcmap (Proxy @KnownNat)
1942− (K . fromString . show . natVal)
1943− (hpure Proxy :: NP Proxy ns)
1944−
1945−-- | `pgtype` is a demoted version of a `PGType`
1946−class PGTyped schemas (ty :: NullityType) where
1947− pgtype :: TypeExpression schemas ty
1948−instance PGTyped schemas (nullity 'PGbool) where pgtype = bool
1949−instance PGTyped schemas (nullity 'PGint2) where pgtype = int2
1950−instance PGTyped schemas (nullity 'PGint4) where pgtype = int4
1951−instance PGTyped schemas (nullity 'PGint8) where pgtype = int8
1952−instance PGTyped schemas (nullity 'PGnumeric) where pgtype = numeric
1953−instance PGTyped schemas (nullity 'PGfloat4) where pgtype = float4
1954−instance PGTyped schemas (nullity 'PGfloat8) where pgtype = float8
1955−instance PGTyped schemas (nullity 'PGtext) where pgtype = text
1956−instance (KnownNat n, 1 <= n)
1957− => PGTyped schemas (nullity ('PGchar n)) where pgtype = char @n
1958−instance (KnownNat n, 1 <= n)
1959− => PGTyped schemas (nullity ('PGvarchar n)) where pgtype = varchar @n
1960−instance PGTyped schemas (nullity 'PGbytea) where pgtype = bytea
1961−instance PGTyped schemas (nullity 'PGtimestamp) where pgtype = timestamp
1962−instance PGTyped schemas (nullity 'PGtimestamptz) where pgtype = timestampWithTimeZone
1963−instance PGTyped schemas (nullity 'PGdate) where pgtype = date
1964−instance PGTyped schemas (nullity 'PGtime) where pgtype = time
1965−instance PGTyped schemas (nullity 'PGtimetz) where pgtype = timeWithTimeZone
1966−instance PGTyped schemas (nullity 'PGinterval) where pgtype = interval
1967−instance PGTyped schemas (nullity 'PGuuid) where pgtype = uuid
1968−instance PGTyped schemas (nullity 'PGjson) where pgtype = json
1969−instance PGTyped schemas (nullity 'PGjsonb) where pgtype = jsonb
1970−instance PGTyped schemas ty
1971− => PGTyped schemas (nullity ('PGvararray ty)) where
1972− pgtype = vararray (pgtype @schemas @ty)
1973−instance (All KnownNat dims, PGTyped schemas ty)
1974− => PGTyped schemas (nullity ('PGfixarray dims ty)) where
1975− pgtype = fixarray @dims (pgtype @schemas @ty)
1976−
1977−{-----------------------------------------
1978−Sorting
1979−-----------------------------------------}
1980−
1981−-- | `SortExpression`s are used by `sortBy` to optionally sort the results
1982−-- of a `Query`. `Asc` or `Desc` set the sort direction of a `NotNull` result
1983−-- column to ascending or descending. Ascending order puts smaller values
1984−-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
1985−-- descending order is determined with the `.>` operator. `AscNullsFirst`,
1986−-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
1987−-- determine whether nulls appear before or after non-null values in the sort
1988−-- ordering of a `Null` result column.
1989−data SortExpression grp commons schemas params from where
1990− Asc
1991− :: Expression grp commons schemas params from ('NotNull ty)
1992− -> SortExpression grp commons schemas params from
1993− Desc
1994− :: Expression grp commons schemas params from ('NotNull ty)
1995− -> SortExpression grp commons schemas params from
1996− AscNullsFirst
1997− :: Expression grp commons schemas params from ('Null ty)
1998− -> SortExpression grp commons schemas params from
1999− AscNullsLast
2000− :: Expression grp commons schemas params from ('Null ty)
2001− -> SortExpression grp commons schemas params from
2002− DescNullsFirst
2003− :: Expression grp commons schemas params from ('Null ty)
2004− -> SortExpression grp commons schemas params from
2005− DescNullsLast
2006− :: Expression grp commons schemas params from ('Null ty)
2007− -> SortExpression grp commons schemas params from
2008−deriving instance Show (SortExpression grp commons schemas params from)
2009−
2010−class OrderBy expr where
2011− orderBy
2012− :: [SortExpression grp commons schemas params from]
2013− -> expr grp commons schemas params from
2014− -> expr grp commons schemas params from
2015−
2016−-- | Render a `SortExpression`.
2017−instance RenderSQL (SortExpression grp commons schemas params from) where
2018− renderSQL = \case
2019− Asc expression -> renderSQL expression <+> "ASC"
2020− Desc expression -> renderSQL expression <+> "DESC"
2021− AscNullsFirst expression -> renderSQL expression
2022− <+> "ASC NULLS FIRST"
2023− DescNullsFirst expression -> renderSQL expression
2024− <+> "DESC NULLS FIRST"
2025− AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
2026− DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
2027−
2028−data WindowDefinition grp commons schemas params from where
2029− WindowDefinition
2030− :: SListI bys
2031− => NP (Expression grp commons schemas params from) bys
2032− -> [SortExpression grp commons schemas params from]
2033− -> WindowDefinition grp commons schemas params from
2034−
2035−instance OrderBy WindowDefinition where
2036− orderBy sortsR (WindowDefinition parts sortsL)
2037− = WindowDefinition parts (sortsL ++ sortsR)
2038−
2039−instance RenderSQL (WindowDefinition commons schemas from grp params) where
2040− renderSQL (WindowDefinition part ord) =
2041− renderPartitionByClause part <> renderOrderByClause ord
2042− where
2043− renderPartitionByClause = \case
2044− Nil -> ""
2045− parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
2046− renderOrderByClause = \case
2047− [] -> ""
2048− srts -> " ORDER" <+> "BY"
2049− <+> commaSeparated (renderSQL <$> srts)
2050−
2051−partitionBy
2052− :: SListI bys
2053− => NP (Expression grp commons schemas params from) bys
2054− -> WindowDefinition grp commons schemas params from
2055−partitionBy bys = WindowDefinition bys []
2056−
2057−newtype WindowFunction
2058− (grp :: Grouping)
2059− (commons :: FromType)
2060− (schemas :: SchemasType)
2061− (params :: [NullityType])
2062− (from :: FromType)
2063− (ty :: NullityType)
2064− = UnsafeWindowFunction { renderWindowFunction :: ByteString }
2065− deriving (GHC.Generic,Show,Eq,Ord,NFData)
2066−
2067−instance RenderSQL (WindowFunction grp commons schemas params from ty) where
2068− renderSQL = renderWindowFunction
2069−
2070−unsafeWindowFunction1
2071− :: ByteString
2072− -> Expression grp commons schemas params from ty0
2073− -> WindowFunction grp commons schemas params from ty1
2074−unsafeWindowFunction1 fun x
2075− = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x)
2076−
2077−unsafeWindowFunction2
2078− :: ByteString
2079− -> (Expression grp commons schemas params from :*: Expression grp commons schemas params from) ty0
2080− -> WindowFunction grp commons schemas params from ty1
2081−unsafeWindowFunction2 fun (x :*: x')
2082− = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x <> ", " <> renderSQL x')
2083−
2084−{- | rank of the current row with gaps; same as `rowNumber` of its first peer
2085−>>> printSQL rank
2086−rank()
2087−-}
2088−rank :: WindowFunction grp commons schemas params from ('NotNull 'PGint8)
2089−rank = UnsafeWindowFunction "rank()"
2090−
2091−{- | number of the current row within its partition, counting from 1
2092−>>> printSQL rowNumber
2093−row_number()
2094−-}
2095−rowNumber :: WindowFunction grp commons schemas params from ('NotNull 'PGint8)
2096−rowNumber = UnsafeWindowFunction "row_number()"
2097−
2098−{- | rank of the current row without gaps; this function counts peer groups
2099−>>> printSQL denseRank
2100−dense_rank()
2101−-}
2102−denseRank :: WindowFunction grp commons schemas params from ('NotNull 'PGint8)
2103−denseRank = UnsafeWindowFunction "dense_rank()"
2104−
2105−{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
2106−>>> printSQL percentRank
2107−percent_rank()
2108−-}
2109−percentRank :: WindowFunction grp commons schemas params from ('NotNull 'PGfloat8)
2110−percentRank = UnsafeWindowFunction "percent_rank()"
2111−
2112−{- | cumulative distribution: (number of partition rows
2113−preceding or peer with current row) / total partition rows
2114−>>> printSQL cumeDist
2115−cume_dist()
2116−-}
2117−cumeDist :: WindowFunction grp commons schemas params from ('NotNull 'PGfloat8)
2118−cumeDist = UnsafeWindowFunction "cume_dist()"
2119−
2120−{- | integer ranging from 1 to the argument value,
2121−dividing the partition as equally as possible
2122−-}
2123−ntile
2124− :: Expression grp commons schemas params from ('NotNull 'PGint4)
2125− -- ^ num buckets
2126− -> WindowFunction grp commons schemas params from ('NotNull 'PGint4)
2127−ntile = unsafeWindowFunction1 "ntile"
2128−
2129−{- | returns value evaluated at the row that is offset rows before the current
2130−row within the partition; if there is no such row, instead return default
2131−(which must be of the same type as value). Both offset and default are
2132−evaluated with respect to the current row.
2133−-}
2134−lag
2135− :: Expression grp commons schemas params from ty
2136− -- ^ value
2137− -> Expression grp commons schemas params from ('NotNull 'PGint4)
2138− -- ^ offset
2139− -> Expression grp commons schemas params from ty
2140− -- ^ default
2141− -> WindowFunction grp commons schemas params from ty
2142−lag value offset def = UnsafeWindowFunction $ "lag"
2143− <> parenthesized
2144− (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
2145−
2146−{- | returns value evaluated at the row that is offset rows after the current
2147−row within the partition; if there is no such row, instead return default
2148−(which must be of the same type as value). Both offset and default are
2149−evaluated with respect to the current row.
2150−-}
2151−lead
2152− :: Expression grp commons schemas params from ty
2153− -- ^ value
2154− -> Expression grp commons schemas params from ('NotNull 'PGint4)
2155− -- ^ offset
2156− -> Expression grp commons schemas params from ty
2157− -- ^ default
2158− -> WindowFunction grp commons schemas params from ty
2159−lead value offset def = UnsafeWindowFunction $ "lag"
2160− <> parenthesized
2161− (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
2162−
2163−{- | returns value evaluated at the row that is the
2164−first row of the window frame
2165−-}
2166−firstValue
2167− :: Expression grp commons schemas params from ty
2168− -- ^ value
2169− -> WindowFunction grp commons schemas params from ty
2170−firstValue = unsafeWindowFunction1 "first_value"
2171−
2172−{- | returns value evaluated at the row that is the
2173−last row of the window frame
2174−-}
2175−lastValue
2176− :: Expression grp commons schemas params from ty
2177− -- ^ value
2178− -> WindowFunction grp commons schemas params from ty
2179−lastValue = unsafeWindowFunction1 "last_value"
2180−
2181−{- | returns value evaluated at the row that is the nth
2182−row of the window frame (counting from 1); null if no such row
2183−-}
2184−nthValue
2185− :: Expression grp commons schemas params from (nullity ty)
2186− -- ^ value
2187− -> Expression grp commons schemas params from ('NotNull 'PGint4)
2188− -- ^ nth
2189− -> WindowFunction grp commons schemas params from ('Null ty)
2190−nthValue value nth = UnsafeWindowFunction $ "nth_value"
2191− <> parenthesized (commaSeparated [renderSQL value, renderSQL nth])