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