@@ -1,14 +1,13 @@
11{-|
22Module: 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
@@ -35,389 +34,213 @@ module Squeal.PostgreSQL.Expression
3534 ( -- * Expression
3635 Expression (..)
3736 , Expr
37+ , type (-->)
38+ , FunctionDB
39+ , unsafeFunction
40+ , function
41+ , unsafeLeftOp
42+ , leftOp
43+ , unsafeRightOp
44+ , rightOp
3845 , Operator
39− , (:-->)
40− , HasParameter (parameter)
41− , param
42− -- ** Null
43− , null_
44− , notNull
45− , coalesce
46− , fromNull
47− , isNull
48− , isNotNull
49− , matchNull
50− , nullIf
51− -- ** Collections
52− , array
53− , cardinality
54− , index
55− , row
56− , field
57− , PGSubset (..)
58− -- ** Functions
46+ , OperatorDB
5947 , unsafeBinaryOp
60− , unsafeUnaryOpL
61− , unsafeUnaryOpR
62− , unsafeFunction
63− , unsafeFunctionHet
64− , atan2_
65− , cast
66− , quot_
67− , rem_
68− , trunc
69− , round_
70− , ceiling_
71− , greatest
72− , least
73− , litChar
74− -- ** Conditions
75− , true
76− , false
77− , not_
78− , (.&&)
79− , (.||)
80− , Condition
81− , caseWhenThenElse
82− , ifThenElse
83− , (.==)
84− , (./=)
85− , (.>=)
86− , (.<)
87− , (.<=)
88− , (.>)
89− , between
90− , notBetween
91− , betweenSymmetric
92− , notBetweenSymmetric
93− , isDistinctFrom
94− , isNotDistinctFrom
95− , isTrue
96− , isNotTrue
97− , isFalse
98− , isNotFalse
99− , isUnknown
100− , isNotUnknown
101− -- ** Time
102− , currentDate
103− , currentTime
104− , currentTimestamp
105− , localTime
106− , localTimestamp
107− , TimeOp (..)
108− , makeDate
109− , makeTime
110− , makeTimestamp
111− , makeTimestamptz
112− -- ** Text
113− , lower
114− , upper
115− , charLength
116− , like
117− , ilike
118− -- ** Json
119− -- *** Json and Jsonb operators
120− , (.->)
121− , (.->>)
122− , (.#>)
123− , (.#>>)
124− -- *** Jsonb operators
125− , (.?)
126− , (.?|)
127− , (.?&)
128− , (.-.)
129− , (#-.)
130− -- *** Functions
131− , jsonLit
132− , jsonbLit
133− , toJson
134− , toJsonb
135− , arrayToJson
136− , rowToJson
137− , jsonBuildArray
138− , jsonbBuildArray
139− , PGBuildObject
140− , jsonBuildObject
141− , jsonbBuildObject
142− , jsonObject
143− , jsonbObject
144− , jsonZipObject
145− , jsonbZipObject
146− , jsonArrayLength
147− , jsonbArrayLength
148− , jsonExtractPath
149− , jsonbExtractPath
150− , jsonExtractPathAsText
151− , jsonbExtractPathAsText
152− , jsonTypeof
153− , jsonbTypeof
154− , jsonStripNulls
155− , jsonbStripNulls
156− , jsonbSet
157− , jsonbInsert
158− , jsonbPretty
159− -- ** Text Search
160− , (@@)
161− , (.&)
162− , (.|)
163− , (.!)
164− , (<->)
165− , arrayToTSvector
166− , tsvectorLength
167− , numnode
168− , plainToTSquery
169− , phraseToTSquery
170− , websearchToTSquery
171− , queryTree
172− , toTSquery
173− , toTSvector
174− , setWeight
175− , strip
176− , jsonToTSvector
177− , jsonbToTSvector
178− , tsDelete
179− , tsFilter
180− , tsHeadline
181− -- ** Aggregation
182− , Aggregate (..)
183− , Distinction (..)
184− , PGAvg
185− -- * Window Functions
186− , WindowDefinition (..)
187− , partitionBy
188− , WindowFunction (..)
189− , rank
190− , rowNumber
191− , denseRank
192− , percentRank
193− , cumeDist
194− , ntile
195− , lag
196− , lead
197− , firstValue
198− , lastValue
199− , nthValue
200− -- * Sorting
201− , SortExpression (..)
202− , OrderBy (..)
203− -- * Types
204− , TypeExpression (..)
205− , PGTyped (..)
206− , typedef
207− , typetable
208− , typeview
209− , bool
210− , int2
211− , smallint
212− , int4
213− , int
214− , integer
215− , int8
216− , bigint
217− , numeric
218− , float4
219− , real
220− , float8
221− , doublePrecision
222− , money
223− , text
224− , char
225− , character
226− , varchar
227− , characterVarying
228− , bytea
229− , timestamp
230− , timestampWithTimeZone
231− , date
232− , time
233− , timeWithTimeZone
234− , interval
235− , uuid
236− , inet
237− , json
238− , jsonb
239− , vararray
240− , fixarray
241− , tsvector
242− , tsquery
48+ , binaryOp
49+ , FunctionVar
50+ , unsafeFunctionVar
51+ , type (--->)
52+ , FunctionNDB
53+ , unsafeFunctionN
54+ , functionN
55+ , PGSubset (..)
56+ , PGIntersect (..)
24357 -- * Re-export
24458 , (&)
245− , NP (..)
24659 , K (..)
60+ , unK
24761 ) where
24862
24963import Control.Category
25064import Control.DeepSeq
25165import Data.ByteString (ByteString)
252−import Data.ByteString.Lazy (toStrict)
25366import Data.Function ((&))
254−import Data.Kind
25567import Data.Semigroup hiding (All)
256−import qualified Data.Aeson as JSON
25768import Data.String
258−import Data.Word
25969import Generics.SOP hiding (All, from)
26070import GHC.OverloadedLabels
26171import GHC.TypeLits
26272import Numeric
26373import Prelude hiding (id, (.))
26474
265−import qualified Data.ByteString as ByteString
26675import qualified GHC.Generics as GHC
267−import qualified Generics.SOP as SOP
26876
77+import Squeal.PostgreSQL.Alias
78+import Squeal.PostgreSQL.List
26979import Squeal.PostgreSQL.Render
27080import Squeal.PostgreSQL.Schema
27181
82+-- $setup
83+-- >>> import Squeal.PostgreSQL
84+
27285{-----------------------------------------
27386column expressions
27487-----------------------------------------}
27588
27689{- | `Expression`s are used in a variety of contexts,
277−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,
27892as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
27993`Squeal.PostgreSQL.Manipulation.update`,
280−or in search `Condition`s in a number of commands.
94+or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
28195
28296The expression syntax allows the calculation of
28397values from primitive expression using arithmetic, logical,
28498and 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`.
285113-}
286114newtype Expression
287115 (outer :: FromType)
288− (grp :: Grouping)
289116 (commons :: FromType)
117+ (grp :: Grouping)
290118 (schemas :: SchemasType)
291119 (params :: [NullityType])
292120 (from :: FromType)
293121 (ty :: NullityType)
294122 = UnsafeExpression { renderExpression :: ByteString }
295123 deriving (GHC.Generic,Show,Eq,Ord,NFData)
296−instance RenderSQL (Expression outer grp commons schemas params from ty) where
124+instance RenderSQL (Expression outer commons grp schemas params from ty) where
297125 renderSQL = renderExpression
298126
299127-- | An `Expr` is a closed `Expression`.
300−-- It is a F`RankNType` but don't be scared.
128+-- It is a F@RankNType@ but don't be scared.
301129-- Think of it as an expression which sees no
302130-- namespaces, so you can't use parameters
303131-- or alias references. It can be used as
304132-- a simple piece of more complex `Expression`s.
305133type Expr x
306− = forall outer grp commons schemas params from
307− . Expression outer grp commons schemas params from x
134+ = forall outer commons grp schemas params from
135+ . Expression outer commons grp schemas params from x
308136 -- ^ cannot reference aliases
309137
310−-- | A `RankNType` for binary operators.
138+-- | A @RankNType@ for binary operators.
311139type Operator x1 x2 y
312− = forall outer grp commons schemas params from
313− . Expression outer grp commons schemas params from x1
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
314151 -- ^ left input
315− -> Expression outer grp commons schemas params from x2
152+ -> Expression outer commons grp schemas params from x2
316153 -- ^ right input
317− -> Expression outer grp commons schemas params from y
154+ -> Expression outer commons grp schemas params from y
318155 -- ^ output
319156
320−-- | A `RankNType` for functions with a single argument.
157+-- | A @RankNType@ for functions with a single argument.
321158-- These could be either function calls or unary operators.
322159-- This is a subtype of the usual Haskell function type `Prelude.->`,
323160-- indeed a subcategory as it is closed under the usual
324161-- `Prelude..` and `Prelude.id`.
325−type (:-->) x y
326− = forall outer grp commons schemas params from
327− . Expression outer grp commons schemas params from x
162+type (-->) x y
163+ = forall outer commons grp schemas params from
164+ . Expression outer commons grp schemas params from x
328165 -- ^ input
329− -> Expression outer grp commons schemas params from y
166+ -> Expression outer commons grp schemas params from y
330167 -- ^ output
331168
332−type FunctionHet xs y
333− = forall outer grp commons schemas params from
334− . NP (Expression outer grp commons schemas params from) xs
335− -- ^ inputs
336− -> Expression outer grp commons schemas params from y
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
337174 -- ^ output
338175
339−type FunctionHom x0 x1 y
340− = forall outer grp commons schemas params from
341− . [Expression outer grp commons schemas params from x0]
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)
181+-}
182+type (--->) xs y
183+ = forall outer commons grp schemas params from
184+ . NP (Expression outer commons grp schemas params from) xs
342185 -- ^ inputs
343− -> Expression outer grp commons schemas params from x1
344− -- ^ must have at least 1 input
345− -> Expression outer grp commons schemas params from y
186+ -> Expression outer commons grp schemas params from y
346187 -- ^ output
347188
348−unsafeFunctionHom :: ByteString -> FunctionHom x0 x1 y
349−unsafeFunctionHom fun xs x = UnsafeExpression $ fun <> parenthesized
350− (commaSeparated (renderSQL <$> xs) <> ", " <> renderSQL x)
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
351195
352−{- | A `HasParameter` constraint is used to indicate a value that is
353−supplied externally to a SQL statement.
354−`Squeal.PostgreSQL.PQ.manipulateParams`,
355−`Squeal.PostgreSQL.PQ.queryParams` and
356−`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
357−separately from the SQL command string, in which case `param`s are used to
358−refer to the out-of-line data values.
196+{- | A @RankNType@ for functions with a variable-length list of
197+homogeneous arguments and at least 1 more argument.
359198-}
360−class KnownNat n => HasParameter
361− (n :: Nat)
362− (params :: [NullityType])
363− (ty :: NullityType)
364− | n params -> ty where
365− -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
366− --
367− -- >>> let expr = parameter @1 int4 :: Expression outer grp '[] schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
368− -- >>> printSQL expr
369− -- ($1 :: int4)
370− parameter
371− :: TypeExpression schemas ty
372− -> Expression outer grp commons schemas params from ty
373− parameter ty = UnsafeExpression $ parenthesized $
374− "$" <> renderNat @n <+> "::"
375− <+> renderSQL ty
376−instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
377−instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
378− => HasParameter n (ty' : params) ty
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
379207
380−-- | `param` takes a `Nat` using type application and for basic types,
381−-- infers a `TypeExpression`.
382−--
383−-- >>> let expr = param @1 :: Expression outer grp commons schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
384−-- >>> printSQL expr
385−-- ($1 :: int4)
386−param
387− :: forall n outer commons schemas params from grp ty
388− . (PGTyped schemas ty, HasParameter n params ty)
389− => Expression outer grp commons schemas params from ty -- ^ param
390−param = parameter @n (pgtype @schemas)
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)
391214
392215instance (HasUnique tab (Join outer from) row, Has col row ty)
393− => IsLabel col (Expression outer 'Ungrouped commons schemas params from ty) where
216+ => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
394217 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
395218instance (HasUnique tab (Join outer from) row, Has col row ty, tys ~ '[ty])
396− => IsLabel col (NP (Expression outer 'Ungrouped commons schemas params from) tys) where
219+ => IsLabel col (NP (Expression outer commons 'Ungrouped schemas params from) tys) where
397220 fromLabel = fromLabel @col :* Nil
398221instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
399222 => IsLabel col
400− (Aliased (Expression outer 'Ungrouped commons schemas params from) column) where
223+ (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
401224 fromLabel = fromLabel @col `As` Alias
402225instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
403226 => IsLabel col
404− (NP (Aliased (Expression outer 'Ungrouped commons schemas params from)) columns) where
227+ (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
405228 fromLabel = fromLabel @col :* Nil
406229
407230instance (Has tab (Join outer from) row, Has col row ty)
408− => IsQualified tab col (Expression outer 'Ungrouped commons schemas params from ty) where
231+ => IsQualified tab col (Expression outer commons 'Ungrouped schemas params from ty) where
409232 tab ! col = UnsafeExpression $
410233 renderSQL tab <> "." <> renderSQL col
411234instance (Has tab (Join outer from) row, Has col row ty, tys ~ '[ty])
412− => IsQualified tab col (NP (Expression outer 'Ungrouped commons schemas params from) tys) where
235+ => IsQualified tab col (NP (Expression outer commons 'Ungrouped schemas params from) tys) where
413236 tab ! col = tab ! col :* Nil
414237instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
415238 => IsQualified tab col
416− (Aliased (Expression outer 'Ungrouped commons schemas params from) column) where
239+ (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
417240 tab ! col = tab ! col `As` col
418241instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
419242 => IsQualified tab col
420− (NP (Aliased (Expression outer 'Ungrouped commons schemas params from)) columns) where
243+ (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
421244 tab ! col = tab ! col :* Nil
422245
423246instance
@@ -425,7 +248,7 @@ instance
425248 , Has col row ty
426249 , GroupedBy tab col bys
427250 ) => IsLabel col
428− (Expression outer ('Grouped bys) commons schemas params from ty) where
251+ (Expression outer commons ('Grouped bys) schemas params from ty) where
429252 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
430253instance
431254 ( HasUnique tab (Join outer from) row
@@ -433,7 +256,7 @@ instance
433256 , GroupedBy tab col bys
434257 , tys ~ '[ty]
435258 ) => IsLabel col
436− (NP (Expression outer ('Grouped bys) commons schemas params from) tys) where
259+ (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
437260 fromLabel = fromLabel @col :* Nil
438261instance
439262 ( HasUnique tab (Join outer from) row
@@ -441,7 +264,7 @@ instance
441264 , GroupedBy tab col bys
442265 , column ~ (col ::: ty)
443266 ) => IsLabel col
444− (Aliased (Expression outer ('Grouped bys) commons schemas params from) column) where
267+ (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
445268 fromLabel = fromLabel @col `As` Alias
446269instance
447270 ( HasUnique tab (Join outer from) row
@@ -449,7 +272,7 @@ instance
449272 , GroupedBy tab col bys
450273 , columns ~ '[col ::: ty]
451274 ) => IsLabel col
452− (NP (Aliased (Expression outer ('Grouped bys) commons schemas params from)) columns) where
275+ (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
453276 fromLabel = fromLabel @col :* Nil
454277
455278instance
@@ -457,7 +280,7 @@ instance
457280 , Has col row ty
458281 , GroupedBy tab col bys
459282 ) => IsQualified tab col
460− (Expression outer ('Grouped bys) commons schemas params from ty) where
283+ (Expression outer commons ('Grouped bys) schemas params from ty) where
461284 tab ! col = UnsafeExpression $
462285 renderSQL tab <> "." <> renderSQL col
463286instance
@@ -466,7 +289,7 @@ instance
466289 , GroupedBy tab col bys
467290 , tys ~ '[ty]
468291 ) => IsQualified tab col
469− (NP (Expression outer ('Grouped bys) commons schemas params from) tys) where
292+ (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
470293 tab ! col = tab ! col :* Nil
471294instance
472295 ( Has tab (Join outer from) row
@@ -474,7 +297,7 @@ instance
474297 , GroupedBy tab col bys
475298 , column ~ (col ::: ty)
476299 ) => IsQualified tab col
477− (Aliased (Expression outer ('Grouped bys) commons schemas params from) column) where
300+ (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
478301 tab ! col = tab ! col `As` col
479302instance
480303 ( Has tab (Join outer from) row
@@ -482,196 +305,78 @@ instance
482305 , GroupedBy tab col bys
483306 , columns ~ '[col ::: ty]
484307 ) => IsQualified tab col
485− (NP (Aliased (Expression outer ('Grouped bys) commons schemas params from)) columns) where
308+ (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
486309 tab ! col = tab ! col :* Nil
487310
488−-- | analagous to `Nothing`
489−--
490−-- >>> printSQL null_
491−-- NULL
492−null_ :: Expr ('Null ty)
493−null_ = UnsafeExpression "NULL"
494−
495−-- | analagous to `Just`
496−--
497−-- >>> printSQL $ notNull true
498−-- TRUE
499−notNull :: 'NotNull ty :--> 'Null ty
500−notNull = UnsafeExpression . renderSQL
501−
502−-- | return the leftmost value which is not NULL
503−--
504−-- >>> printSQL $ coalesce [null_, true] false
505−-- COALESCE(NULL, TRUE, FALSE)
506−coalesce :: FunctionHom ('Null ty) ('NotNull ty) ('NotNull ty)
507−coalesce nullxs notNullx = UnsafeExpression $
508− "COALESCE" <> parenthesized (commaSeparated
509− ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
510−
511−-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
512−--
513−-- >>> printSQL $ fromNull true null_
514−-- COALESCE(NULL, TRUE)
515−fromNull
516− :: Expression outer grp commons schemas params from ('NotNull ty)
517− -- ^ what to convert @NULL@ to
518− -> Expression outer grp commons schemas params from ('Null ty)
519− -> Expression outer grp commons schemas params from ('NotNull ty)
520−fromNull notNullx nullx = coalesce [nullx] notNullx
521−
522−-- | >>> printSQL $ null_ & isNull
523−-- NULL IS NULL
524−isNull :: 'Null ty :--> null 'PGbool
525−isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
526−
527−-- | >>> printSQL $ null_ & isNotNull
528−-- NULL IS NOT NULL
529−isNotNull :: 'Null ty :--> null 'PGbool
530−isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
531−
532−-- | analagous to `maybe` using @IS NULL@
533−--
534−-- >>> printSQL $ matchNull true not_ null_
535−-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
536−matchNull
537− :: Expression outer grp commons schemas params from (nullty)
538− -- ^ what to convert @NULL@ to
539− -> ( Expression outer grp commons schemas params from ('NotNull ty)
540− -> Expression outer grp commons schemas params from (nullty) )
541− -- ^ function to perform when @NULL@ is absent
542− -> Expression outer grp commons schemas params from ('Null ty)
543− -> Expression outer grp commons schemas params from (nullty)
544−matchNull y f x = ifThenElse (isNull x) y
545− (f (UnsafeExpression (renderSQL x)))
546−
547−{-| right inverse to `fromNull`, if its arguments are equal then
548−`nullIf` gives @NULL@.
549−
550−>>> :set -XTypeApplications -XDataKinds
551−>>> let expr = nullIf (false *: param @1) :: Expression outer grp commons schemas '[ 'NotNull 'PGbool] from ('Null 'PGbool)
552−>>> printSQL expr
553−NULLIF(FALSE, ($1 :: bool))
554−-}
555−nullIf :: FunctionHet '[ 'NotNull ty, 'NotNull ty] ('Null ty)
556−nullIf = unsafeFunctionHet "NULLIF"
557−
558−-- | >>> printSQL $ array [null_, false, true]
559−-- ARRAY[NULL, FALSE, TRUE]
560−array
561− :: [Expression outer grp commons schemas params from ty]
562− -- ^ array elements
563− -> Expression outer grp commons schemas params from (null ('PGvararray ty))
564−array xs = UnsafeExpression $
565− "ARRAY[" <> commaSeparated (renderSQL <$> xs) <> "]"
566−
567−-- | >>> printSQL $ cardinality (array [null_, false, true])
568−-- cardinality(ARRAY[NULL, FALSE, TRUE])
569−cardinality :: null ('PGvararray ty) :--> null 'PGint8
570−cardinality = unsafeFunction "cardinality"
571−
572−-- | >>> printSQL $ array [null_, false, true] & index 2
573−-- (ARRAY[NULL, FALSE, TRUE])[2]
574−index
575− :: Word64 -- ^ index
576− -> null ('PGvararray ty) :--> NullifyType ty
577−index n expr = UnsafeExpression $
578− parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
579−
580311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
581− (Expression outer grp commons schemas params from (null ('PGenum labels))) where
312+ (Expression outer commons grp schemas params from (null ('PGenum labels))) where
582313 label = UnsafeExpression $ renderSQL (PGlabel @label)
583314
584−-- | A row constructor is an expression that builds a row value
585−-- (also called a composite value) using values for its member fields.
586−--
587−-- >>> :{
588−-- type Complex = 'PGcomposite
589−-- '[ "real" ::: 'NotNull 'PGfloat8
590−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
591−-- :}
592−--
593−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer grp commons schemas params from ('NotNull Complex)
594−-- >>> printSQL i
595−-- ROW(0, 1)
596−row
597− :: SListI row
598− => NP (Aliased (Expression outer grp commons schemas params from)) row
599− -- ^ zero or more expressions for the row field values
600− -> Expression outer grp commons schemas params from (null ('PGcomposite row))
601−row exprs = UnsafeExpression $ "ROW" <> parenthesized
602− (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
603−
604−-- | >>> :{
605−-- type Complex = 'PGcomposite
606−-- '[ "real" ::: 'NotNull 'PGfloat8
607−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
608−-- type Schema = '["complex" ::: 'Typedef Complex]
609−-- :}
610−--
611−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer grp '[] (Public Schema) from params ('NotNull Complex)
612−-- >>> printSQL $ i & field #complex #imaginary
613−-- (ROW(0, 1)::"complex")."imaginary"
614−field
615− :: ( Has sch schemas schema
616− , Has tydef schema ('Typedef ('PGcomposite row))
617− , Has field row ty)
618− => QualifiedAlias sch tydef -- ^ row type
619− -> Alias field -- ^ field name
620− -> Expression outer grp commons schemas params from ('NotNull ('PGcomposite row))
621− -> Expression outer grp commons schemas params from ty
622−field td fld expr = UnsafeExpression $
623− parenthesized (renderSQL expr <> "::" <> renderSQL td)
624− <> "." <> renderSQL fld
625−
626−instance Semigroup
627− (Expression outer grp commons schemas params from (null ('PGvararray ty))) where
628− (<>) = unsafeBinaryOp "||"
629−
630−instance Monoid
631− (Expression outer grp commons schemas params from (null ('PGvararray ty))) where
632− mempty = array []
633− mappend = (<>)
634−
635−-- | >>> let expr = greatest [param @1] currentTimestamp :: Expression outer grp commons schemas '[ 'NotNull 'PGtimestamptz] from ('NotNull 'PGtimestamptz)
636−-- >>> printSQL expr
637−-- GREATEST(($1 :: timestamp with time zone), CURRENT_TIMESTAMP)
638−greatest :: FunctionHom ty ty ty
639−greatest = unsafeFunctionHom "GREATEST"
640−
641−-- | >>> printSQL $ least [null_] currentTimestamp
642−-- LEAST(NULL, CURRENT_TIMESTAMP)
643−least :: FunctionHom ty ty ty
644−least = unsafeFunctionHom "LEAST"
645−
646315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
647316-- (TRUE OR FALSE)
648−unsafeBinaryOp :: ByteString {- ^ operator -} -> Operator ty0 ty1 ty2
317+unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
649318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
650319 renderSQL x <+> op <+> renderSQL y
651320
652−-- | >>> printSQL $ unsafeUnaryOpL "NOT" true
653−-- (NOT TRUE)
654−unsafeUnaryOpL :: ByteString {- ^ operator -} -> x :--> y
655−unsafeUnaryOpL op x = UnsafeExpression $ parenthesized $ op <+> renderSQL x
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
656327
657−unsafeUnaryOpR :: ByteString {- ^ operator -} -> x :--> y
658−unsafeUnaryOpR op x = UnsafeExpression $ parenthesized $ renderSQL x <+> op
328+-- | >>> printSQL $ unsafeLeftOp "NOT" true
329+-- (NOT TRUE)
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
659351
660352-- | >>> printSQL $ unsafeFunction "f" true
661353-- f(TRUE)
662−unsafeFunction :: ByteString {- ^ function -} -> x :--> y
354+unsafeFunction :: ByteString -> x --> y
663355unsafeFunction fun x = UnsafeExpression $
664356 fun <> parenthesized (renderSQL x)
665357
666−unsafeFunctionHet
667− :: SListI xs
668− => ByteString {- ^ function -}
669− -> FunctionHet xs y
670−unsafeFunctionHet fun xs = UnsafeExpression $
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 $
671368 fun <> parenthesized (renderCommaSeparated renderSQL xs)
672369
370+functionN
371+ :: ( Has sch schemas schema
372+ , Has fun schema ('Function (xs :=> 'Returns y))
373+ , SListI xs )
374+ => QualifiedAlias sch fun
375+ -> FunctionNDB schemas xs y
376+functionN = unsafeFunctionN . renderSQL
377+
673378instance ty `In` PGNum
674− => Num (Expression outer grp commons schemas params from (null ty)) where
379+ => Num (Expression outer commons grp schemas params from (null ty)) where
675380 (+) = unsafeBinaryOp "+"
676381 (-) = unsafeBinaryOp "-"
677382 (*) = unsafeBinaryOp "*"
@@ -683,7 +388,7 @@ instance ty `In` PGNum
683388 . show
684389
685390instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
686− (Expression outer grp commons schemas params from (null ty)) where
391+ (Expression outer commons grp schemas params from (null ty)) where
687392 (/) = unsafeBinaryOp "/"
688393 fromRational
689394 = UnsafeExpression
@@ -693,7 +398,7 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
693398 . fromRat @Double
694399
695400instance (ty `In` PGNum, ty `In` PGFloating) => Floating
696− (Expression outer grp commons schemas params from (null ty)) where
401+ (Expression outer commons grp schemas params from (null ty)) where
697402 pi = UnsafeExpression "pi()"
698403 exp = unsafeFunction "exp"
699404 log = unsafeFunction "ln"
@@ -714,1748 +419,54 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
714419 acosh x = log (x + sqrt (x*x - 1))
715420 atanh x = log ((1 + x) / (1 - x)) / 2
716421
717−-- | >>> :{
718−-- let
719−-- expression :: Expr (null 'PGfloat4)
720−-- expression = atan2_ (pi *: 2)
721−-- in printSQL expression
722−-- :}
723−-- atan2(pi(), 2)
724−atan2_
725− :: float `In` PGFloating
726− => FunctionHet '[ null float, null float] (null float)
727−atan2_ = unsafeFunctionHet "atan2"
728−
729−-- When a `cast` is applied to an `Expression` of a known type, it
730−-- represents a run-time type conversion. The cast will succeed only if a
731−-- suitable type conversion operation has been defined.
732−--
733−-- | >>> printSQL $ true & cast int4
734−-- (TRUE :: int4)
735−cast
736− :: TypeExpression schemas ty1
737− -- ^ type to cast as
738− -> Expression outer grp commons schemas params from ty0
739− -- ^ value to convert
740− -> Expression outer grp commons schemas params from ty1
741−cast ty x = UnsafeExpression $ parenthesized $
742− renderSQL x <+> "::" <+> renderSQL ty
743−
744−-- | integer division, truncates the result
745−--
746−-- >>> :{
747−-- let
748−-- expression :: Expression outer grp commons schemas params from (null 'PGint2)
749−-- expression = 5 `quot_` 2
750−-- in printSQL expression
751−-- :}
752−-- (5 / 2)
753−quot_
754− :: int `In` PGIntegral
755− => Operator (null int) (null int) (null int)
756−quot_ = unsafeBinaryOp "/"
757−
758−-- | remainder upon integer division
759−--
760−-- >>> :{
761−-- let
762−-- expression :: Expression outer grp commons schemas params from (null 'PGint2)
763−-- expression = 5 `rem_` 2
764−-- in printSQL expression
765−-- :}
766−-- (5 % 2)
767−rem_
768− :: int `In` PGIntegral
769− => Operator (null int) (null int) (null int)
770−rem_ = unsafeBinaryOp "%"
771−
772−-- | >>> :{
773−-- let
774−-- expression :: Expression outer grp commons schemas params from (null 'PGfloat4)
775−-- expression = trunc pi
776−-- in printSQL expression
777−-- :}
778−-- trunc(pi())
779−trunc :: frac `In` PGFloating => null frac :--> null frac
780−trunc = unsafeFunction "trunc"
781−
782−-- | >>> :{
783−-- let
784−-- expression :: Expression outer grp commons schemas params from (null 'PGfloat4)
785−-- expression = round_ pi
786−-- in printSQL expression
787−-- :}
788−-- round(pi())
789−round_ :: frac `In` PGFloating => null frac :--> null frac
790−round_ = unsafeFunction "round"
791−
792−-- | >>> :{
793−-- let
794−-- expression :: Expression outer grp commons schemas params from (null 'PGfloat4)
795−-- expression = ceiling_ pi
796−-- in printSQL expression
797−-- :}
798−-- ceiling(pi())
799−ceiling_ :: frac `In` PGFloating => null frac :--> null frac
800−ceiling_ = unsafeFunction "ceiling"
801−
802−-- | A `Condition` is an `Expression`, which can evaluate
803−-- to `true`, `false` or `null_`. This is because SQL uses
804−-- a three valued logic.
805−type Condition outer grp commons schemas params from =
806− Expression outer grp commons schemas params from ('Null 'PGbool)
807−
808−-- | >>> printSQL true
809−-- TRUE
810−true :: Expr (null 'PGbool)
811−true = UnsafeExpression "TRUE"
812−
813−-- | >>> printSQL false
814−-- FALSE
815−false :: Expr (null 'PGbool)
816−false = UnsafeExpression "FALSE"
817−
818−-- | >>> printSQL $ not_ true
819−-- (NOT TRUE)
820−not_ :: null 'PGbool :--> null 'PGbool
821−not_ = unsafeUnaryOpL "NOT"
822−
823−-- | >>> printSQL $ true .&& false
824−-- (TRUE AND FALSE)
825−(.&&) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
826−infixr 3 .&&
827−(.&&) = unsafeBinaryOp "AND"
828−
829−-- | >>> printSQL $ true .|| false
830−-- (TRUE OR FALSE)
831−(.||) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
832−infixr 2 .||
833−(.||) = unsafeBinaryOp "OR"
834−
835−-- | >>> :{
836−-- let
837−-- expression :: Expression outer grp commons schemas params from (null 'PGint2)
838−-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
839−-- in printSQL expression
840−-- :}
841−-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
842−caseWhenThenElse
843− :: [ ( Condition outer grp commons schemas params from
844− , Expression outer grp commons schemas params from ty
845− ) ]
846− -- ^ whens and thens
847− -> Expression outer grp commons schemas params from ty
848− -- ^ else
849− -> Expression outer grp commons schemas params from ty
850−caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
851− [ "CASE"
852− , mconcat
853− [ mconcat
854− [ " WHEN ", renderSQL when_
855− , " THEN ", renderSQL then_
856− ]
857− | (when_,then_) <- whenThens
858− ]
859− , " ELSE ", renderSQL else_
860− , " END"
861− ]
862−
863−-- | >>> :{
864−-- let
865−-- expression :: Expression outer grp commons schemas params from (null 'PGint2)
866−-- expression = ifThenElse true 1 0
867−-- in printSQL expression
868−-- :}
869−-- CASE WHEN TRUE THEN 1 ELSE 0 END
870−ifThenElse
871− :: Condition outer grp commons schemas params from
872− -> Expression outer grp commons schemas params from ty -- ^ then
873− -> Expression outer grp commons schemas params from ty -- ^ else
874− -> Expression outer grp commons schemas params from ty
875−ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
876−
877−-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
878−-- will produce @NULL@s if one of their arguments is @NULL@.
879−--
880−-- >>> printSQL $ true .== null_
881−-- (TRUE = NULL)
882−(.==) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
883−(.==) = unsafeBinaryOp "="
884−infix 4 .==
885−
886−-- | >>> printSQL $ true ./= null_
887−-- (TRUE <> NULL)
888−(./=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
889−(./=) = unsafeBinaryOp "<>"
890−infix 4 ./=
891−
892−-- | >>> printSQL $ true .>= null_
893−-- (TRUE >= NULL)
894−(.>=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
895−(.>=) = unsafeBinaryOp ">="
896−infix 4 .>=
897−
898−-- | >>> printSQL $ true .< null_
899−-- (TRUE < NULL)
900−(.<) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
901−(.<) = unsafeBinaryOp "<"
902−infix 4 .<
903−
904−-- | >>> printSQL $ true .<= null_
905−-- (TRUE <= NULL)
906−(.<=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
907−(.<=) = unsafeBinaryOp "<="
908−infix 4 .<=
909−
910−-- | >>> printSQL $ true .> null_
911−-- (TRUE > NULL)
912−(.>) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
913−(.>) = unsafeBinaryOp ">"
914−infix 4 .>
915−
916−{- | >>> printSQL $ true `between` (null_, false)
917−TRUE BETWEEN NULL AND FALSE
918−-}
919−between
920− :: Expression outer grp commons schemas params from (null ty)
921− -> ( Expression outer grp commons schemas params from (null ty)
922− , Expression outer grp commons schemas params from (null ty) ) -- ^ bounds
923− -> Condition outer grp commons schemas params from
924−between a (x,y) = UnsafeExpression $ renderSQL a <+> "BETWEEN"
925− <+> renderSQL x <+> "AND" <+> renderSQL y
926−
927−{- | >>> printSQL $ true `notBetween` (null_, false)
928−TRUE NOT BETWEEN NULL AND FALSE
929−-}
930−notBetween
931− :: Expression outer grp commons schemas params from (null ty)
932− -> ( Expression outer grp commons schemas params from (null ty)
933− , Expression outer grp commons schemas params from (null ty) ) -- ^ bounds
934− -> Condition outer grp commons schemas params from
935−notBetween a (x,y) = UnsafeExpression $ renderSQL a <+> "NOT BETWEEN"
936− <+> renderSQL x <+> "AND" <+> renderSQL y
937−
938−{- | between, after sorting the comparison values
939−
940−>>> printSQL $ true `betweenSymmetric` (null_, false)
941−TRUE BETWEEN SYMMETRIC NULL AND FALSE
942−-}
943−betweenSymmetric
944− :: Expression outer grp commons schemas params from (null ty)
945− -> ( Expression outer grp commons schemas params from (null ty)
946− , Expression outer grp commons schemas params from (null ty) ) -- ^ bounds
947− -> Condition outer grp commons schemas params from
948−betweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
949− <+> "BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
950−
951−{- | not between, after sorting the comparison values
952−
953−>>> printSQL $ true `notBetweenSymmetric` (null_, false)
954−TRUE NOT BETWEEN SYMMETRIC NULL AND FALSE
955−-}
956−notBetweenSymmetric
957− :: Expression outer grp commons schemas params from (null ty)
958− -> ( Expression outer grp commons schemas params from (null ty)
959− , Expression outer grp commons schemas params from (null ty) ) -- ^ bounds
960− -> Condition outer grp commons schemas params from
961−notBetweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
962− <+> "NOT BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
963−
964−{- | not equal, treating null like an ordinary value
965−
966−>>> printSQL $ true `isDistinctFrom` null_
967−(TRUE IS DISTINCT FROM NULL)
968−-}
969−isDistinctFrom :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
970−isDistinctFrom = unsafeBinaryOp "IS DISTINCT FROM"
971−
972−{- | equal, treating null like an ordinary value
973−
974−>>> printSQL $ true `isNotDistinctFrom` null_
975−(TRUE IS NOT DISTINCT FROM NULL)
976−-}
977−isNotDistinctFrom :: Operator (null0 ty) (null1 ty) ('NotNull 'PGbool)
978−isNotDistinctFrom = unsafeBinaryOp "IS NOT DISTINCT FROM"
979−
980−{- | is true
981−
982−>>> printSQL $ true & isTrue
983−(TRUE IS TRUE)
984−-}
985−isTrue :: null0 'PGbool :--> null1 'PGbool
986−isTrue = unsafeUnaryOpR "IS TRUE"
987−
988−{- | is false or unknown
989−
990−>>> printSQL $ true & isNotTrue
991−(TRUE IS NOT TRUE)
992−-}
993−isNotTrue :: null0 'PGbool :--> null1 'PGbool
994−isNotTrue = unsafeUnaryOpR "IS NOT TRUE"
995−
996−{- | is false
997−
998−>>> printSQL $ true & isFalse
999−(TRUE IS FALSE)
1000−-}
1001−isFalse :: null0 'PGbool :--> null1 'PGbool
1002−isFalse = unsafeUnaryOpR "IS FALSE"
1003−
1004−{- | is true or unknown
1005−
1006−>>> printSQL $ true & isNotFalse
1007−(TRUE IS NOT FALSE)
1008−-}
1009−isNotFalse :: null0 'PGbool :--> null1 'PGbool
1010−isNotFalse = unsafeUnaryOpR "IS NOT FALSE"
1011−
1012−{- | is unknown
1013−
1014−>>> printSQL $ true & isUnknown
1015−(TRUE IS UNKNOWN)
1016−-}
1017−isUnknown :: null0 'PGbool :--> null1 'PGbool
1018−isUnknown = unsafeUnaryOpR "IS UNKNOWN"
1019−
1020−{- | is true or false
1021−
1022−>>> printSQL $ true & isNotUnknown
1023−(TRUE IS NOT UNKNOWN)
1024−-}
1025−isNotUnknown :: null0 'PGbool :--> null1 'PGbool
1026−isNotUnknown = unsafeUnaryOpR "IS NOT UNKNOWN"
1027−
1028−-- | >>> printSQL currentDate
1029−-- CURRENT_DATE
1030−currentDate :: Expr (null 'PGdate)
1031−currentDate = UnsafeExpression "CURRENT_DATE"
1032−
1033−-- | >>> printSQL currentTime
1034−-- CURRENT_TIME
1035−currentTime :: Expr (null 'PGtimetz)
1036−currentTime = UnsafeExpression "CURRENT_TIME"
1037−
1038−-- | >>> printSQL currentTimestamp
1039−-- CURRENT_TIMESTAMP
1040−currentTimestamp :: Expr (null 'PGtimestamptz)
1041−currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
1042−
1043−-- | >>> printSQL localTime
1044−-- LOCALTIME
1045−localTime :: Expr (null 'PGtime)
1046−localTime = UnsafeExpression "LOCALTIME"
1047−
1048−-- | >>> printSQL localTimestamp
1049−-- LOCALTIMESTAMP
1050−localTimestamp :: Expr (null 'PGtimestamp)
1051−localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
1052−
1053−{-----------------------------------------
1054−text
1055−-----------------------------------------}
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)
1056432
1057−escape :: Char -> String
1058−escape = \case
1059− '\NUL' -> "\\0"
1060− '\'' -> "''"
1061− '"' -> "\\\""
1062− '\b' -> "\\b"
1063− '\n' -> "\\n"
1064− '\r' -> "\\r"
1065− '\t' -> "\\t"
1066− '\\' -> "\\\\"
1067− c -> [c]
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)
1068438
1069439instance IsString
1070− (Expression outer grp commons schemas params from (null 'PGtext)) where
440+ (Expression outer commons grp schemas params from (null 'PGtext)) where
1071441 fromString str = UnsafeExpression $
1072442 "E\'" <> fromString (escape =<< str) <> "\'"
1073443instance IsString
1074− (Expression outer grp commons schemas params from (null 'PGtsvector)) where
1075− fromString str = cast tsvector . UnsafeExpression $
444+ (Expression outer commons grp schemas params from (null 'PGtsvector)) where
445+ fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
1076446 "E\'" <> fromString (escape =<< str) <> "\'"
1077447instance IsString
1078− (Expression outer grp commons schemas params from (null 'PGtsquery)) where
1079− fromString str = cast tsquery . UnsafeExpression $
448+ (Expression outer commons grp schemas params from (null 'PGtsquery)) where
449+ fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
1080450 "E\'" <> fromString (escape =<< str) <> "\'"
1081451
1082452instance Semigroup
1083− (Expression outer grp commons schemas params from (null 'PGtext)) where
453+ (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
1084454 (<>) = unsafeBinaryOp "||"
1085455instance Semigroup
1086− (Expression outer grp commons schemas params from (null 'PGtsvector)) where
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
1087463 (<>) = unsafeBinaryOp "||"
1088464
1089465instance Monoid
1090− (Expression outer grp commons schemas params from (null 'PGtext)) where
466+ (Expression outer commons grp schemas params from (null 'PGtext)) where
1091467 mempty = fromString ""
1092468 mappend = (<>)
1093469instance Monoid
1094− (Expression outer grp commons schemas params from (null 'PGtsvector)) where
470+ (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1095471 mempty = fromString ""
1096472 mappend = (<>)
1097−
1098−-- | >>> printSQL $ lower "ARRRGGG"
1099−-- lower(E'ARRRGGG')
1100−lower :: null 'PGtext :--> null 'PGtext
1101−lower = unsafeFunction "lower"
1102−
1103−-- | >>> printSQL $ upper "eeee"
1104−-- upper(E'eeee')
1105−upper :: null 'PGtext :--> null 'PGtext
1106−upper = unsafeFunction "upper"
1107−
1108−-- | >>> printSQL $ charLength "four"
1109−-- char_length(E'four')
1110−charLength :: null 'PGtext :--> null 'PGint4
1111−charLength = unsafeFunction "char_length"
1112−
1113−-- | The `like` expression returns true if the @string@ matches
1114−-- the supplied @pattern@. If @pattern@ does not contain percent signs
1115−-- or underscores, then the pattern only represents the string itself;
1116−-- in that case `like` acts like the equals operator. An underscore (_)
1117−-- in pattern stands for (matches) any single character; a percent sign (%)
1118−-- matches any sequence of zero or more characters.
1119−--
1120−-- >>> printSQL $ "abc" `like` "a%"
1121−-- (E'abc' LIKE E'a%')
1122−like :: Operator (null 'PGtext) (null 'PGtext) ('Null 'PGbool)
1123−like = unsafeBinaryOp "LIKE"
1124−
1125−-- | The key word ILIKE can be used instead of LIKE to make the
1126−-- match case-insensitive according to the active locale.
1127−--
1128−-- >>> printSQL $ "abc" `ilike` "a%"
1129−-- (E'abc' ILIKE E'a%')
1130−ilike :: Operator (null 'PGtext) (null 'PGtext) ('Null 'PGbool)
1131−ilike = unsafeBinaryOp "ILIKE"
1132−
1133−{-----------------------------------------
1134− -- json and jsonb support
1135−
1136−See https://www.postgresql.org/docs/10/static/functions-json.html -- most
1137−comments lifted directly from this page.
1138−
1139−Table 9.44: json and jsonb operators
1140−-----------------------------------------}
1141−
1142−-- | Get JSON value (object field or array element) at a key.
1143−(.->)
1144− :: (json `In` PGJsonType, key `In` PGJsonKey)
1145− => Operator (null json) (null key) ('Null json)
1146−infixl 8 .->
1147−(.->) = unsafeBinaryOp "->"
1148−
1149−-- | Get JSON value (object field or array element) at a key, as text.
1150−(.->>)
1151− :: (json `In` PGJsonType, key `In` PGJsonKey)
1152− => Operator (null json) (null key) ('Null 'PGtext)
1153−infixl 8 .->>
1154−(.->>) = unsafeBinaryOp "->>"
1155−
1156−-- | Get JSON value at a specified path.
1157−(.#>)
1158− :: json `In` PGJsonType
1159− => Operator (null json) (null ('PGvararray ('NotNull 'PGtext))) ('Null json)
1160−infixl 8 .#>
1161−(.#>) = unsafeBinaryOp "#>"
1162−
1163−-- | Get JSON value at a specified path as text.
1164−(.#>>)
1165− :: json `In` PGJsonType
1166− => Operator (null json) (null ('PGvararray ('NotNull 'PGtext))) ('Null 'PGtext)
1167−infixl 8 .#>>
1168−(.#>>) = unsafeBinaryOp "#>>"
1169−
1170−-- Additional jsonb operators
1171−
1172−class PGSubset container where
1173− (@>) :: Operator (null0 container) (null1 container) ('Null 'PGbool)
1174− (@>) = unsafeBinaryOp "@>"
1175− (<@) :: Operator (null0 container) (null1 container) ('Null 'PGbool)
1176− (<@) = unsafeBinaryOp "<@"
1177−instance PGSubset 'PGjsonb
1178−instance PGSubset 'PGtsquery
1179−instance PGSubset ('PGvararray ty)
1180−
1181−-- | Does the string exist as a top-level key within the JSON value?
1182−(.?) :: Operator (null 'PGjsonb) (null 'PGtext) ('Null 'PGbool)
1183−infixl 9 .?
1184−(.?) = unsafeBinaryOp "?"
1185−
1186−-- | Do any of these array strings exist as top-level keys?
1187−(.?|) :: Operator
1188− (null 'PGjsonb)
1189− (null ('PGvararray ('NotNull 'PGtext)))
1190− ('Null 'PGbool)
1191−infixl 9 .?|
1192−(.?|) = unsafeBinaryOp "?|"
1193−
1194−-- | Do all of these array strings exist as top-level keys?
1195−(.?&) :: Operator
1196− (null 'PGjsonb)
1197− (null ('PGvararray ('NotNull 'PGtext)))
1198− ('Null 'PGbool)
1199−infixl 9 .?&
1200−(.?&) = unsafeBinaryOp "?&"
1201−
1202−-- | Concatenate two jsonb values into a new jsonb value.
1203−instance Semigroup
1204− (Expression outer grp commons schemas params from (null 'PGjsonb)) where
1205− (<>) = unsafeBinaryOp "||"
1206−
1207−-- | Delete a key or keys from a JSON object, or remove an array element.
1208−--
1209−-- If the right operand is..
1210−--
1211−-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1212−-- are matched based on their key value.
1213−--
1214−-- @ text[] @: Delete multiple key/value pairs or string elements
1215−-- from left operand. Key/value pairs are matched based on their key value.
1216−--
1217−-- @ integer @: Delete the array element with specified index (Negative integers
1218−-- count from the end). Throws an error if top level container is not an array.
1219−(.-.)
1220− :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1221− => Operator (null 'PGjsonb) (null key) (null 'PGjsonb)
1222−infixl 6 .-.
1223−(.-.) = unsafeBinaryOp "-"
1224−
1225−-- | Delete the field or element with specified path (for JSON arrays, negative
1226−-- integers count from the end)
1227−(#-.) :: Operator (null 'PGjsonb) (null ('PGvararray ('NotNull 'PGtext))) (null 'PGjsonb)
1228−infixl 6 #-.
1229−(#-.) = unsafeBinaryOp "#-"
1230−
1231−{-----------------------------------------
1232−Table 9.45: JSON creation functions
1233−-----------------------------------------}
1234−
1235−-- | Literal binary JSON
1236−jsonbLit :: JSON.ToJSON x => x -> Expr (null 'PGjsonb)
1237−jsonbLit = cast jsonb . UnsafeExpression
1238− . singleQuotedUtf8 . toStrict . JSON.encode
1239−
1240−-- | Literal JSON
1241−jsonLit :: JSON.ToJSON x => x -> Expr (null 'PGjson)
1242−jsonLit = cast json . UnsafeExpression
1243− . singleQuotedUtf8 . toStrict . JSON.encode
1244−
1245−-- | Returns the value as json. Arrays and composites are converted
1246−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1247−-- type to json, the cast function will be used to perform the conversion;
1248−-- otherwise, a scalar value is produced. For any scalar type other than a
1249−-- number, a Boolean, or a null value, the text representation will be used, in
1250−-- such a fashion that it is a valid json value.
1251−toJson :: null ty :--> null 'PGjson
1252−toJson = unsafeFunction "to_json"
1253−
1254−-- | Returns the value as jsonb. Arrays and composites are converted
1255−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1256−-- type to json, the cast function will be used to perform the conversion;
1257−-- otherwise, a scalar value is produced. For any scalar type other than a
1258−-- number, a Boolean, or a null value, the text representation will be used, in
1259−-- such a fashion that it is a valid jsonb value.
1260−toJsonb :: null ty :--> null 'PGjsonb
1261−toJsonb = unsafeFunction "to_jsonb"
1262−
1263−-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1264−-- becomes a JSON array of arrays.
1265−arrayToJson :: null ('PGvararray ty) :--> null 'PGjson
1266−arrayToJson = unsafeFunction "array_to_json"
1267−
1268−-- | Returns the row as a JSON object.
1269−rowToJson :: null ('PGcomposite ty) :--> null 'PGjson
1270−rowToJson = unsafeFunction "row_to_json"
1271−
1272−-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1273−-- argument list.
1274−jsonBuildArray :: SListI tuple => FunctionHet tuple (null 'PGjson)
1275−jsonBuildArray = unsafeFunctionHet "json_build_array"
1276−
1277−-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1278−-- variadic argument list.
1279−jsonbBuildArray :: SListI tuple => FunctionHet tuple (null 'PGjsonb)
1280−jsonbBuildArray = unsafeFunctionHet "jsonb_build_array"
1281−
1282−class PGBuildObject tys where
1283−instance PGBuildObject '[]
1284−instance (PGBuildObject tys, key `In` PGJsonKey)
1285− => PGBuildObject ('NotNull key ': value ': tys)
1286−
1287−-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1288−-- argument list. The elements of the argument list must alternate between text
1289−-- and values.
1290−jsonBuildObject
1291− :: (SListI elems, PGBuildObject elems)
1292− => FunctionHet elems (null 'PGjson)
1293−jsonBuildObject = unsafeFunctionHet "json_build_object"
1294−
1295−-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1296−-- variadic argument list. The elements of the argument list must alternate
1297−-- between keys and values.
1298−jsonbBuildObject
1299− :: (SListI elems, PGBuildObject elems)
1300− => FunctionHet elems (null 'PGjsonb)
1301−jsonbBuildObject = unsafeFunctionHet "jsonb_build_object"
1302−
1303−-- | Builds a JSON object out of a text array.
1304−-- The array must have two dimensions
1305−-- such that each inner array has exactly two elements,
1306−-- which are taken as a key/value pair.
1307−jsonObject
1308− :: null ('PGfixarray '[n,2] ('NotNull 'PGtext))
1309− :--> null 'PGjson
1310−jsonObject = unsafeFunction "json_object"
1311−
1312−-- | Builds a binary JSON object out of a text array.
1313−-- The array must have two dimensions
1314−-- such that each inner array has exactly two elements,
1315−-- which are taken as a key/value pair.
1316−jsonbObject
1317− :: null ('PGfixarray '[n,2] ('NotNull 'PGtext))
1318− :--> null 'PGjsonb
1319−jsonbObject = unsafeFunction "jsonb_object"
1320−
1321−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1322−-- keys and one for values, that are zipped pairwise to create a JSON object.
1323−jsonZipObject :: FunctionHet
1324− '[ null ('PGvararray ('NotNull 'PGtext))
1325− , null ('PGvararray ('NotNull 'PGtext)) ]
1326− ( null 'PGjson )
1327−jsonZipObject = unsafeFunctionHet "json_object"
1328−
1329−-- | This is an alternate form of 'jsonbObject' that takes two arrays; one for
1330−-- keys and one for values, that are zipped pairwise to create a binary JSON
1331−-- object.
1332−jsonbZipObject :: FunctionHet
1333− '[ null ('PGvararray ('NotNull 'PGtext))
1334− , null ('PGvararray ('NotNull 'PGtext)) ]
1335− ( null 'PGjsonb )
1336−jsonbZipObject = unsafeFunctionHet "jsonb_object"
1337−
1338−{-----------------------------------------
1339−Table 9.46: JSON processing functions
1340−-----------------------------------------}
1341−
1342−-- | Returns the number of elements in the outermost JSON array.
1343−jsonArrayLength :: null 'PGjson :--> null 'PGint4
1344−jsonArrayLength = unsafeFunction "json_array_length"
1345−
1346−-- | Returns the number of elements in the outermost binary JSON array.
1347−jsonbArrayLength :: null 'PGjsonb :--> null 'PGint4
1348−jsonbArrayLength = unsafeFunction "jsonb_array_length"
1349−
1350−-- | Returns JSON value pointed to by the given path (equivalent to #>
1351−-- operator).
1352−jsonExtractPath
1353− :: SListI elems
1354− => Expression outer grp commons schemas params from (null 'PGjson)
1355− -> NP (Expression outer grp commons schemas params from) elems
1356− -> Expression outer grp commons schemas params from (null 'PGjsonb)
1357−jsonExtractPath x xs =
1358− unsafeFunctionHet "json_extract_path" (x :* xs)
1359−
1360−-- | Returns JSON value pointed to by the given path (equivalent to #>
1361−-- operator).
1362−jsonbExtractPath
1363− :: SListI elems
1364− => Expression outer grp commons schemas params from (null 'PGjsonb)
1365− -> NP (Expression outer grp commons schemas params from) elems
1366− -> Expression outer grp commons schemas params from (null 'PGjsonb)
1367−jsonbExtractPath x xs =
1368− unsafeFunctionHet "jsonb_extract_path" (x :* xs)
1369−
1370−-- | Returns JSON value pointed to by the given path (equivalent to #>
1371−-- operator), as text.
1372−jsonExtractPathAsText
1373− :: SListI elems
1374− => Expression outer grp commons schemas params from (null 'PGjson)
1375− -> NP (Expression outer grp commons schemas params from) elems
1376− -> Expression outer grp commons schemas params from (null 'PGjson)
1377−jsonExtractPathAsText x xs =
1378− unsafeFunctionHet "json_extract_path_text" (x :* xs)
1379−
1380−-- | Returns JSON value pointed to by the given path (equivalent to #>
1381−-- operator), as text.
1382−jsonbExtractPathAsText
1383− :: SListI elems
1384− => Expression outer grp commons schemas params from (null 'PGjsonb)
1385− -> NP (Expression outer grp commons schemas params from) elems
1386− -> Expression outer grp commons schemas params from (null 'PGjsonb)
1387−jsonbExtractPathAsText x xs =
1388− unsafeFunctionHet "jsonb_extract_path_text" (x :* xs)
1389−
1390−-- | Returns the type of the outermost JSON value as a text string. Possible
1391−-- types are object, array, string, number, boolean, and null.
1392−jsonTypeof :: null 'PGjson :--> null 'PGtext
1393−jsonTypeof = unsafeFunction "json_typeof"
1394−
1395−-- | Returns the type of the outermost binary JSON value as a text string.
1396−-- Possible types are object, array, string, number, boolean, and null.
1397−jsonbTypeof :: null 'PGjsonb :--> null 'PGtext
1398−jsonbTypeof = unsafeFunction "jsonb_typeof"
1399−
1400−-- | Returns its argument with all object fields that have null values omitted.
1401−-- Other null values are untouched.
1402−jsonStripNulls :: null 'PGjson :--> null 'PGjson
1403−jsonStripNulls = unsafeFunction "json_strip_nulls"
1404−
1405−-- | Returns its argument with all object fields that have null values omitted.
1406−-- Other null values are untouched.
1407−jsonbStripNulls :: null 'PGjsonb :--> null 'PGjsonb
1408−jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1409−
1410−-- | @ jsonbSet target path new_value create_missing @
1411−--
1412−-- Returns target with the section designated by path replaced by new_value,
1413−-- or with new_value added if create_missing is true ( default is true) and the
1414−-- item designated by path does not exist. As with the path orientated
1415−-- operators, negative integers that appear in path count from the end of JSON
1416−-- arrays.
1417−jsonbSet
1418− :: Expression outer grp commons schemas params from (null 'PGjsonb)
1419− -> Expression outer grp commons schemas params from (null ('PGvararray ('NotNull 'PGtext)))
1420− -> Expression outer grp commons schemas params from (null 'PGjsonb)
1421− -> Maybe (Expression outer grp commons schemas params from (null 'PGbool))
1422− -> Expression outer grp commons schemas params from (null 'PGjsonb)
1423−jsonbSet tgt path val createMissing = case createMissing of
1424− Just m -> unsafeFunctionHet "jsonb_set" (tgt :* path :* val :* m :* Nil)
1425− Nothing -> unsafeFunctionHet "jsonb_set" (tgt :* path :* val :* Nil)
1426−
1427−-- | @ jsonbInsert target path new_value insert_after @
1428−--
1429−-- Returns target with new_value inserted. If target section designated by
1430−-- path is in a JSONB array, new_value will be inserted before target or after
1431−-- if insert_after is true (default is false). If target section designated by
1432−-- path is in JSONB object, new_value will be inserted only if target does not
1433−-- exist. As with the path orientated operators, negative integers that appear
1434−-- in path count from the end of JSON arrays.
1435−jsonbInsert
1436− :: Expression outer grp commons schemas params from (null 'PGjsonb)
1437− -> Expression outer grp commons schemas params from (null ('PGvararray ('NotNull 'PGtext)))
1438− -> Expression outer grp commons schemas params from (null 'PGjsonb)
1439− -> Maybe (Expression outer grp commons schemas params from (null 'PGbool))
1440− -> Expression outer grp commons schemas params from (null 'PGjsonb)
1441−jsonbInsert tgt path val insertAfter = case insertAfter of
1442− Just i -> unsafeFunctionHet "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1443− Nothing -> unsafeFunctionHet "jsonb_insert" (tgt :* path :* val :* Nil)
1444−
1445−-- | Returns its argument as indented JSON text.
1446−jsonbPretty :: null 'PGjsonb :--> null 'PGtext
1447−jsonbPretty = unsafeFunction "jsonb_pretty"
1448−
1449−(@@) :: Operator (null 'PGtsvector) (null 'PGtsquery) ('Null 'PGbool)
1450−(@@) = unsafeBinaryOp "@@"
1451−
1452−(.&) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1453−(.&) = unsafeBinaryOp "&&"
1454−
1455−(.|) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1456−(.|) = unsafeBinaryOp "||"
1457−
1458−(.!) :: null 'PGtsquery :--> null 'PGtsquery
1459−(.!) = unsafeUnaryOpL "!!"
1460−
1461−(<->) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1462−(<->) = unsafeBinaryOp "<->"
1463−
1464−arrayToTSvector
1465− :: null ('PGvararray ('NotNull 'PGtext))
1466− :--> null 'PGtsvector
1467−arrayToTSvector = unsafeFunction "array_to_tsvector"
1468−
1469−tsvectorLength :: null 'PGtsvector :--> null 'PGint4
1470−tsvectorLength = unsafeFunction "length"
1471−
1472−numnode :: null 'PGtsquery :--> null 'PGint4
1473−numnode = unsafeFunction "numnode"
1474−
1475−plainToTSquery :: null 'PGtext :--> null 'PGtsquery
1476−plainToTSquery = unsafeFunction "plainto_tsquery"
1477−
1478−phraseToTSquery :: null 'PGtext :--> null 'PGtsquery
1479−phraseToTSquery = unsafeFunction "phraseto_tsquery"
1480−
1481−websearchToTSquery :: null 'PGtext :--> null 'PGtsquery
1482−websearchToTSquery = unsafeFunction "websearch_to_tsquery"
1483−
1484−queryTree :: null 'PGtsquery :--> null 'PGtext
1485−queryTree = unsafeFunction "query_tree"
1486−
1487−toTSquery :: null 'PGtext :--> null 'PGtsquery
1488−toTSquery = unsafeFunction "to_tsquery"
1489−
1490−toTSvector
1491− :: ty `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1492− => null ty :--> null 'PGtsquery
1493−toTSvector = unsafeFunction "to_tsvector"
1494−
1495−setWeight
1496− :: FunctionHet '[null 'PGtsvector, null ('PGchar 1)] (null 'PGtsvector)
1497−setWeight = unsafeFunctionHet "set_weight"
1498−
1499−litChar :: Char -> Expr (null ('PGchar 1))
1500−litChar chr = UnsafeExpression $
1501− "E\'" <> fromString (escape =<< [chr]) <> "\'"
1502−
1503−strip :: null 'PGtsvector :--> null 'PGtsvector
1504−strip = unsafeFunction "strip"
1505−
1506−jsonToTSvector :: FunctionHet '[null 'PGjson, null 'PGjson] (null 'PGtsvector)
1507−jsonToTSvector = unsafeFunctionHet "json_to_tsvector"
1508−
1509−jsonbToTSvector :: FunctionHet '[null 'PGjsonb, null 'PGjsonb] (null 'PGtsvector)
1510−jsonbToTSvector = unsafeFunctionHet "jsonb_to_tsvector"
1511−
1512−tsDelete :: FunctionHet
1513− '[null 'PGtsvector, null ('PGvararray ('NotNull 'PGtext))]
1514− (null 'PGtsvector)
1515−tsDelete = unsafeFunctionHet "ts_delete"
1516−
1517−tsFilter :: FunctionHet
1518− '[null 'PGtsvector, null ('PGvararray ('NotNull ('PGchar 1)))]
1519− (null 'PGtsvector)
1520−tsFilter = unsafeFunctionHet "ts_filter"
1521−
1522−tsHeadline
1523− :: document `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1524− => FunctionHet '[null document, null 'PGtsquery] (null 'PGtext)
1525−tsHeadline = unsafeFunctionHet "ts_headline"
1526−{-----------------------------------------
1527−aggregation
1528−-----------------------------------------}
1529−
1530−type AggrFun x y
1531− = forall outer bys commons schemas params from
1532− . Distinction (Expression outer 'Ungrouped commons schemas params from) x
1533− -- ^ input
1534− -> Expression outer ('Grouped bys) commons schemas params from y
1535− -- ^ output
1536−
1537−type AggrHet xs y
1538− = forall outer bys commons schemas params from
1539− . Distinction (NP (Expression outer 'Ungrouped commons schemas params from)) xs
1540− -- ^ inputs
1541− -> Expression outer ('Grouped bys) commons schemas params from y
1542− -- ^ output
1543−
1544−unsafeAggregateHet :: SOP.SListI xs => ByteString -> AggrHet xs y
1545−unsafeAggregateHet fun xs = UnsafeExpression $ mconcat
1546− [fun, "(", renderSQL xs, ")"]
1547−
1548−{- |
1549−`Aggregate` functions compute a single result from a set of input values.
1550−`Aggregate` functions can be used as `GroupedBy` `Expression`s as well
1551−as `WindowFunction`s.
1552−-}
1553−class Aggregate expr1 exprHet aggr
1554− | aggr -> expr1, aggr -> exprHet where
1555−
1556− -- | A special aggregation that does not require an input
1557− --
1558− -- >>> :{
1559− -- let
1560− -- expression :: Expression '[] ('Grouped bys) commons schemas params from ('NotNull 'PGint8)
1561− -- expression = countStar
1562− -- in printSQL expression
1563− -- :}
1564− -- count(*)
1565− countStar :: aggr ('NotNull 'PGint8)
1566−
1567− -- | >>> :{
1568− -- let
1569− -- expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: null ty]] ('NotNull 'PGint8)
1570− -- expression = count (All #col)
1571− -- in printSQL expression
1572− -- :}
1573− -- count(ALL "col")
1574− count
1575− :: expr1 ty
1576− -- ^ what to count
1577− -> aggr ('NotNull 'PGint8)
1578−
1579− -- | >>> :{
1580− -- let
1581− -- expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('NotNull 'PGnumeric)
1582− -- expression = sum_ (Distinct #col)
1583− -- in printSQL expression
1584− -- :}
1585− -- sum(DISTINCT "col")
1586− sum_
1587− :: ty `In` PGNum
1588− => expr1 (null ty)
1589− -> aggr ('NotNull ty)
1590−
1591− -- | input values, including nulls, concatenated into an array
1592− arrayAgg
1593− :: expr1 ty
1594− -> aggr ('Null ('PGvararray ty))
1595−
1596− -- | aggregates values as a JSON array
1597− jsonAgg
1598− :: expr1 ty
1599− -> aggr ('Null 'PGjson)
1600−
1601− -- | aggregates values as a JSON array
1602− jsonbAgg
1603− :: expr1 ty
1604− -> aggr ('Null 'PGjsonb)
1605−
1606− {- |
1607− the bitwise AND of all non-null input values, or null if none
1608− >>> :{
1609− let
1610− expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: null 'PGint4]] ('Null 'PGint4)
1611− expression = bitAnd (Distinct #col)
1612− in printSQL expression
1613− :}
1614− bit_and(DISTINCT "col")
1615− -}
1616− bitAnd
1617− :: int `In` PGIntegral
1618− => expr1 (null int)
1619− -- ^ what to aggregate
1620− -> aggr ('Null int)
1621−
1622− {- |
1623− the bitwise OR of all non-null input values, or null if none
1624−
1625− >>> :{
1626− let
1627− expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: null 'PGint4]] ('Null 'PGint4)
1628− expression = bitOr (All #col)
1629− in printSQL expression
1630− :}
1631− bit_or(ALL "col")
1632− -}
1633− bitOr
1634− :: int `In` PGIntegral
1635− => expr1 (null int)
1636− -- ^ what to aggregate
1637− -> aggr ('Null int)
1638−
1639− {- |
1640− true if all input values are true, otherwise false
1641−
1642− >>> :{
1643− let
1644− winFun :: WindowFunction '[] 'Ungrouped commons schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1645− winFun = boolAnd #col
1646− in printSQL winFun
1647− :}
1648− bool_and("col")
1649− -}
1650− boolAnd
1651− :: expr1 (null 'PGbool)
1652− -- ^ what to aggregate
1653− -> aggr ('Null 'PGbool)
1654−
1655− {- |
1656− true if at least one input value is true, otherwise false
1657−
1658− >>> :{
1659− let
1660− expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1661− expression = boolOr (All #col)
1662− in printSQL expression
1663− :}
1664− bool_or(ALL "col")
1665− -}
1666− boolOr
1667− :: expr1 (null 'PGbool)
1668− -- ^ what to aggregate
1669− -> aggr ('Null 'PGbool)
1670−
1671− {- |
1672− equivalent to `boolAnd`
1673−
1674− >>> :{
1675− let
1676− expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1677− expression = every (Distinct #col)
1678− in printSQL expression
1679− :}
1680− every(DISTINCT "col")
1681− -}
1682− every
1683− :: expr1 (null 'PGbool)
1684− -- ^ what to aggregate
1685− -> aggr ('Null 'PGbool)
1686−
1687− {- |maximum value of expression across all input values-}
1688− max_
1689− :: expr1 (null ty)
1690− -- ^ what to maximize
1691− -> aggr ('Null ty)
1692−
1693− -- | minimum value of expression across all input values
1694− min_
1695− :: expr1 (null ty)
1696− -- ^ what to minimize
1697− -> aggr ('Null ty)
1698−
1699− -- | the average (arithmetic mean) of all input values
1700− avg
1701− :: expr1 (null ty)
1702− -- ^ what to average
1703− -> aggr ('Null (PGAvg ty))
1704−
1705− {- | correlation coefficient
1706− >>> :{
1707− let
1708− expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1709− expression = corr (All (#y *: #x))
1710− in printSQL expression
1711− :}
1712− corr(ALL "y", "x")
1713− -}
1714− corr
1715− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1716− -> aggr ('Null 'PGfloat8)
1717−
1718− {- | population covariance
1719− >>> :{
1720− let
1721− expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1722− expression = covarPop (All (#y *: #x))
1723− in printSQL expression
1724− :}
1725− covar_pop(ALL "y", "x")
1726− -}
1727− covarPop
1728− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1729− -> aggr ('Null 'PGfloat8)
1730−
1731− {- | sample covariance
1732− >>> :{
1733− let
1734− winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1735− winFun = covarSamp (#y *: #x)
1736− in printSQL winFun
1737− :}
1738− covar_samp("y", "x")
1739− -}
1740− covarSamp
1741− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1742− -> aggr ('Null 'PGfloat8)
1743−
1744− {- | average of the independent variable (sum(X)/N)
1745− >>> :{
1746− let
1747− expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1748− expression = regrAvgX (All (#y *: #x))
1749− in printSQL expression
1750− :}
1751− regr_avgx(ALL "y", "x")
1752− -}
1753− regrAvgX
1754− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1755− -> aggr ('Null 'PGfloat8)
1756−
1757− {- | average of the dependent variable (sum(Y)/N)
1758− >>> :{
1759− let
1760− winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1761− winFun = regrAvgY (#y *: #x)
1762− in printSQL winFun
1763− :}
1764− regr_avgy("y", "x")
1765− -}
1766− regrAvgY
1767− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1768− -> aggr ('Null 'PGfloat8)
1769−
1770− {- | number of input rows in which both expressions are nonnull
1771− >>> :{
1772− let
1773− winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGint8)
1774− winFun = regrCount (#y *: #x)
1775− in printSQL winFun
1776− :}
1777− regr_count("y", "x")
1778− -}
1779− regrCount
1780− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1781− -> aggr ('Null 'PGint8)
1782−
1783− {- | y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs
1784− >>> :{
1785− let
1786− expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1787− expression = regrIntercept (All (#y *: #x))
1788− in printSQL expression
1789− :}
1790− regr_intercept(ALL "y", "x")
1791− -}
1792− regrIntercept
1793− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1794− -> aggr ('Null 'PGfloat8)
1795−
1796− -- | @regr_r2(Y, X)@, square of the correlation coefficient
1797− regrR2
1798− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1799− -> aggr ('Null 'PGfloat8)
1800−
1801− -- | @regr_slope(Y, X)@, slope of the least-squares-fit linear equation
1802− -- determined by the (X, Y) pairs
1803− regrSlope
1804− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1805− -> aggr ('Null 'PGfloat8)
1806−
1807− -- | @regr_sxx(Y, X)@, sum(X^2) - sum(X)^2/N
1808− -- (“sum of squares” of the independent variable)
1809− regrSxx
1810− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1811− -> aggr ('Null 'PGfloat8)
1812−
1813− -- | @regr_sxy(Y, X)@, sum(X*Y) - sum(X) * sum(Y)/N
1814− -- (“sum of products” of independent times dependent variable)
1815− regrSxy
1816− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1817− -> aggr ('Null 'PGfloat8)
1818−
1819− -- | @regr_syy(Y, X)@, sum(Y^2) - sum(Y)^2/N
1820− -- (“sum of squares” of the dependent variable)
1821− regrSyy
1822− :: exprHet '[null 'PGfloat8, null 'PGfloat8]
1823− -> aggr ('Null 'PGfloat8)
1824−
1825− -- | historical alias for `stddevSamp`
1826− stddev
1827− :: expr1 (null ty)
1828− -> aggr ('Null (PGAvg ty))
1829−
1830− -- | population standard deviation of the input values
1831− stddevPop
1832− :: expr1 (null ty)
1833− -> aggr ('Null (PGAvg ty))
1834−
1835− -- | sample standard deviation of the input values
1836− stddevSamp
1837− :: expr1 (null ty)
1838− -> aggr ('Null (PGAvg ty))
1839−
1840− -- | historical alias for `varSamp`
1841− variance
1842− :: expr1 (null ty)
1843− -> aggr ('Null (PGAvg ty))
1844−
1845− -- | population variance of the input values
1846− -- (square of the population standard deviation)
1847− varPop
1848− :: expr1 (null ty)
1849− -> aggr ('Null (PGAvg ty))
1850−
1851− -- | sample variance of the input values
1852− -- (square of the sample standard deviation)
1853− varSamp
1854− :: expr1 (null ty)
1855− -> aggr ('Null (PGAvg ty))
1856−
1857−{- |
1858−`Distinction`s are used for the input of `Aggregate` `Expression`s.
1859−`All` invokes the aggregate once for each input row.
1860−`Distinct` invokes the aggregate once for each distinct value of the expression
1861−(or distinct set of values, for multiple expressions) found in the input
1862−-}
1863−data Distinction (expr :: kind -> Type) (ty :: kind)
1864− = All (expr ty)
1865− | Distinct (expr ty)
1866− deriving (GHC.Generic,Show,Eq,Ord)
1867−instance NFData (Distinction (Expression outer grp commons schemas params from) ty)
1868−instance RenderSQL (Distinction (Expression outer grp commons schemas params from) ty) where
1869− renderSQL = \case
1870− All x -> "ALL" <+> renderSQL x
1871− Distinct x -> "DISTINCT" <+> renderSQL x
1872−instance SOP.SListI tys => RenderSQL
1873− (Distinction (NP (Expression outer grp commons schemas params from)) tys) where
1874− renderSQL = \case
1875− All xs -> "ALL" <+> renderCommaSeparated renderSQL xs
1876− Distinct xs -> "DISTINCT" <+> renderCommaSeparated renderSQL xs
1877−
1878−instance Aggregate
1879− (Distinction (Expression outer 'Ungrouped commons schemas params from))
1880− (Distinction (NP (Expression outer 'Ungrouped commons schemas params from)))
1881− (Expression outer ('Grouped bys) commons schemas params from) where
1882− countStar = UnsafeExpression "count(*)"
1883− count = unsafeAggregate1 "count"
1884− sum_ = unsafeAggregate1 "sum"
1885− arrayAgg = unsafeAggregate1 "array_agg"
1886− jsonAgg = unsafeAggregate1 "json_agg"
1887− jsonbAgg = unsafeAggregate1 "jsonb_agg"
1888− bitAnd = unsafeAggregate1 "bit_and"
1889− bitOr = unsafeAggregate1 "bit_or"
1890− boolAnd = unsafeAggregate1 "bool_and"
1891− boolOr = unsafeAggregate1 "bool_or"
1892− every = unsafeAggregate1 "every"
1893− max_ = unsafeAggregate1 "max"
1894− min_ = unsafeAggregate1 "min"
1895− avg = unsafeAggregate1 "avg"
1896− corr = unsafeAggregateHet "corr"
1897− covarPop = unsafeAggregateHet "covar_pop"
1898− covarSamp = unsafeAggregateHet "covar_samp"
1899− regrAvgX = unsafeAggregateHet "regr_avgx"
1900− regrAvgY = unsafeAggregateHet "regr_avgy"
1901− regrCount = unsafeAggregateHet "regr_count"
1902− regrIntercept = unsafeAggregateHet "regr_intercept"
1903− regrR2 = unsafeAggregateHet "regr_r2"
1904− regrSlope = unsafeAggregateHet "regr_slope"
1905− regrSxx = unsafeAggregateHet "regr_sxx"
1906− regrSxy = unsafeAggregateHet "regr_sxy"
1907− regrSyy = unsafeAggregateHet "regr_syy"
1908− stddev = unsafeAggregate1 "stddev"
1909− stddevPop = unsafeAggregate1 "stddev_pop"
1910− stddevSamp = unsafeAggregate1 "stddev_samp"
1911− variance = unsafeAggregate1 "variance"
1912− varPop = unsafeAggregate1 "var_pop"
1913− varSamp = unsafeAggregate1 "var_samp"
1914−instance Aggregate
1915− (Expression outer grp commons schemas params from)
1916− (NP (Expression outer grp commons schemas params from))
1917− (WindowFunction outer grp commons schemas params from) where
1918− countStar = UnsafeWindowFunction "count(*)"
1919− count = unsafeWindowFunction1 "count"
1920− sum_ = unsafeWindowFunction1 "sum"
1921− arrayAgg = unsafeWindowFunction1 "array_agg"
1922− jsonAgg = unsafeWindowFunction1 "json_agg"
1923− jsonbAgg = unsafeWindowFunction1 "jsonb_agg"
1924− bitAnd = unsafeWindowFunction1 "bit_and"
1925− bitOr = unsafeWindowFunction1 "bit_or"
1926− boolAnd = unsafeWindowFunction1 "bool_and"
1927− boolOr = unsafeWindowFunction1 "bool_or"
1928− every = unsafeWindowFunction1 "every"
1929− max_ = unsafeWindowFunction1 "max"
1930− min_ = unsafeWindowFunction1 "min"
1931− avg = unsafeWindowFunction1 "avg"
1932− corr = unsafeWindowFunctionHet "corr"
1933− covarPop = unsafeWindowFunctionHet "covar_pop"
1934− covarSamp = unsafeWindowFunctionHet "covar_samp"
1935− regrAvgX = unsafeWindowFunctionHet "regr_avgx"
1936− regrAvgY = unsafeWindowFunctionHet "regr_avgy"
1937− regrCount = unsafeWindowFunctionHet "regr_count"
1938− regrIntercept = unsafeWindowFunctionHet "regr_intercept"
1939− regrR2 = unsafeWindowFunctionHet "regr_r2"
1940− regrSlope = unsafeWindowFunctionHet "regr_slope"
1941− regrSxx = unsafeWindowFunctionHet "regr_sxx"
1942− regrSxy = unsafeWindowFunctionHet "regr_sxy"
1943− regrSyy = unsafeWindowFunctionHet "regr_syy"
1944− stddev = unsafeWindowFunction1 "stddev"
1945− stddevPop = unsafeWindowFunction1 "stddev_pop"
1946− stddevSamp = unsafeWindowFunction1 "stddev_samp"
1947− variance = unsafeWindowFunction1 "variance"
1948− varPop = unsafeWindowFunction1 "var_pop"
1949− varSamp = unsafeWindowFunction1 "var_samp"
1950−
1951−-- | escape hatch to define aggregate functions
1952−unsafeAggregate1
1953− :: ByteString -- ^ aggregate function
1954− -> AggrFun xty yty
1955−unsafeAggregate1 fun x = UnsafeExpression $ mconcat
1956− [fun, "(", renderSQL x, ")"]
1957−
1958−-- | A type family that calculates `PGAvg` type of a `PGType`.
1959−type family PGAvg ty where
1960− PGAvg 'PGint2 = 'PGnumeric
1961− PGAvg 'PGint4 = 'PGnumeric
1962− PGAvg 'PGint8 = 'PGnumeric
1963− PGAvg 'PGnumeric = 'PGnumeric
1964− PGAvg 'PGfloat4 = 'PGfloat8
1965− PGAvg 'PGfloat8 = 'PGfloat8
1966− PGAvg 'PGinterval = 'PGinterval
1967− PGAvg pg = TypeError
1968− ('Text "Squeal type error: No average for " ':<>: 'ShowType pg)
1969−
1970−{-----------------------------------------
1971−type expressions
1972−-----------------------------------------}
1973−
1974−-- | `TypeExpression`s are used in `cast`s and
1975−-- `Squeal.PostgreSQL.Definition.createTable` commands.
1976−newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
1977− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
1978− deriving (GHC.Generic,Show,Eq,Ord,NFData)
1979−instance RenderSQL (TypeExpression schemas ty) where
1980− renderSQL = renderTypeExpression
1981−
1982−-- | The enum or composite type in a `Typedef` can be expressed by its alias.
1983−typedef
1984− :: (Has sch schemas schema, Has td schema ('Typedef ty))
1985− => QualifiedAlias sch td
1986− -> TypeExpression schemas (null ty)
1987−typedef = UnsafeTypeExpression . renderSQL
1988−
1989−-- | The composite type corresponding to a `Table` definition can be expressed
1990−-- by its alias.
1991−typetable
1992− :: (Has sch schemas schema, Has tab schema ('Table table))
1993− => QualifiedAlias sch tab
1994− -> TypeExpression schemas (null ('PGcomposite (TableToRow table)))
1995−typetable = UnsafeTypeExpression . renderSQL
1996−
1997−-- | The composite type corresponding to a `View` definition can be expressed
1998−-- by its alias.
1999−typeview
2000− :: (Has sch schemas schema, Has vw schema ('View view))
2001− => QualifiedAlias sch vw
2002− -> TypeExpression schemas (null ('PGcomposite view))
2003−typeview = UnsafeTypeExpression . renderSQL
2004−
2005−-- | logical Boolean (true/false)
2006−bool :: TypeExpression schemas (null 'PGbool)
2007−bool = UnsafeTypeExpression "bool"
2008−-- | signed two-byte integer
2009−int2, smallint :: TypeExpression schemas (null 'PGint2)
2010−int2 = UnsafeTypeExpression "int2"
2011−smallint = UnsafeTypeExpression "smallint"
2012−-- | signed four-byte integer
2013−int4, int, integer :: TypeExpression schemas (null 'PGint4)
2014−int4 = UnsafeTypeExpression "int4"
2015−int = UnsafeTypeExpression "int"
2016−integer = UnsafeTypeExpression "integer"
2017−-- | signed eight-byte integer
2018−int8, bigint :: TypeExpression schemas (null 'PGint8)
2019−int8 = UnsafeTypeExpression "int8"
2020−bigint = UnsafeTypeExpression "bigint"
2021−-- | arbitrary precision numeric type
2022−numeric :: TypeExpression schemas (null 'PGnumeric)
2023−numeric = UnsafeTypeExpression "numeric"
2024−-- | single precision floating-point number (4 bytes)
2025−float4, real :: TypeExpression schemas (null 'PGfloat4)
2026−float4 = UnsafeTypeExpression "float4"
2027−real = UnsafeTypeExpression "real"
2028−-- | double precision floating-point number (8 bytes)
2029−float8, doublePrecision :: TypeExpression schemas (null 'PGfloat8)
2030−float8 = UnsafeTypeExpression "float8"
2031−doublePrecision = UnsafeTypeExpression "double precision"
2032−-- | currency amount
2033−money :: TypeExpression schema (null 'PGmoney)
2034−money = UnsafeTypeExpression "money"
2035−-- | variable-length character string
2036−text :: TypeExpression schemas (null 'PGtext)
2037−text = UnsafeTypeExpression "text"
2038−-- | fixed-length character string
2039−char, character
2040− :: forall n schemas null. (KnownNat n, 1 <= n)
2041− => TypeExpression schemas (null ('PGchar n))
2042−char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
2043−character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
2044−-- | variable-length character string
2045−varchar, characterVarying
2046− :: forall n schemas null. (KnownNat n, 1 <= n)
2047− => TypeExpression schemas (null ('PGvarchar n))
2048−varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
2049−characterVarying = UnsafeTypeExpression $
2050− "character varying(" <> renderNat @n <> ")"
2051−-- | binary data ("byte array")
2052−bytea :: TypeExpression schemas (null 'PGbytea)
2053−bytea = UnsafeTypeExpression "bytea"
2054−-- | date and time (no time zone)
2055−timestamp :: TypeExpression schemas (null 'PGtimestamp)
2056−timestamp = UnsafeTypeExpression "timestamp"
2057−-- | date and time, including time zone
2058−timestampWithTimeZone :: TypeExpression schemas (null 'PGtimestamptz)
2059−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
2060−-- | calendar date (year, month, day)
2061−date :: TypeExpression schemas (null 'PGdate)
2062−date = UnsafeTypeExpression "date"
2063−-- | time of day (no time zone)
2064−time :: TypeExpression schemas (null 'PGtime)
2065−time = UnsafeTypeExpression "time"
2066−-- | time of day, including time zone
2067−timeWithTimeZone :: TypeExpression schemas (null 'PGtimetz)
2068−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
2069−-- | time span
2070−interval :: TypeExpression schemas (null 'PGinterval)
2071−interval = UnsafeTypeExpression "interval"
2072−-- | universally unique identifier
2073−uuid :: TypeExpression schemas (null 'PGuuid)
2074−uuid = UnsafeTypeExpression "uuid"
2075−-- | IPv4 or IPv6 host address
2076−inet :: TypeExpression schemas (null 'PGinet)
2077−inet = UnsafeTypeExpression "inet"
2078−-- | textual JSON data
2079−json :: TypeExpression schemas (null 'PGjson)
2080−json = UnsafeTypeExpression "json"
2081−-- | binary JSON data, decomposed
2082−jsonb :: TypeExpression schemas (null 'PGjsonb)
2083−jsonb = UnsafeTypeExpression "jsonb"
2084−-- | variable length array
2085−vararray
2086− :: TypeExpression schemas pg
2087− -> TypeExpression schemas (null ('PGvararray pg))
2088−vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
2089−-- | fixed length array
2090−--
2091−-- >>> renderSQL (fixarray @'[2] json)
2092−-- "json[2]"
2093−fixarray
2094− :: forall dims schemas null pg. SOP.All KnownNat dims
2095− => TypeExpression schemas pg
2096− -> TypeExpression schemas (null ('PGfixarray dims pg))
2097−fixarray ty = UnsafeTypeExpression $
2098− renderSQL ty <> renderDims @dims
2099− where
2100− renderDims :: forall ns. SOP.All KnownNat ns => ByteString
2101− renderDims =
2102− ("[" <>)
2103− . (<> "]")
2104− . ByteString.intercalate "]["
2105− . hcollapse
2106− $ hcmap (SOP.Proxy @KnownNat)
2107− (K . fromString . show . natVal)
2108− (hpure SOP.Proxy :: NP SOP.Proxy ns)
2109−tsvector :: TypeExpression schemas (null 'PGtsvector)
2110−tsvector = UnsafeTypeExpression "tsvector"
2111−tsquery :: TypeExpression schemas (null 'PGtsquery)
2112−tsquery = UnsafeTypeExpression "tsquery"
2113−
2114−-- | `pgtype` is a demoted version of a `PGType`
2115−class PGTyped schemas (ty :: NullityType) where
2116− pgtype :: TypeExpression schemas ty
2117−instance PGTyped schemas (null 'PGbool) where pgtype = bool
2118−instance PGTyped schemas (null 'PGint2) where pgtype = int2
2119−instance PGTyped schemas (null 'PGint4) where pgtype = int4
2120−instance PGTyped schemas (null 'PGint8) where pgtype = int8
2121−instance PGTyped schemas (null 'PGnumeric) where pgtype = numeric
2122−instance PGTyped schemas (null 'PGfloat4) where pgtype = float4
2123−instance PGTyped schemas (null 'PGfloat8) where pgtype = float8
2124−instance PGTyped schemas (null 'PGmoney) where pgtype = money
2125−instance PGTyped schemas (null 'PGtext) where pgtype = text
2126−instance (KnownNat n, 1 <= n)
2127− => PGTyped schemas (null ('PGchar n)) where pgtype = char @n
2128−instance (KnownNat n, 1 <= n)
2129− => PGTyped schemas (null ('PGvarchar n)) where pgtype = varchar @n
2130−instance PGTyped schemas (null 'PGbytea) where pgtype = bytea
2131−instance PGTyped schemas (null 'PGtimestamp) where pgtype = timestamp
2132−instance PGTyped schemas (null 'PGtimestamptz) where pgtype = timestampWithTimeZone
2133−instance PGTyped schemas (null 'PGdate) where pgtype = date
2134−instance PGTyped schemas (null 'PGtime) where pgtype = time
2135−instance PGTyped schemas (null 'PGtimetz) where pgtype = timeWithTimeZone
2136−instance PGTyped schemas (null 'PGinterval) where pgtype = interval
2137−instance PGTyped schemas (null 'PGuuid) where pgtype = uuid
2138−instance PGTyped schemas (null 'PGjson) where pgtype = json
2139−instance PGTyped schemas (null 'PGjsonb) where pgtype = jsonb
2140−instance PGTyped schemas ty
2141− => PGTyped schemas (null ('PGvararray ty)) where
2142− pgtype = vararray (pgtype @schemas @ty)
2143−instance (SOP.All KnownNat dims, PGTyped schemas ty)
2144− => PGTyped schemas (null ('PGfixarray dims ty)) where
2145− pgtype = fixarray @dims (pgtype @schemas @ty)
2146−instance PGTyped schemas (null 'PGtsvector) where pgtype = tsvector
2147−instance PGTyped schemas (null 'PGtsquery) where pgtype = tsquery
2148−
2149−{-----------------------------------------
2150−Sorting
2151−-----------------------------------------}
2152−
2153−-- | `SortExpression`s are used by `orderBy` to optionally sort the results
2154−-- of a `Squeal.PostgreSQL.Query.Query`. `Asc` or `Desc`
2155−-- set the sort direction of a `NotNull` result
2156−-- column to ascending or descending. Ascending order puts smaller values
2157−-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
2158−-- descending order is determined with the `.>` operator. `AscNullsFirst`,
2159−-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
2160−-- determine whether nulls appear before or after non-null values in the sort
2161−-- ordering of a `Null` result column.
2162−data SortExpression outer grp commons schemas params from where
2163− Asc
2164− :: Expression outer grp commons schemas params from ('NotNull ty)
2165− -> SortExpression outer grp commons schemas params from
2166− Desc
2167− :: Expression outer grp commons schemas params from ('NotNull ty)
2168− -> SortExpression outer grp commons schemas params from
2169− AscNullsFirst
2170− :: Expression outer grp commons schemas params from ('Null ty)
2171− -> SortExpression outer grp commons schemas params from
2172− AscNullsLast
2173− :: Expression outer grp commons schemas params from ('Null ty)
2174− -> SortExpression outer grp commons schemas params from
2175− DescNullsFirst
2176− :: Expression outer grp commons schemas params from ('Null ty)
2177− -> SortExpression outer grp commons schemas params from
2178− DescNullsLast
2179− :: Expression outer grp commons schemas params from ('Null ty)
2180− -> SortExpression outer grp commons schemas params from
2181−deriving instance Show (SortExpression outer grp commons schemas params from)
2182−
2183−{- |
2184−The `orderBy` clause causes the result rows of a `Squeal.PostgreSQL.Query.TableExpression`
2185−to be sorted according to the specified `SortExpression`(s).
2186−If two rows are equal according to the leftmost expression,
2187−they are compared according to the next expression and so on.
2188−If they are equal according to all specified expressions,
2189−they are returned in an implementation-dependent order.
2190−
2191−You can also control the order in which rows are processed by window functions
2192−using `orderBy` within `Squeal.PostgreSQL.Query.Over`.
2193−-}
2194−class OrderBy expr where
2195− orderBy
2196− :: [SortExpression outer grp commons schemas params from]
2197− -> expr outer grp commons schemas params from
2198− -> expr outer grp commons schemas params from
2199−
2200−-- | Render a `SortExpression`.
2201−instance RenderSQL (SortExpression outer grp commons schemas params from) where
2202− renderSQL = \case
2203− Asc expression -> renderSQL expression <+> "ASC"
2204− Desc expression -> renderSQL expression <+> "DESC"
2205− AscNullsFirst expression -> renderSQL expression
2206− <+> "ASC NULLS FIRST"
2207− DescNullsFirst expression -> renderSQL expression
2208− <+> "DESC NULLS FIRST"
2209− AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
2210− DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
2211−
2212−-- | A `WindowDefinition` is a set of table rows that are somehow related
2213−-- to the current row
2214−data WindowDefinition outer grp commons schemas params from where
2215− WindowDefinition
2216− :: SListI bys
2217− => NP (Expression outer grp commons schemas params from) bys
2218− -> [SortExpression outer grp commons schemas params from]
2219− -> WindowDefinition outer grp commons schemas params from
2220−
2221−instance OrderBy WindowDefinition where
2222− orderBy sortsR (WindowDefinition parts sortsL)
2223− = WindowDefinition parts (sortsL ++ sortsR)
2224−
2225−instance RenderSQL (WindowDefinition outer commons schemas from grp params) where
2226− renderSQL (WindowDefinition part ord) =
2227− renderPartitionByClause part <> renderOrderByClause ord
2228− where
2229− renderPartitionByClause = \case
2230− Nil -> ""
2231− parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
2232− renderOrderByClause = \case
2233− [] -> ""
2234− srts -> " ORDER" <+> "BY"
2235− <+> commaSeparated (renderSQL <$> srts)
2236−
2237−{- |
2238−The `partitionBy` clause within `Squeal.PostgreSQL.Query.Over` divides the rows into groups,
2239−or partitions, that share the same values of the `partitionBy` `Expression`(s).
2240−For each row, the window function is computed across the rows that fall into
2241−the same partition as the current row.
2242−-}
2243−partitionBy
2244− :: SListI bys
2245− => NP (Expression outer grp commons schemas params from) bys
2246− -> WindowDefinition outer grp commons schemas params from
2247−partitionBy bys = WindowDefinition bys []
2248−
2249−{- |
2250−A window function performs a calculation across a set of table rows
2251−that are somehow related to the current row. This is comparable to the type
2252−of calculation that can be done with an aggregate function.
2253−However, window functions do not cause rows to become grouped into a single
2254−output row like non-window aggregate calls would.
2255−Instead, the rows retain their separate identities.
2256−Behind the scenes, the window function is able to access more than
2257−just the current row of the query result.
2258−-}
2259−newtype WindowFunction
2260− (outer :: FromType)
2261− (grp :: Grouping)
2262− (commons :: FromType)
2263− (schemas :: SchemasType)
2264− (params :: [NullityType])
2265− (from :: FromType)
2266− (ty :: NullityType)
2267− = UnsafeWindowFunction { renderWindowFunction :: ByteString }
2268− deriving (GHC.Generic,Show,Eq,Ord,NFData)
2269−
2270−instance RenderSQL (WindowFunction outer grp commons schemas params from ty) where
2271− renderSQL = renderWindowFunction
2272−
2273−type WinFun0 x
2274− = forall outer grp commons schemas params from
2275− . WindowFunction outer grp commons schemas params from x
2276− -- ^ cannot reference aliases
2277−
2278−type WinFun1 x y
2279− = forall outer grp commons schemas params from
2280− . Expression outer grp commons schemas params from x
2281− -- ^ input
2282− -> WindowFunction outer grp commons schemas params from y
2283− -- ^ output
2284−
2285−type WinFunHet xs y
2286− = forall outer grp commons schemas params from
2287− . NP (Expression outer grp commons schemas params from) xs
2288− -- ^ inputs
2289− -> WindowFunction outer grp commons schemas params from y
2290− -- ^ output
2291−
2292−unsafeWindowFunction1 :: ByteString -> WinFun1 x y
2293−unsafeWindowFunction1 fun x
2294− = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x)
2295−
2296−unsafeWindowFunctionHet :: SOP.SListI xs => ByteString -> WinFunHet xs y
2297−unsafeWindowFunctionHet fun xs = UnsafeWindowFunction $ fun <>
2298− parenthesized (renderCommaSeparated renderSQL xs)
2299−
2300−{- | rank of the current row with gaps; same as `rowNumber` of its first peer
2301−>>> printSQL rank
2302−rank()
2303−-}
2304−rank :: WinFun0 ('NotNull 'PGint8)
2305−rank = UnsafeWindowFunction "rank()"
2306−
2307−{- | number of the current row within its partition, counting from 1
2308−>>> printSQL rowNumber
2309−row_number()
2310−-}
2311−rowNumber :: WinFun0 ('NotNull 'PGint8)
2312−rowNumber = UnsafeWindowFunction "row_number()"
2313−
2314−{- | rank of the current row without gaps; this function counts peer groups
2315−>>> printSQL denseRank
2316−dense_rank()
2317−-}
2318−denseRank :: WinFun0 ('NotNull 'PGint8)
2319−denseRank = UnsafeWindowFunction "dense_rank()"
2320−
2321−{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
2322−>>> printSQL percentRank
2323−percent_rank()
2324−-}
2325−percentRank :: WinFun0 ('NotNull 'PGfloat8)
2326−percentRank = UnsafeWindowFunction "percent_rank()"
2327−
2328−{- | cumulative distribution: (number of partition rows
2329−preceding or peer with current row) / total partition rows
2330−>>> printSQL cumeDist
2331−cume_dist()
2332−-}
2333−cumeDist :: WinFun0 ('NotNull 'PGfloat8)
2334−cumeDist = UnsafeWindowFunction "cume_dist()"
2335−
2336−{- | integer ranging from 1 to the argument value,
2337−dividing the partition as equally as possible
2338−-}
2339−ntile :: WinFun1 ('NotNull 'PGint4) ('NotNull 'PGint4)
2340−ntile = unsafeWindowFunction1 "ntile"
2341−
2342−{- | returns value evaluated at the row that is offset rows before the current
2343−row within the partition; if there is no such row, instead return default
2344−(which must be of the same type as value). Both offset and default are
2345−evaluated with respect to the current row.
2346−-}
2347−lag :: WinFunHet '[ty, 'NotNull 'PGint4, ty] ty
2348−lag = unsafeWindowFunctionHet "lag"
2349−
2350−{- | returns value evaluated at the row that is offset rows after the current
2351−row within the partition; if there is no such row, instead return default
2352−(which must be of the same type as value). Both offset and default are
2353−evaluated with respect to the current row.
2354−-}
2355−lead :: WinFunHet '[ty, 'NotNull 'PGint4, ty] ty
2356−lead = unsafeWindowFunctionHet "lag"
2357−
2358−{- | returns value evaluated at the row that is the
2359−first row of the window frame
2360−-}
2361−firstValue :: WinFun1 ty ty
2362−firstValue = unsafeWindowFunction1 "first_value"
2363−
2364−{- | returns value evaluated at the row that is the
2365−last row of the window frame
2366−-}
2367−lastValue :: WinFun1 ty ty
2368−lastValue = unsafeWindowFunction1 "last_value"
2369−
2370−{- | returns value evaluated at the row that is the nth
2371−row of the window frame (counting from 1); null if no such row
2372−-}
2373−nthValue :: WinFunHet '[null ty, 'NotNull 'PGint4] ('Null ty)
2374−nthValue = unsafeWindowFunctionHet "nth_value"
2375−
2376−{-|
2377−Create date from year, month and day fields
2378−
2379−>>> printSQL (makeDate (1984 :* 7 *: 3))
2380−make_date(1984, 7, 3)
2381−-}
2382−makeDate :: FunctionHet
2383− '[ null 'PGint4, null 'PGint4, null 'PGint4 ]
2384− ( null 'PGdate )
2385−makeDate = unsafeFunctionHet "make_date"
2386−
2387−{-|
2388−Create time from hour, minute and seconds fields
2389−
2390−>>> printSQL (makeTime (8 :* 15 *: 23.5))
2391−make_time(8, 15, 23.5)
2392−-}
2393−makeTime :: FunctionHet
2394− '[ null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2395− ( null 'PGtime )
2396−makeTime = unsafeFunctionHet "make_time"
2397−
2398−{-|
2399−Create timestamp from year, month, day, hour, minute and seconds fields
2400−
2401−>>> printSQL (makeTimestamp (2013 :* 7 :* 15 :* 8 :* 15 *: 23.5))
2402−make_timestamp(2013, 7, 15, 8, 15, 23.5)
2403−-}
2404−makeTimestamp :: FunctionHet
2405− '[ null 'PGint4, null 'PGint4, null 'PGint4
2406− , null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2407− ( null 'PGtimestamp )
2408−makeTimestamp = unsafeFunctionHet "make_timestamp"
2409−
2410−{-|
2411−Create timestamp with time zone from
2412−year, month, day, hour, minute and seconds fields;
2413−the current time zone is used
2414−
2415−>>> printSQL (makeTimestamptz (2013 :* 7 :* 15 :* 8 :* 15 *: 23.5))
2416−make_timestamptz(2013, 7, 15, 8, 15, 23.5)
2417−-}
2418−makeTimestamptz :: FunctionHet
2419− '[ null 'PGint4, null 'PGint4, null 'PGint4
2420− , null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2421− ( null 'PGtimestamptz )
2422−makeTimestamptz = unsafeFunctionHet "make_timestamptz"
2423−
2424−{-|
2425−Affine space operations on time types.
2426−-}
2427−class TimeOp time diff | time -> diff where
2428− {-|
2429− >>> printSQL (makeDate (1984 :* 7 *: 3) !+ 365)
2430− (make_date(1984, 7, 3) + 365)
2431− -}
2432− (!+) :: Operator (null time) (null diff) (null time)
2433− (!+) = unsafeBinaryOp "+"
2434− {-|
2435− >>> printSQL (365 +! makeDate (1984 :* 7 *: 3))
2436− (365 + make_date(1984, 7, 3))
2437− -}
2438− (+!) :: Operator (null diff) (null time) (null time)
2439− (+!) = unsafeBinaryOp "+"
2440− {-|
2441− >>> printSQL (makeDate (1984 :* 7 *: 3) !- 365)
2442− (make_date(1984, 7, 3) - 365)
2443− -}
2444− (!-) :: Operator (null time) (null diff) (null time)
2445− (!-) = unsafeBinaryOp "-"
2446− {-|
2447− >>> printSQL (makeDate (1984 :* 7 *: 3) !-! currentDate)
2448− (make_date(1984, 7, 3) - CURRENT_DATE)
2449− -}
2450− (!-!) :: Operator (null time) (null time) (null diff)
2451− (!-!) = unsafeBinaryOp "-"
2452−instance TimeOp 'PGtimestamp 'PGinterval
2453−instance TimeOp 'PGtimestamptz 'PGinterval
2454−instance TimeOp 'PGtime 'PGinterval
2455−instance TimeOp 'PGtimetz 'PGinterval
2456−instance TimeOp 'PGinterval 'PGinterval
2457−instance TimeOp 'PGdate 'PGint4
2458−infixl 6 !+
2459−infixl 6 +!
2460−infixl 6 !-
2461−infixl 6 !-!