@@ -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,257 +34,54 @@ module Squeal.PostgreSQL.Expression
3534 ( -- * Expression
3635 Expression (..)
3736 , Expr
38− , (:-->)
37+ , type (-->)
38+ , FunctionDB
3939 , unsafeFunction
40− , unsafeUnaryOpL
41− , unsafeUnaryOpR
40+ , function
41+ , unsafeLeftOp
42+ , leftOp
43+ , unsafeRightOp
44+ , rightOp
4245 , Operator
46+ , OperatorDB
4347 , unsafeBinaryOp
48+ , binaryOp
4449 , FunctionVar
4550 , unsafeFunctionVar
46− , FunctionN
51+ , type (--->)
52+ , FunctionNDB
4753 , unsafeFunctionN
48− , Literal (..)
49− , HasParameter (parameter)
50− , param
51− -- * Null
52− , null_
53− , notNull
54− , coalesce
55− , fromNull
56− , isNull
57− , isNotNull
58− , matchNull
59− , nullIf
60− -- * Collections
61− , array
62− , array1
63− , array2
64− , cardinality
65− , index
66− , row
67− , field
54+ , functionN
6855 , PGSubset (..)
69− -- * Numerical
70− , atan2_
71− , quot_
72− , rem_
73− , trunc
74− , round_
75− , ceiling_
76− -- * Logic
77− , Condition
78− , true
79− , false
80− , not_
81− , (.&&)
82− , (.||)
83− , caseWhenThenElse
84− , ifThenElse
85− -- * Comparison
86− , (.==)
87− , (./=)
88− , (.>=)
89− , (.<)
90− , (.<=)
91− , (.>)
92− , greatest
93− , least
94− , between
95− , notBetween
96− , betweenSymmetric
97− , notBetweenSymmetric
98− , isDistinctFrom
99− , isNotDistinctFrom
100− , isTrue
101− , isNotTrue
102− , isFalse
103− , isNotFalse
104− , isUnknown
105− , isNotUnknown
106− -- * Time
107− , TimeOp (..)
108− , currentDate
109− , currentTime
110− , currentTimestamp
111− , localTime
112− , localTimestamp
113− , now
114− , makeDate
115− , makeTime
116− , makeTimestamp
117− , makeTimestamptz
118− , interval_
119− , TimeUnit (..)
120− -- * Text
121− , lower
122− , upper
123− , charLength
124− , like
125− , ilike
126− -- * Json
127− -- ** Json and Jsonb operators
128− , (.->)
129− , (.->>)
130− , (.#>)
131− , (.#>>)
132− -- ** Jsonb operators
133− , (.?)
134− , (.?|)
135− , (.?&)
136− , (.-.)
137− , (#-.)
138− -- ** Functions
139− , toJson
140− , toJsonb
141− , arrayToJson
142− , rowToJson
143− , jsonBuildArray
144− , jsonbBuildArray
145− , PGBuildObject
146− , jsonBuildObject
147− , jsonbBuildObject
148− , jsonObject
149− , jsonbObject
150− , jsonZipObject
151− , jsonbZipObject
152− , jsonArrayLength
153− , jsonbArrayLength
154− , jsonExtractPath
155− , jsonbExtractPath
156− , jsonExtractPathAsText
157− , jsonbExtractPathAsText
158− , jsonTypeof
159− , jsonbTypeof
160− , jsonStripNulls
161− , jsonbStripNulls
162− , jsonbSet
163− , jsonbInsert
164− , jsonbPretty
165− -- * Text Search
166− , (@@)
167− , (.&)
168− , (.|)
169− , (.!)
170− , (<->)
171− , arrayToTSvector
172− , tsvectorLength
173− , numnode
174− , plainToTSquery
175− , phraseToTSquery
176− , websearchToTSquery
177− , queryTree
178− , toTSquery
179− , toTSvector
180− , setWeight
181− , strip
182− , jsonToTSvector
183− , jsonbToTSvector
184− , tsDelete
185− , tsFilter
186− , tsHeadline
187− -- * Aggregation
188− , Aggregate (..)
189− , Distinction (..)
190− , PGAvg
191− -- * Window Functions
192− , WindowDefinition (..)
193− , partitionBy
194− , WindowFunction (..)
195− , rank
196− , rowNumber
197− , denseRank
198− , percentRank
199− , cumeDist
200− , ntile
201− , lag
202− , lead
203− , firstValue
204− , lastValue
205− , nthValue
206− -- * Sorting
207− , SortExpression (..)
208− , OrderBy (..)
209− -- * Types
210− , TypeExpression (..)
211− , cast
212− , PGTyped (..)
213− , typedef
214− , typetable
215− , typeview
216− , bool
217− , int2
218− , smallint
219− , int4
220− , int
221− , integer
222− , int8
223− , bigint
224− , numeric
225− , float4
226− , real
227− , float8
228− , doublePrecision
229− , money
230− , text
231− , char
232− , character
233− , varchar
234− , characterVarying
235− , bytea
236− , timestamp
237− , timestampWithTimeZone
238− , date
239− , time
240− , timeWithTimeZone
241− , interval
242− , uuid
243− , inet
244− , json
245− , jsonb
246− , vararray
247− , fixarray
248− , tsvector
249− , tsquery
56+ , PGIntersect (..)
25057 -- * Re-export
25158 , (&)
252− , NP (..)
25359 , K (..)
60+ , unK
25461 ) where
25562
25663import Control.Category
25764import Control.DeepSeq
25865import Data.ByteString (ByteString)
259−import Data.ByteString.Lazy (toStrict)
260−import ByteString.StrictBuilder (builderBytes)
26166import Data.Function ((&))
262−import Data.Kind
26367import Data.Semigroup hiding (All)
264−import qualified Data.Aeson as JSON
265−import Data.Int
26668import Data.String
267−import Data.Text (Text)
268−import Data.Word
26969import Generics.SOP hiding (All, from)
27070import GHC.OverloadedLabels
27171import GHC.TypeLits
27272import Numeric
27373import Prelude hiding (id, (.))
27474
275−import qualified Data.ByteString as ByteString
276−import qualified Data.Text as Text
277−import qualified Data.Text.Lazy as Lazy (Text)
278−import qualified Data.Text.Lazy as Lazy.Text
27975import qualified GHC.Generics as GHC
280−import qualified Generics.SOP as SOP
28176
28277import Squeal.PostgreSQL.Alias
283−import Squeal.PostgreSQL.Binary
28478import Squeal.PostgreSQL.List
285−import Squeal.PostgreSQL.PG
28679import Squeal.PostgreSQL.Render
28780import Squeal.PostgreSQL.Schema
28881
82+-- $setup
83+-- >>> import Squeal.PostgreSQL
84+
28985{-----------------------------------------
29086column expressions
29187-----------------------------------------}
@@ -295,7 +91,7 @@ such as in the target `Squeal.PostgreSQL.Query.List` of the
29591`Squeal.PostgreSQL.Query.select` command,
29692as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
29793`Squeal.PostgreSQL.Manipulation.update`,
298−or in search `Condition`s in a number of commands.
94+or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
29995
30096The expression syntax allows the calculation of
30197values from primitive expression using arithmetic, logical,
@@ -329,7 +125,7 @@ instance RenderSQL (Expression outer commons grp schemas params from ty) where
329125 renderSQL = renderExpression
330126
331127-- | An `Expr` is a closed `Expression`.
332−-- It is a F`RankNType` but don't be scared.
128+-- It is a F@RankNType@ but don't be scared.
333129-- Think of it as an expression which sees no
334130-- namespaces, so you can't use parameters
335131-- or alias references. It can be used as
@@ -339,7 +135,7 @@ type Expr x
339135 . Expression outer commons grp schemas params from x
340136 -- ^ cannot reference aliases
341137
342−-- | A `RankNType` for binary operators.
138+-- | A @RankNType@ for binary operators.
343139type Operator x1 x2 y
344140 = forall outer commons grp schemas params from
345141 . Expression outer commons grp schemas params from x1
@@ -349,32 +145,55 @@ type Operator x1 x2 y
349145 -> Expression outer commons grp schemas params from y
350146 -- ^ output
351147
352−-- | A `RankNType` for functions with a single argument.
148+type OperatorDB schemas x1 x2 y
149+ = forall outer commons grp params from
150+ . Expression outer commons grp schemas params from x1
151+ -- ^ left input
152+ -> Expression outer commons grp schemas params from x2
153+ -- ^ right input
154+ -> Expression outer commons grp schemas params from y
155+ -- ^ output
156+
157+-- | A @RankNType@ for functions with a single argument.
353158-- These could be either function calls or unary operators.
354159-- This is a subtype of the usual Haskell function type `Prelude.->`,
355160-- indeed a subcategory as it is closed under the usual
356161-- `Prelude..` and `Prelude.id`.
357−type (:-->) x y
162+type (-->) x y
358163 = forall outer commons grp schemas params from
359164 . Expression outer commons grp schemas params from x
360165 -- ^ input
361166 -> Expression outer commons grp schemas params from y
362167 -- ^ output
363168
364−{- | 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.
365177Use the `*:` operator to end your argument lists, like so.
366178
367179>>> printSQL (unsafeFunctionN "fun" (true :* false :* localTime *: true))
368180fun(TRUE, FALSE, LOCALTIME, TRUE)
369181-}
370−type FunctionN xs y
182+type (--->) xs y
371183 = forall outer commons grp schemas params from
372184 . NP (Expression outer commons grp schemas params from) xs
373185 -- ^ inputs
374186 -> Expression outer commons grp schemas params from y
375187 -- ^ output
376188
377−{- | A `RankNType` for functions with a variable-length list of
189+type FunctionNDB schemas xs y
190+ = forall outer commons grp params from
191+ . NP (Expression outer commons grp schemas params from) xs
192+ -- ^ inputs
193+ -> Expression outer commons grp schemas params from y
194+ -- ^ output
195+
196+{- | A @RankNType@ for functions with a variable-length list of
378197homogeneous arguments and at least 1 more argument.
379198-}
380199type FunctionVar x0 x1 y
@@ -393,46 +212,6 @@ unsafeFunctionVar :: ByteString -> FunctionVar x0 x1 y
393212unsafeFunctionVar fun xs x = UnsafeExpression $ fun <> parenthesized
394213 (commaSeparated (renderSQL <$> xs) <> ", " <> renderSQL x)
395214
396−{- | A `HasParameter` constraint is used to indicate a value that is
397−supplied externally to a SQL statement.
398−`Squeal.PostgreSQL.PQ.manipulateParams`,
399−`Squeal.PostgreSQL.PQ.queryParams` and
400−`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
401−separately from the SQL command string, in which case `param`s are used to
402−refer to the out-of-line data values.
403−-}
404−class KnownNat n => HasParameter
405− (n :: Nat)
406− (params :: [NullityType])
407− (ty :: NullityType)
408− | n params -> ty where
409− -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
410− --
411− -- >>> let expr = parameter @1 int4 :: Expression outer '[] grp schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
412− -- >>> printSQL expr
413− -- ($1 :: int4)
414− parameter
415− :: TypeExpression schemas ty
416− -> Expression outer commons grp schemas params from ty
417− parameter ty = UnsafeExpression $ parenthesized $
418− "$" <> renderNat @n <+> "::"
419− <+> renderSQL ty
420−instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
421−instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
422− => HasParameter n (ty' : params) ty
423−
424−-- | `param` takes a `Nat` using type application and for basic types,
425−-- infers a `TypeExpression`.
426−--
427−-- >>> let expr = param @1 :: Expression outer commons grp schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
428−-- >>> printSQL expr
429−-- ($1 :: int4)
430−param
431− :: forall n outer commons schemas params from grp ty
432− . (PGTyped schemas ty, HasParameter n params ty)
433− => Expression outer commons grp schemas params from ty -- ^ param
434−param = parameter @n (pgtype @schemas)
435−
436215instance (HasUnique tab (Join outer from) row, Has col row ty)
437216 => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
438217 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
@@ -529,242 +308,73 @@ instance
529308 (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
530309 tab ! col = tab ! col :* Nil
531310
532−-- | analagous to `Nothing`
533−--
534−-- >>> printSQL null_
535−-- NULL
536−null_ :: Expr ('Null ty)
537−null_ = UnsafeExpression "NULL"
538−
539−-- | analagous to `Just`
540−--
541−-- >>> printSQL $ notNull true
542−-- TRUE
543−notNull :: 'NotNull ty :--> 'Null ty
544−notNull = UnsafeExpression . renderSQL
545−
546−-- | return the leftmost value which is not NULL
547−--
548−-- >>> printSQL $ coalesce [null_, true] false
549−-- COALESCE(NULL, TRUE, FALSE)
550−coalesce :: FunctionVar ('Null ty) ('NotNull ty) ('NotNull ty)
551−coalesce nullxs notNullx = UnsafeExpression $
552− "COALESCE" <> parenthesized (commaSeparated
553− ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
554−
555−-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
556−--
557−-- >>> printSQL $ fromNull true null_
558−-- COALESCE(NULL, TRUE)
559−fromNull
560− :: Expression outer commons grp schemas params from ('NotNull ty)
561− -- ^ what to convert @NULL@ to
562− -> Expression outer commons grp schemas params from ('Null ty)
563− -> Expression outer commons grp schemas params from ('NotNull ty)
564−fromNull notNullx nullx = coalesce [nullx] notNullx
565−
566−-- | >>> printSQL $ null_ & isNull
567−-- NULL IS NULL
568−isNull :: 'Null ty :--> null 'PGbool
569−isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
570−
571−-- | >>> printSQL $ null_ & isNotNull
572−-- NULL IS NOT NULL
573−isNotNull :: 'Null ty :--> null 'PGbool
574−isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
575−
576−-- | analagous to `maybe` using @IS NULL@
577−--
578−-- >>> printSQL $ matchNull true not_ null_
579−-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
580−matchNull
581− :: Expression outer commons grp schemas params from (nullty)
582− -- ^ what to convert @NULL@ to
583− -> ( Expression outer commons grp schemas params from ('NotNull ty)
584− -> Expression outer commons grp schemas params from (nullty) )
585− -- ^ function to perform when @NULL@ is absent
586− -> Expression outer commons grp schemas params from ('Null ty)
587− -> Expression outer commons grp schemas params from (nullty)
588−matchNull y f x = ifThenElse (isNull x) y
589− (f (UnsafeExpression (renderSQL x)))
590−
591−{-| right inverse to `fromNull`, if its arguments are equal then
592−`nullIf` gives @NULL@.
593−
594−>>> :set -XTypeApplications -XDataKinds
595−>>> let expr = nullIf (false *: param @1) :: Expression outer commons grp schemas '[ 'NotNull 'PGbool] from ('Null 'PGbool)
596−>>> printSQL expr
597−NULLIF(FALSE, ($1 :: bool))
598−-}
599−nullIf :: FunctionN '[ 'NotNull ty, 'NotNull ty] ('Null ty)
600−nullIf = unsafeFunctionN "NULLIF"
601−
602−-- | >>> printSQL $ array [null_, false, true]
603−-- ARRAY[NULL, FALSE, TRUE]
604−array
605− :: [Expression outer commons grp schemas params from ty]
606− -- ^ array elements
607− -> Expression outer commons grp schemas params from (null ('PGvararray ty))
608−array xs = UnsafeExpression $ "ARRAY" <>
609− bracketed (commaSeparated (renderSQL <$> xs))
610−
611−{- | construct a 1-dimensional fixed length array
612−
613−>>> printSQL $ array1 (null_ :* false *: true)
614−ARRAY[NULL, FALSE, TRUE]
615−
616−>>> :type array1 (null_ :* false *: true)
617−array1 (null_ :* false *: true)
618− :: Expression
619− outer
620− commons
621− grp
622− schemas
623− params
624− from
625− (null ('PGfixarray '[3] ('Null 'PGbool)))
626−-}
627−array1
628− :: (n ~ Length tys, SOP.All ((~) ty) tys)
629− => NP (Expression outer commons grp schemas params from) tys
630− -> Expression outer commons grp schemas params from (null ('PGfixarray '[n] ty))
631−array1 xs = UnsafeExpression $ "ARRAY" <>
632− bracketed (renderCommaSeparated renderSQL xs)
633−
634−{- | construct a 2-dimensional fixed length array
635−
636−>>> printSQL $ array2 ((null_ :* false *: true) *: (false :* null_ *: true))
637−ARRAY[[NULL, FALSE, TRUE], [FALSE, NULL, TRUE]]
638−
639−>>> :type array2 ((null_ :* false *: true) *: (false :* null_ *: true))
640−array2 ((null_ :* false *: true) *: (false :* null_ *: true))
641− :: Expression
642− outer
643− commons
644− grp
645− schemas
646− params
647− from
648− (null ('PGfixarray '[2, 3] ('Null 'PGbool)))
649−-}
650−array2
651− :: ( SOP.All ((~) tys) tyss
652− , SOP.All SOP.SListI tyss
653− , Length tyss ~ n1
654− , SOP.All ((~) ty) tys
655− , Length tys ~ n2 )
656− => NP (NP (Expression outer commons grp schemas params from)) tyss
657− -> Expression outer commons grp schemas params from (null ('PGfixarray '[n1,n2] ty))
658−array2 xss = UnsafeExpression $ "ARRAY" <>
659− bracketed (renderCommaSeparatedConstraint @SOP.SListI (bracketed . renderCommaSeparated renderSQL) xss)
660−
661−-- | >>> printSQL $ cardinality (array [null_, false, true])
662−-- cardinality(ARRAY[NULL, FALSE, TRUE])
663−cardinality :: null ('PGvararray ty) :--> null 'PGint8
664−cardinality = unsafeFunction "cardinality"
665−
666−-- | >>> printSQL $ array [null_, false, true] & index 2
667−-- (ARRAY[NULL, FALSE, TRUE])[2]
668−index
669− :: Word64 -- ^ index
670− -> null ('PGvararray ty) :--> NullifyType ty
671−index n expr = UnsafeExpression $
672− parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
673−
674311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
675312 (Expression outer commons grp schemas params from (null ('PGenum labels))) where
676313 label = UnsafeExpression $ renderSQL (PGlabel @label)
677314
678−-- | A row constructor is an expression that builds a row value
679−-- (also called a composite value) using values for its member fields.
680−--
681−-- >>> :{
682−-- type Complex = 'PGcomposite
683−-- '[ "real" ::: 'NotNull 'PGfloat8
684−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
685−-- :}
686−--
687−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer commons grp schemas params from ('NotNull Complex)
688−-- >>> printSQL i
689−-- ROW(0, 1)
690−row
691− :: SListI row
692− => NP (Aliased (Expression outer commons grp schemas params from)) row
693− -- ^ zero or more expressions for the row field values
694− -> Expression outer commons grp schemas params from (null ('PGcomposite row))
695−row exprs = UnsafeExpression $ "ROW" <> parenthesized
696− (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
697−
698−-- | >>> :{
699−-- type Complex = 'PGcomposite
700−-- '[ "real" ::: 'NotNull 'PGfloat8
701−-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
702−-- type Schema = '["complex" ::: 'Typedef Complex]
703−-- :}
704−--
705−-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer '[] grp (Public Schema) from params ('NotNull Complex)
706−-- >>> printSQL $ i & field #complex #imaginary
707−-- (ROW(0, 1)::"complex")."imaginary"
708−field
709− :: ( Has sch schemas schema
710− , Has tydef schema ('Typedef ('PGcomposite row))
711− , Has field row ty)
712− => QualifiedAlias sch tydef -- ^ row type
713− -> Alias field -- ^ field name
714− -> Expression outer commons grp schemas params from ('NotNull ('PGcomposite row))
715− -> Expression outer commons grp schemas params from ty
716−field td fld expr = UnsafeExpression $
717− parenthesized (renderSQL expr <> "::" <> renderSQL td)
718− <> "." <> renderSQL fld
719−
720−instance Semigroup
721− (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
722− (<>) = unsafeBinaryOp "||"
723−
724−instance Monoid
725− (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
726− mempty = array []
727− mappend = (<>)
728−
729−-- | >>> let expr = greatest [param @1] currentTimestamp :: Expression outer commons grp schemas '[ 'NotNull 'PGtimestamptz] from ('NotNull 'PGtimestamptz)
730−-- >>> printSQL expr
731−-- GREATEST(($1 :: timestamp with time zone), CURRENT_TIMESTAMP)
732−greatest :: FunctionVar ty ty ty
733−greatest = unsafeFunctionVar "GREATEST"
734−
735−-- | >>> printSQL $ least [null_] currentTimestamp
736−-- LEAST(NULL, CURRENT_TIMESTAMP)
737−least :: FunctionVar ty ty ty
738−least = unsafeFunctionVar "LEAST"
739−
740315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
741316-- (TRUE OR FALSE)
742317unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
743318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
744319 renderSQL x <+> op <+> renderSQL y
745320
746−-- | >>> 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
747329-- (NOT TRUE)
748−unsafeUnaryOpL :: ByteString -> x :--> y
749−unsafeUnaryOpL op x = UnsafeExpression $ parenthesized $ op <+> renderSQL x
330+unsafeLeftOp :: ByteString -> x --> y
331+unsafeLeftOp op x = UnsafeExpression $ parenthesized $ op <+> renderSQL x
750332
751−-- | >>> 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"
752341-- (TRUE IS NOT TRUE)
753−unsafeUnaryOpR :: ByteString -> x :--> y
754−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
755351
756352-- | >>> printSQL $ unsafeFunction "f" true
757353-- f(TRUE)
758−unsafeFunction :: ByteString -> x :--> y
354+unsafeFunction :: ByteString -> x --> y
759355unsafeFunction fun x = UnsafeExpression $
760356 fun <> parenthesized (renderSQL x)
761357
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+
762364-- | >>> printSQL $ unsafeFunctionN "f" (currentTime :* localTimestamp :* false *: literal 'a')
763365-- f(CURRENT_TIME, LOCALTIMESTAMP, FALSE, E'a')
764−unsafeFunctionN :: SListI xs => ByteString -> FunctionN xs y
366+unsafeFunctionN :: SListI xs => ByteString -> xs ---> y
765367unsafeFunctionN fun xs = UnsafeExpression $
766368 fun <> parenthesized (renderCommaSeparated renderSQL xs)
767369
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+
768378instance ty `In` PGNum
769379 => Num (Expression outer commons grp schemas params from (null ty)) where
770380 (+) = unsafeBinaryOp "+"
@@ -809,364 +419,22 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
809419 acosh x = log (x + sqrt (x*x - 1))
810420 atanh x = log ((1 + x) / (1 - x)) / 2
811421
812−-- | >>> :{
813−-- let
814−-- expression :: Expr (null 'PGfloat4)
815−-- expression = atan2_ (pi *: 2)
816−-- in printSQL expression
817−-- :}
818−-- atan2(pi(), 2)
819−atan2_
820− :: float `In` PGFloating
821− => FunctionN '[ null float, null float] (null float)
822−atan2_ = unsafeFunctionN "atan2"
823−
824−-- When a `cast` is applied to an `Expression` of a known type, it
825−-- represents a run-time type conversion. The cast will succeed only if a
826−-- suitable type conversion operation has been defined.
827−--
828−-- | >>> printSQL $ true & cast int4
829−-- (TRUE :: int4)
830−cast
831− :: TypeExpression schemas ty1
832− -- ^ type to cast as
833− -> Expression outer commons grp schemas params from ty0
834− -- ^ value to convert
835− -> Expression outer commons grp schemas params from ty1
836−cast ty x = UnsafeExpression $ parenthesized $
837− renderSQL x <+> "::" <+> renderSQL ty
838−
839−-- | integer division, truncates the result
840−--
841−-- >>> :{
842−-- let
843−-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
844−-- expression = 5 `quot_` 2
845−-- in printSQL expression
846−-- :}
847−-- (5 / 2)
848−quot_
849− :: int `In` PGIntegral
850− => Operator (null int) (null int) (null int)
851−quot_ = unsafeBinaryOp "/"
852−
853−-- | remainder upon integer division
854−--
855−-- >>> :{
856−-- let
857−-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
858−-- expression = 5 `rem_` 2
859−-- in printSQL expression
860−-- :}
861−-- (5 % 2)
862−rem_
863− :: int `In` PGIntegral
864− => Operator (null int) (null int) (null int)
865−rem_ = unsafeBinaryOp "%"
866−
867−-- | >>> :{
868−-- let
869−-- expression :: Expression outer commons grp schemas params from (null 'PGfloat4)
870−-- expression = trunc pi
871−-- in printSQL expression
872−-- :}
873−-- trunc(pi())
874−trunc :: frac `In` PGFloating => null frac :--> null frac
875−trunc = unsafeFunction "trunc"
876−
877−-- | >>> :{
878−-- let
879−-- expression :: Expression outer commons grp schemas params from (null 'PGfloat4)
880−-- expression = round_ pi
881−-- in printSQL expression
882−-- :}
883−-- round(pi())
884−round_ :: frac `In` PGFloating => null frac :--> null frac
885−round_ = unsafeFunction "round"
886−
887−-- | >>> :{
888−-- let
889−-- expression :: Expression outer commons grp schemas params from (null 'PGfloat4)
890−-- expression = ceiling_ pi
891−-- in printSQL expression
892−-- :}
893−-- ceiling(pi())
894−ceiling_ :: frac `In` PGFloating => null frac :--> null frac
895−ceiling_ = unsafeFunction "ceiling"
896−
897−-- | A `Condition` is an `Expression`, which can evaluate
898−-- to `true`, `false` or `null_`. This is because SQL uses
899−-- a three valued logic.
900−type Condition outer commons grp schemas params from =
901− Expression outer commons grp schemas params from ('Null 'PGbool)
902−
903−-- | >>> printSQL true
904−-- TRUE
905−true :: Expr (null 'PGbool)
906−true = UnsafeExpression "TRUE"
907−
908−-- | >>> printSQL false
909−-- FALSE
910−false :: Expr (null 'PGbool)
911−false = UnsafeExpression "FALSE"
912−
913−-- | >>> printSQL $ not_ true
914−-- (NOT TRUE)
915−not_ :: null 'PGbool :--> null 'PGbool
916−not_ = unsafeUnaryOpL "NOT"
917−
918−-- | >>> printSQL $ true .&& false
919−-- (TRUE AND FALSE)
920−(.&&) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
921−infixr 3 .&&
922−(.&&) = unsafeBinaryOp "AND"
923−
924−-- | >>> printSQL $ true .|| false
925−-- (TRUE OR FALSE)
926−(.||) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
927−infixr 2 .||
928−(.||) = unsafeBinaryOp "OR"
929−
930−-- | >>> :{
931−-- let
932−-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
933−-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
934−-- in printSQL expression
935−-- :}
936−-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
937−caseWhenThenElse
938− :: [ ( Condition outer commons grp schemas params from
939− , Expression outer commons grp schemas params from ty
940− ) ]
941− -- ^ whens and thens
942− -> Expression outer commons grp schemas params from ty
943− -- ^ else
944− -> Expression outer commons grp schemas params from ty
945−caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
946− [ "CASE"
947− , mconcat
948− [ mconcat
949− [ " WHEN ", renderSQL when_
950− , " THEN ", renderSQL then_
951− ]
952− | (when_,then_) <- whenThens
953− ]
954− , " ELSE ", renderSQL else_
955− , " END"
956− ]
957−
958−-- | >>> :{
959−-- let
960−-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
961−-- expression = ifThenElse true 1 0
962−-- in printSQL expression
963−-- :}
964−-- CASE WHEN TRUE THEN 1 ELSE 0 END
965−ifThenElse
966− :: Condition outer commons grp schemas params from
967− -> Expression outer commons grp schemas params from ty -- ^ then
968− -> Expression outer commons grp schemas params from ty -- ^ else
969− -> Expression outer commons grp schemas params from ty
970−ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
971−
972−-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
973−-- will produce @NULL@s if one of their arguments is @NULL@.
974−--
975−-- >>> printSQL $ true .== null_
976−-- (TRUE = NULL)
977−(.==) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
978−(.==) = unsafeBinaryOp "="
979−infix 4 .==
980−
981−-- | >>> printSQL $ true ./= null_
982−-- (TRUE <> NULL)
983−(./=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
984−(./=) = unsafeBinaryOp "<>"
985−infix 4 ./=
986−
987−-- | >>> printSQL $ true .>= null_
988−-- (TRUE >= NULL)
989−(.>=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
990−(.>=) = unsafeBinaryOp ">="
991−infix 4 .>=
992−
993−-- | >>> printSQL $ true .< null_
994−-- (TRUE < NULL)
995−(.<) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
996−(.<) = unsafeBinaryOp "<"
997−infix 4 .<
998−
999−-- | >>> printSQL $ true .<= null_
1000−-- (TRUE <= NULL)
1001−(.<=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
1002−(.<=) = unsafeBinaryOp "<="
1003−infix 4 .<=
1004−
1005−-- | >>> printSQL $ true .> null_
1006−-- (TRUE > NULL)
1007−(.>) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
1008−(.>) = unsafeBinaryOp ">"
1009−infix 4 .>
1010−
1011−{- | >>> printSQL $ true `between` (null_, false)
1012−TRUE BETWEEN NULL AND FALSE
1013−-}
1014−between
1015− :: Expression outer commons grp schemas params from (null ty)
1016− -> ( Expression outer commons grp schemas params from (null ty)
1017− , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1018− -> Condition outer commons grp schemas params from
1019−between a (x,y) = UnsafeExpression $ renderSQL a <+> "BETWEEN"
1020− <+> renderSQL x <+> "AND" <+> renderSQL y
1021−
1022−{- | >>> printSQL $ true `notBetween` (null_, false)
1023−TRUE NOT BETWEEN NULL AND FALSE
1024−-}
1025−notBetween
1026− :: Expression outer commons grp schemas params from (null ty)
1027− -> ( Expression outer commons grp schemas params from (null ty)
1028− , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1029− -> Condition outer commons grp schemas params from
1030−notBetween a (x,y) = UnsafeExpression $ renderSQL a <+> "NOT BETWEEN"
1031− <+> renderSQL x <+> "AND" <+> renderSQL y
1032−
1033−{- | between, after sorting the comparison values
1034−
1035−>>> printSQL $ true `betweenSymmetric` (null_, false)
1036−TRUE BETWEEN SYMMETRIC NULL AND FALSE
1037−-}
1038−betweenSymmetric
1039− :: Expression outer commons grp schemas params from (null ty)
1040− -> ( Expression outer commons grp schemas params from (null ty)
1041− , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1042− -> Condition outer commons grp schemas params from
1043−betweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
1044− <+> "BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
1045−
1046−{- | not between, after sorting the comparison values
1047−
1048−>>> printSQL $ true `notBetweenSymmetric` (null_, false)
1049−TRUE NOT BETWEEN SYMMETRIC NULL AND FALSE
1050−-}
1051−notBetweenSymmetric
1052− :: Expression outer commons grp schemas params from (null ty)
1053− -> ( Expression outer commons grp schemas params from (null ty)
1054− , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1055− -> Condition outer commons grp schemas params from
1056−notBetweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
1057− <+> "NOT BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
1058−
1059−{- | not equal, treating null like an ordinary value
1060−
1061−>>> printSQL $ true `isDistinctFrom` null_
1062−(TRUE IS DISTINCT FROM NULL)
1063−-}
1064−isDistinctFrom :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
1065−isDistinctFrom = unsafeBinaryOp "IS DISTINCT FROM"
1066−
1067−{- | equal, treating null like an ordinary value
1068−
1069−>>> printSQL $ true `isNotDistinctFrom` null_
1070−(TRUE IS NOT DISTINCT FROM NULL)
1071−-}
1072−isNotDistinctFrom :: Operator (null0 ty) (null1 ty) ('NotNull 'PGbool)
1073−isNotDistinctFrom = unsafeBinaryOp "IS NOT DISTINCT FROM"
1074−
1075−{- | is true
1076−
1077−>>> printSQL $ true & isTrue
1078−(TRUE IS TRUE)
1079−-}
1080−isTrue :: null0 'PGbool :--> null1 'PGbool
1081−isTrue = unsafeUnaryOpR "IS TRUE"
1082−
1083−{- | is false or unknown
1084−
1085−>>> printSQL $ true & isNotTrue
1086−(TRUE IS NOT TRUE)
1087−-}
1088−isNotTrue :: null0 'PGbool :--> null1 'PGbool
1089−isNotTrue = unsafeUnaryOpR "IS NOT TRUE"
1090−
1091−{- | is false
1092−
1093−>>> printSQL $ true & isFalse
1094−(TRUE IS FALSE)
1095−-}
1096−isFalse :: null0 'PGbool :--> null1 'PGbool
1097−isFalse = unsafeUnaryOpR "IS FALSE"
1098−
1099−{- | is true or unknown
1100−
1101−>>> printSQL $ true & isNotFalse
1102−(TRUE IS NOT FALSE)
1103−-}
1104−isNotFalse :: null0 'PGbool :--> null1 'PGbool
1105−isNotFalse = unsafeUnaryOpR "IS NOT FALSE"
1106−
1107−{- | is unknown
1108−
1109−>>> printSQL $ true & isUnknown
1110−(TRUE IS UNKNOWN)
1111−-}
1112−isUnknown :: null0 'PGbool :--> null1 'PGbool
1113−isUnknown = unsafeUnaryOpR "IS UNKNOWN"
1114−
1115−{- | is true or false
1116−
1117−>>> printSQL $ true & isNotUnknown
1118−(TRUE IS NOT UNKNOWN)
1119−-}
1120−isNotUnknown :: null0 'PGbool :--> null1 'PGbool
1121−isNotUnknown = unsafeUnaryOpR "IS NOT UNKNOWN"
1122−
1123−-- | >>> printSQL currentDate
1124−-- CURRENT_DATE
1125−currentDate :: Expr (null 'PGdate)
1126−currentDate = UnsafeExpression "CURRENT_DATE"
1127−
1128−-- | >>> printSQL currentTime
1129−-- CURRENT_TIME
1130−currentTime :: Expr (null 'PGtimetz)
1131−currentTime = UnsafeExpression "CURRENT_TIME"
1132−
1133−-- | >>> printSQL currentTimestamp
1134−-- CURRENT_TIMESTAMP
1135−currentTimestamp :: Expr (null 'PGtimestamptz)
1136−currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
1137−
1138−-- | >>> printSQL localTime
1139−-- LOCALTIME
1140−localTime :: Expr (null 'PGtime)
1141−localTime = UnsafeExpression "LOCALTIME"
1142−
1143−-- | >>> printSQL localTimestamp
1144−-- LOCALTIMESTAMP
1145−localTimestamp :: Expr (null 'PGtimestamp)
1146−localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
1147−
1148−-- | Current date and time (equivalent to `currentTimestamp`)
1149−--
1150−-- >>> printSQL now
1151−-- now()
1152−now :: Expr (null 'PGtimestamptz)
1153−now = UnsafeExpression "now()"
1154−
1155−{-----------------------------------------
1156−text
1157−-----------------------------------------}
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)
1158432
1159−escape :: Char -> String
1160−escape = \case
1161− '\NUL' -> "\\0"
1162− '\'' -> "''"
1163− '"' -> "\\\""
1164− '\b' -> "\\b"
1165− '\n' -> "\\n"
1166− '\r' -> "\\r"
1167− '\t' -> "\\t"
1168− '\\' -> "\\\\"
1169− 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)
1170438
1171439instance IsString
1172440 (Expression outer commons grp schemas params from (null 'PGtext)) where
@@ -1174,13 +442,19 @@ instance IsString
1174442 "E\'" <> fromString (escape =<< str) <> "\'"
1175443instance IsString
1176444 (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1177− fromString str = cast tsvector . UnsafeExpression $
445+ fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
1178446 "E\'" <> fromString (escape =<< str) <> "\'"
1179447instance IsString
1180448 (Expression outer commons grp schemas params from (null 'PGtsquery)) where
1181− fromString str = cast tsquery . UnsafeExpression $
449+ fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
1182450 "E\'" <> fromString (escape =<< str) <> "\'"
1183451
452+instance Semigroup
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 "||"
1184458instance Semigroup
1185459 (Expression outer commons grp schemas params from (null 'PGtext)) where
1186460 (<>) = unsafeBinaryOp "||"
@@ -1196,1399 +470,3 @@ instance Monoid
1196470 (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1197471 mempty = fromString ""
1198472 mappend = (<>)
1199−
1200−-- | >>> printSQL $ lower "ARRRGGG"
1201−-- lower(E'ARRRGGG')
1202−lower :: null 'PGtext :--> null 'PGtext
1203−lower = unsafeFunction "lower"
1204−
1205−-- | >>> printSQL $ upper "eeee"
1206−-- upper(E'eeee')
1207−upper :: null 'PGtext :--> null 'PGtext
1208−upper = unsafeFunction "upper"
1209−
1210−-- | >>> printSQL $ charLength "four"
1211−-- char_length(E'four')
1212−charLength :: null 'PGtext :--> null 'PGint4
1213−charLength = unsafeFunction "char_length"
1214−
1215−-- | The `like` expression returns true if the @string@ matches
1216−-- the supplied @pattern@. If @pattern@ does not contain percent signs
1217−-- or underscores, then the pattern only represents the string itself;
1218−-- in that case `like` acts like the equals operator. An underscore (_)
1219−-- in pattern stands for (matches) any single character; a percent sign (%)
1220−-- matches any sequence of zero or more characters.
1221−--
1222−-- >>> printSQL $ "abc" `like` "a%"
1223−-- (E'abc' LIKE E'a%')
1224−like :: Operator (null 'PGtext) (null 'PGtext) ('Null 'PGbool)
1225−like = unsafeBinaryOp "LIKE"
1226−
1227−-- | The key word ILIKE can be used instead of LIKE to make the
1228−-- match case-insensitive according to the active locale.
1229−--
1230−-- >>> printSQL $ "abc" `ilike` "a%"
1231−-- (E'abc' ILIKE E'a%')
1232−ilike :: Operator (null 'PGtext) (null 'PGtext) ('Null 'PGbool)
1233−ilike = unsafeBinaryOp "ILIKE"
1234−
1235−{-----------------------------------------
1236− -- json and jsonb support
1237−
1238−See https://www.postgresql.org/docs/10/static/functions-json.html -- most
1239−comments lifted directly from this page.
1240−
1241−Table 9.44: json and jsonb operators
1242−-----------------------------------------}
1243−
1244−-- | Get JSON value (object field or array element) at a key.
1245−(.->)
1246− :: (json `In` PGJsonType, key `In` PGJsonKey)
1247− => Operator (null json) (null key) ('Null json)
1248−infixl 8 .->
1249−(.->) = unsafeBinaryOp "->"
1250−
1251−-- | Get JSON value (object field or array element) at a key, as text.
1252−(.->>)
1253− :: (json `In` PGJsonType, key `In` PGJsonKey)
1254− => Operator (null json) (null key) ('Null 'PGtext)
1255−infixl 8 .->>
1256−(.->>) = unsafeBinaryOp "->>"
1257−
1258−-- | Get JSON value at a specified path.
1259−(.#>)
1260− :: json `In` PGJsonType
1261− => Operator (null json) (null ('PGvararray ('NotNull 'PGtext))) ('Null json)
1262−infixl 8 .#>
1263−(.#>) = unsafeBinaryOp "#>"
1264−
1265−-- | Get JSON value at a specified path as text.
1266−(.#>>)
1267− :: json `In` PGJsonType
1268− => Operator (null json) (null ('PGvararray ('NotNull 'PGtext))) ('Null 'PGtext)
1269−infixl 8 .#>>
1270−(.#>>) = unsafeBinaryOp "#>>"
1271−
1272−-- Additional jsonb operators
1273−
1274−class PGSubset container where
1275− (@>) :: Operator (null0 container) (null1 container) ('Null 'PGbool)
1276− (@>) = unsafeBinaryOp "@>"
1277− (<@) :: Operator (null0 container) (null1 container) ('Null 'PGbool)
1278− (<@) = unsafeBinaryOp "<@"
1279−instance PGSubset 'PGjsonb
1280−instance PGSubset 'PGtsquery
1281−instance PGSubset ('PGvararray ty)
1282−
1283−-- | Does the string exist as a top-level key within the JSON value?
1284−(.?) :: Operator (null 'PGjsonb) (null 'PGtext) ('Null 'PGbool)
1285−infixl 9 .?
1286−(.?) = unsafeBinaryOp "?"
1287−
1288−-- | Do any of these array strings exist as top-level keys?
1289−(.?|) :: Operator
1290− (null 'PGjsonb)
1291− (null ('PGvararray ('NotNull 'PGtext)))
1292− ('Null 'PGbool)
1293−infixl 9 .?|
1294−(.?|) = unsafeBinaryOp "?|"
1295−
1296−-- | Do all of these array strings exist as top-level keys?
1297−(.?&) :: Operator
1298− (null 'PGjsonb)
1299− (null ('PGvararray ('NotNull 'PGtext)))
1300− ('Null 'PGbool)
1301−infixl 9 .?&
1302−(.?&) = unsafeBinaryOp "?&"
1303−
1304−instance Semigroup
1305− (Expression outer commons grp schemas params from (null 'PGjsonb)) where
1306− (<>) = unsafeBinaryOp "||"
1307−
1308−-- | Delete a key or keys from a JSON object, or remove an array element.
1309−--
1310−-- If the right operand is..
1311−--
1312−-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1313−-- are matched based on their key value.
1314−--
1315−-- @ text[] @: Delete multiple key/value pairs or string elements
1316−-- from left operand. Key/value pairs are matched based on their key value.
1317−--
1318−-- @ integer @: Delete the array element with specified index (Negative integers
1319−-- count from the end). Throws an error if top level container is not an array.
1320−(.-.)
1321− :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1322− => Operator (null 'PGjsonb) (null key) (null 'PGjsonb)
1323−infixl 6 .-.
1324−(.-.) = unsafeBinaryOp "-"
1325−
1326−-- | Delete the field or element with specified path (for JSON arrays, negative
1327−-- integers count from the end)
1328−(#-.) :: Operator (null 'PGjsonb) (null ('PGvararray ('NotNull 'PGtext))) (null 'PGjsonb)
1329−infixl 6 #-.
1330−(#-.) = unsafeBinaryOp "#-"
1331−
1332−{-----------------------------------------
1333−Table 9.45: JSON creation functions
1334−-----------------------------------------}
1335−
1336−-- | Returns the value as json. Arrays and composites are converted
1337−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1338−-- type to json, the cast function will be used to perform the conversion;
1339−-- otherwise, a scalar value is produced. For any scalar type other than a
1340−-- number, a Boolean, or a null value, the text representation will be used, in
1341−-- such a fashion that it is a valid json value.
1342−toJson :: null ty :--> null 'PGjson
1343−toJson = unsafeFunction "to_json"
1344−
1345−-- | Returns the value as jsonb. Arrays and composites are converted
1346−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1347−-- type to json, the cast function will be used to perform the conversion;
1348−-- otherwise, a scalar value is produced. For any scalar type other than a
1349−-- number, a Boolean, or a null value, the text representation will be used, in
1350−-- such a fashion that it is a valid jsonb value.
1351−toJsonb :: null ty :--> null 'PGjsonb
1352−toJsonb = unsafeFunction "to_jsonb"
1353−
1354−-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1355−-- becomes a JSON array of arrays.
1356−arrayToJson :: null ('PGvararray ty) :--> null 'PGjson
1357−arrayToJson = unsafeFunction "array_to_json"
1358−
1359−-- | Returns the row as a JSON object.
1360−rowToJson :: null ('PGcomposite ty) :--> null 'PGjson
1361−rowToJson = unsafeFunction "row_to_json"
1362−
1363−-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1364−-- argument list.
1365−jsonBuildArray :: SListI tuple => FunctionN tuple (null 'PGjson)
1366−jsonBuildArray = unsafeFunctionN "json_build_array"
1367−
1368−-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1369−-- variadic argument list.
1370−jsonbBuildArray :: SListI tuple => FunctionN tuple (null 'PGjsonb)
1371−jsonbBuildArray = unsafeFunctionN "jsonb_build_array"
1372−
1373−class PGBuildObject tys where
1374−instance PGBuildObject '[]
1375−instance (PGBuildObject tys, key `In` PGJsonKey)
1376− => PGBuildObject ('NotNull key ': value ': tys)
1377−
1378−-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1379−-- argument list. The elements of the argument list must alternate between text
1380−-- and values.
1381−jsonBuildObject
1382− :: (SListI elems, PGBuildObject elems)
1383− => FunctionN elems (null 'PGjson)
1384−jsonBuildObject = unsafeFunctionN "json_build_object"
1385−
1386−-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1387−-- variadic argument list. The elements of the argument list must alternate
1388−-- between keys and values.
1389−jsonbBuildObject
1390− :: (SListI elems, PGBuildObject elems)
1391− => FunctionN elems (null 'PGjsonb)
1392−jsonbBuildObject = unsafeFunctionN "jsonb_build_object"
1393−
1394−-- | Builds a JSON object out of a text array.
1395−-- The array must have two dimensions
1396−-- such that each inner array has exactly two elements,
1397−-- which are taken as a key/value pair.
1398−jsonObject
1399− :: null ('PGfixarray '[n,2] ('NotNull 'PGtext))
1400− :--> null 'PGjson
1401−jsonObject = unsafeFunction "json_object"
1402−
1403−-- | Builds a binary JSON object out of a text array.
1404−-- The array must have two dimensions
1405−-- such that each inner array has exactly two elements,
1406−-- which are taken as a key/value pair.
1407−jsonbObject
1408− :: null ('PGfixarray '[n,2] ('NotNull 'PGtext))
1409− :--> null 'PGjsonb
1410−jsonbObject = unsafeFunction "jsonb_object"
1411−
1412−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1413−-- keys and one for values, that are zipped pairwise to create a JSON object.
1414−jsonZipObject :: FunctionN
1415− '[ null ('PGvararray ('NotNull 'PGtext))
1416− , null ('PGvararray ('NotNull 'PGtext)) ]
1417− ( null 'PGjson )
1418−jsonZipObject = unsafeFunctionN "json_object"
1419−
1420−-- | This is an alternate form of 'jsonbObject' that takes two arrays; one for
1421−-- keys and one for values, that are zipped pairwise to create a binary JSON
1422−-- object.
1423−jsonbZipObject :: FunctionN
1424− '[ null ('PGvararray ('NotNull 'PGtext))
1425− , null ('PGvararray ('NotNull 'PGtext)) ]
1426− ( null 'PGjsonb )
1427−jsonbZipObject = unsafeFunctionN "jsonb_object"
1428−
1429−{-----------------------------------------
1430−Table 9.46: JSON processing functions
1431−-----------------------------------------}
1432−
1433−-- | Returns the number of elements in the outermost JSON array.
1434−jsonArrayLength :: null 'PGjson :--> null 'PGint4
1435−jsonArrayLength = unsafeFunction "json_array_length"
1436−
1437−-- | Returns the number of elements in the outermost binary JSON array.
1438−jsonbArrayLength :: null 'PGjsonb :--> null 'PGint4
1439−jsonbArrayLength = unsafeFunction "jsonb_array_length"
1440−
1441−-- | Returns JSON value pointed to by the given path (equivalent to #>
1442−-- operator).
1443−jsonExtractPath
1444− :: SListI elems
1445− => Expression outer commons grp schemas params from (null 'PGjson)
1446− -> NP (Expression outer commons grp schemas params from) elems
1447− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1448−jsonExtractPath x xs =
1449− unsafeFunctionN "json_extract_path" (x :* xs)
1450−
1451−-- | Returns JSON value pointed to by the given path (equivalent to #>
1452−-- operator).
1453−jsonbExtractPath
1454− :: SListI elems
1455− => Expression outer commons grp schemas params from (null 'PGjsonb)
1456− -> NP (Expression outer commons grp schemas params from) elems
1457− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1458−jsonbExtractPath x xs =
1459− unsafeFunctionN "jsonb_extract_path" (x :* xs)
1460−
1461−-- | Returns JSON value pointed to by the given path (equivalent to #>
1462−-- operator), as text.
1463−jsonExtractPathAsText
1464− :: SListI elems
1465− => Expression outer commons grp schemas params from (null 'PGjson)
1466− -> NP (Expression outer commons grp schemas params from) elems
1467− -> Expression outer commons grp schemas params from (null 'PGjson)
1468−jsonExtractPathAsText x xs =
1469− unsafeFunctionN "json_extract_path_text" (x :* xs)
1470−
1471−-- | Returns JSON value pointed to by the given path (equivalent to #>
1472−-- operator), as text.
1473−jsonbExtractPathAsText
1474− :: SListI elems
1475− => Expression outer commons grp schemas params from (null 'PGjsonb)
1476− -> NP (Expression outer commons grp schemas params from) elems
1477− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1478−jsonbExtractPathAsText x xs =
1479− unsafeFunctionN "jsonb_extract_path_text" (x :* xs)
1480−
1481−-- | Returns the type of the outermost JSON value as a text string. Possible
1482−-- types are object, array, string, number, boolean, and null.
1483−jsonTypeof :: null 'PGjson :--> null 'PGtext
1484−jsonTypeof = unsafeFunction "json_typeof"
1485−
1486−-- | Returns the type of the outermost binary JSON value as a text string.
1487−-- Possible types are object, array, string, number, boolean, and null.
1488−jsonbTypeof :: null 'PGjsonb :--> null 'PGtext
1489−jsonbTypeof = unsafeFunction "jsonb_typeof"
1490−
1491−-- | Returns its argument with all object fields that have null values omitted.
1492−-- Other null values are untouched.
1493−jsonStripNulls :: null 'PGjson :--> null 'PGjson
1494−jsonStripNulls = unsafeFunction "json_strip_nulls"
1495−
1496−-- | Returns its argument with all object fields that have null values omitted.
1497−-- Other null values are untouched.
1498−jsonbStripNulls :: null 'PGjsonb :--> null 'PGjsonb
1499−jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1500−
1501−-- | @ jsonbSet target path new_value create_missing @
1502−--
1503−-- Returns target with the section designated by path replaced by new_value,
1504−-- or with new_value added if create_missing is true ( default is true) and the
1505−-- item designated by path does not exist. As with the path orientated
1506−-- operators, negative integers that appear in path count from the end of JSON
1507−-- arrays.
1508−jsonbSet
1509− :: Expression outer commons grp schemas params from (null 'PGjsonb)
1510− -> Expression outer commons grp schemas params from (null ('PGvararray ('NotNull 'PGtext)))
1511− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1512− -> Maybe (Expression outer commons grp schemas params from (null 'PGbool))
1513− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1514−jsonbSet tgt path val createMissing = case createMissing of
1515− Just m -> unsafeFunctionN "jsonb_set" (tgt :* path :* val :* m :* Nil)
1516− Nothing -> unsafeFunctionN "jsonb_set" (tgt :* path :* val :* Nil)
1517−
1518−-- | @ jsonbInsert target path new_value insert_after @
1519−--
1520−-- Returns target with new_value inserted. If target section designated by
1521−-- path is in a JSONB array, new_value will be inserted before target or after
1522−-- if insert_after is true (default is false). If target section designated by
1523−-- path is in JSONB object, new_value will be inserted only if target does not
1524−-- exist. As with the path orientated operators, negative integers that appear
1525−-- in path count from the end of JSON arrays.
1526−jsonbInsert
1527− :: Expression outer commons grp schemas params from (null 'PGjsonb)
1528− -> Expression outer commons grp schemas params from (null ('PGvararray ('NotNull 'PGtext)))
1529− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1530− -> Maybe (Expression outer commons grp schemas params from (null 'PGbool))
1531− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1532−jsonbInsert tgt path val insertAfter = case insertAfter of
1533− Just i -> unsafeFunctionN "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1534− Nothing -> unsafeFunctionN "jsonb_insert" (tgt :* path :* val :* Nil)
1535−
1536−-- | Returns its argument as indented JSON text.
1537−jsonbPretty :: null 'PGjsonb :--> null 'PGtext
1538−jsonbPretty = unsafeFunction "jsonb_pretty"
1539−
1540−(@@) :: Operator (null 'PGtsvector) (null 'PGtsquery) ('Null 'PGbool)
1541−(@@) = unsafeBinaryOp "@@"
1542−
1543−(.&) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1544−(.&) = unsafeBinaryOp "&&"
1545−
1546−(.|) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1547−(.|) = unsafeBinaryOp "||"
1548−
1549−(.!) :: null 'PGtsquery :--> null 'PGtsquery
1550−(.!) = unsafeUnaryOpL "!!"
1551−
1552−(<->) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1553−(<->) = unsafeBinaryOp "<->"
1554−
1555−arrayToTSvector
1556− :: null ('PGvararray ('NotNull 'PGtext))
1557− :--> null 'PGtsvector
1558−arrayToTSvector = unsafeFunction "array_to_tsvector"
1559−
1560−tsvectorLength :: null 'PGtsvector :--> null 'PGint4
1561−tsvectorLength = unsafeFunction "length"
1562−
1563−numnode :: null 'PGtsquery :--> null 'PGint4
1564−numnode = unsafeFunction "numnode"
1565−
1566−plainToTSquery :: null 'PGtext :--> null 'PGtsquery
1567−plainToTSquery = unsafeFunction "plainto_tsquery"
1568−
1569−phraseToTSquery :: null 'PGtext :--> null 'PGtsquery
1570−phraseToTSquery = unsafeFunction "phraseto_tsquery"
1571−
1572−websearchToTSquery :: null 'PGtext :--> null 'PGtsquery
1573−websearchToTSquery = unsafeFunction "websearch_to_tsquery"
1574−
1575−queryTree :: null 'PGtsquery :--> null 'PGtext
1576−queryTree = unsafeFunction "query_tree"
1577−
1578−toTSquery :: null 'PGtext :--> null 'PGtsquery
1579−toTSquery = unsafeFunction "to_tsquery"
1580−
1581−toTSvector
1582− :: ty `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1583− => null ty :--> null 'PGtsvector
1584−toTSvector = unsafeFunction "to_tsvector"
1585−
1586−setWeight
1587− :: FunctionN '[null 'PGtsvector, null ('PGchar 1)] (null 'PGtsvector)
1588−setWeight = unsafeFunctionN "set_weight"
1589−
1590−strip :: null 'PGtsvector :--> null 'PGtsvector
1591−strip = unsafeFunction "strip"
1592−
1593−jsonToTSvector :: FunctionN '[null 'PGjson, null 'PGjson] (null 'PGtsvector)
1594−jsonToTSvector = unsafeFunctionN "json_to_tsvector"
1595−
1596−jsonbToTSvector :: FunctionN '[null 'PGjsonb, null 'PGjsonb] (null 'PGtsvector)
1597−jsonbToTSvector = unsafeFunctionN "jsonb_to_tsvector"
1598−
1599−tsDelete :: FunctionN
1600− '[null 'PGtsvector, null ('PGvararray ('NotNull 'PGtext))]
1601− (null 'PGtsvector)
1602−tsDelete = unsafeFunctionN "ts_delete"
1603−
1604−tsFilter :: FunctionN
1605− '[null 'PGtsvector, null ('PGvararray ('NotNull ('PGchar 1)))]
1606− (null 'PGtsvector)
1607−tsFilter = unsafeFunctionN "ts_filter"
1608−
1609−tsHeadline
1610− :: document `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1611− => FunctionN '[null document, null 'PGtsquery] (null 'PGtext)
1612−tsHeadline = unsafeFunctionN "ts_headline"
1613−{-----------------------------------------
1614−aggregation
1615−-----------------------------------------}
1616−
1617−unsafeAggregateN
1618− :: SOP.SListI xs
1619− => ByteString -- ^ function
1620− -> Distinction (NP (Expression outer commons 'Ungrouped schemas params from)) xs
1621− -> Expression outer commons ('Grouped bys) schemas params from y
1622−unsafeAggregateN fun xs = UnsafeExpression $ fun <> parenthesized (renderSQL xs)
1623−
1624−{- |
1625−`Aggregate` functions compute a single result from a set of input values.
1626−`Aggregate` functions can be used as `GroupedBy` `Expression`s as well
1627−as `WindowFunction`s.
1628−-}
1629−class Aggregate expr1 exprN aggr
1630− | aggr -> expr1, aggr -> exprN where
1631−
1632− -- | A special aggregation that does not require an input
1633− --
1634− -- >>> :{
1635− -- let
1636− -- expression :: Expression '[] commons ('Grouped bys) schemas params from ('NotNull 'PGint8)
1637− -- expression = countStar
1638− -- in printSQL expression
1639− -- :}
1640− -- count(*)
1641− countStar :: aggr ('NotNull 'PGint8)
1642−
1643− -- | >>> :{
1644− -- let
1645− -- expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null ty]] ('NotNull 'PGint8)
1646− -- expression = count (All #col)
1647− -- in printSQL expression
1648− -- :}
1649− -- count(ALL "col")
1650− count
1651− :: expr1 ty
1652− -- ^ what to count
1653− -> aggr ('NotNull 'PGint8)
1654−
1655− -- | >>> :{
1656− -- let
1657− -- expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('NotNull 'PGnumeric)
1658− -- expression = sum_ (Distinct #col)
1659− -- in printSQL expression
1660− -- :}
1661− -- sum(DISTINCT "col")
1662− sum_
1663− :: ty `In` PGNum
1664− => expr1 (null ty)
1665− -> aggr ('NotNull ty)
1666−
1667− -- | input values, including nulls, concatenated into an array
1668− arrayAgg
1669− :: expr1 ty
1670− -> aggr ('Null ('PGvararray ty))
1671−
1672− -- | aggregates values as a JSON array
1673− jsonAgg
1674− :: expr1 ty
1675− -> aggr ('Null 'PGjson)
1676−
1677− -- | aggregates values as a JSON array
1678− jsonbAgg
1679− :: expr1 ty
1680− -> aggr ('Null 'PGjsonb)
1681−
1682− {- |
1683− the bitwise AND of all non-null input values, or null if none
1684− >>> :{
1685− let
1686− expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGint4]] ('Null 'PGint4)
1687− expression = bitAnd (Distinct #col)
1688− in printSQL expression
1689− :}
1690− bit_and(DISTINCT "col")
1691− -}
1692− bitAnd
1693− :: int `In` PGIntegral
1694− => expr1 (null int)
1695− -- ^ what to aggregate
1696− -> aggr ('Null int)
1697−
1698− {- |
1699− the bitwise OR of all non-null input values, or null if none
1700−
1701− >>> :{
1702− let
1703− expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGint4]] ('Null 'PGint4)
1704− expression = bitOr (All #col)
1705− in printSQL expression
1706− :}
1707− bit_or(ALL "col")
1708− -}
1709− bitOr
1710− :: int `In` PGIntegral
1711− => expr1 (null int)
1712− -- ^ what to aggregate
1713− -> aggr ('Null int)
1714−
1715− {- |
1716− true if all input values are true, otherwise false
1717−
1718− >>> :{
1719− let
1720− winFun :: WindowFunction '[] commons 'Ungrouped schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1721− winFun = boolAnd #col
1722− in printSQL winFun
1723− :}
1724− bool_and("col")
1725− -}
1726− boolAnd
1727− :: expr1 (null 'PGbool)
1728− -- ^ what to aggregate
1729− -> aggr ('Null 'PGbool)
1730−
1731− {- |
1732− true if at least one input value is true, otherwise false
1733−
1734− >>> :{
1735− let
1736− expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1737− expression = boolOr (All #col)
1738− in printSQL expression
1739− :}
1740− bool_or(ALL "col")
1741− -}
1742− boolOr
1743− :: expr1 (null 'PGbool)
1744− -- ^ what to aggregate
1745− -> aggr ('Null 'PGbool)
1746−
1747− {- |
1748− equivalent to `boolAnd`
1749−
1750− >>> :{
1751− let
1752− expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1753− expression = every (Distinct #col)
1754− in printSQL expression
1755− :}
1756− every(DISTINCT "col")
1757− -}
1758− every
1759− :: expr1 (null 'PGbool)
1760− -- ^ what to aggregate
1761− -> aggr ('Null 'PGbool)
1762−
1763− {- |maximum value of expression across all input values-}
1764− max_
1765− :: expr1 (null ty)
1766− -- ^ what to maximize
1767− -> aggr ('Null ty)
1768−
1769− -- | minimum value of expression across all input values
1770− min_
1771− :: expr1 (null ty)
1772− -- ^ what to minimize
1773− -> aggr ('Null ty)
1774−
1775− -- | the average (arithmetic mean) of all input values
1776− avg
1777− :: expr1 (null ty)
1778− -- ^ what to average
1779− -> aggr ('Null (PGAvg ty))
1780−
1781− {- | correlation coefficient
1782− >>> :{
1783− let
1784− expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1785− expression = corr (All (#y *: #x))
1786− in printSQL expression
1787− :}
1788− corr(ALL "y", "x")
1789− -}
1790− corr
1791− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1792− -> aggr ('Null 'PGfloat8)
1793−
1794− {- | population covariance
1795− >>> :{
1796− let
1797− expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1798− expression = covarPop (All (#y *: #x))
1799− in printSQL expression
1800− :}
1801− covar_pop(ALL "y", "x")
1802− -}
1803− covarPop
1804− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1805− -> aggr ('Null 'PGfloat8)
1806−
1807− {- | sample covariance
1808− >>> :{
1809− let
1810− winFun :: WindowFunction '[] c 'Ungrouped s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1811− winFun = covarSamp (#y *: #x)
1812− in printSQL winFun
1813− :}
1814− covar_samp("y", "x")
1815− -}
1816− covarSamp
1817− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1818− -> aggr ('Null 'PGfloat8)
1819−
1820− {- | average of the independent variable (sum(X)/N)
1821− >>> :{
1822− let
1823− expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1824− expression = regrAvgX (All (#y *: #x))
1825− in printSQL expression
1826− :}
1827− regr_avgx(ALL "y", "x")
1828− -}
1829− regrAvgX
1830− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1831− -> aggr ('Null 'PGfloat8)
1832−
1833− {- | average of the dependent variable (sum(Y)/N)
1834− >>> :{
1835− let
1836− winFun :: WindowFunction '[] c 'Ungrouped s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1837− winFun = regrAvgY (#y *: #x)
1838− in printSQL winFun
1839− :}
1840− regr_avgy("y", "x")
1841− -}
1842− regrAvgY
1843− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1844− -> aggr ('Null 'PGfloat8)
1845−
1846− {- | number of input rows in which both expressions are nonnull
1847− >>> :{
1848− let
1849− winFun :: WindowFunction '[] c 'Ungrouped s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGint8)
1850− winFun = regrCount (#y *: #x)
1851− in printSQL winFun
1852− :}
1853− regr_count("y", "x")
1854− -}
1855− regrCount
1856− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1857− -> aggr ('Null 'PGint8)
1858−
1859− {- | y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs
1860− >>> :{
1861− let
1862− expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1863− expression = regrIntercept (All (#y *: #x))
1864− in printSQL expression
1865− :}
1866− regr_intercept(ALL "y", "x")
1867− -}
1868− regrIntercept
1869− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1870− -> aggr ('Null 'PGfloat8)
1871−
1872− -- | @regr_r2(Y, X)@, square of the correlation coefficient
1873− regrR2
1874− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1875− -> aggr ('Null 'PGfloat8)
1876−
1877− -- | @regr_slope(Y, X)@, slope of the least-squares-fit linear equation
1878− -- determined by the (X, Y) pairs
1879− regrSlope
1880− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1881− -> aggr ('Null 'PGfloat8)
1882−
1883− -- | @regr_sxx(Y, X)@, sum(X^2) - sum(X)^2/N
1884− -- (“sum of squares” of the independent variable)
1885− regrSxx
1886− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1887− -> aggr ('Null 'PGfloat8)
1888−
1889− -- | @regr_sxy(Y, X)@, sum(X*Y) - sum(X) * sum(Y)/N
1890− -- (“sum of products” of independent times dependent variable)
1891− regrSxy
1892− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1893− -> aggr ('Null 'PGfloat8)
1894−
1895− -- | @regr_syy(Y, X)@, sum(Y^2) - sum(Y)^2/N
1896− -- (“sum of squares” of the dependent variable)
1897− regrSyy
1898− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1899− -> aggr ('Null 'PGfloat8)
1900−
1901− -- | historical alias for `stddevSamp`
1902− stddev
1903− :: expr1 (null ty)
1904− -> aggr ('Null (PGAvg ty))
1905−
1906− -- | population standard deviation of the input values
1907− stddevPop
1908− :: expr1 (null ty)
1909− -> aggr ('Null (PGAvg ty))
1910−
1911− -- | sample standard deviation of the input values
1912− stddevSamp
1913− :: expr1 (null ty)
1914− -> aggr ('Null (PGAvg ty))
1915−
1916− -- | historical alias for `varSamp`
1917− variance
1918− :: expr1 (null ty)
1919− -> aggr ('Null (PGAvg ty))
1920−
1921− -- | population variance of the input values
1922− -- (square of the population standard deviation)
1923− varPop
1924− :: expr1 (null ty)
1925− -> aggr ('Null (PGAvg ty))
1926−
1927− -- | sample variance of the input values
1928− -- (square of the sample standard deviation)
1929− varSamp
1930− :: expr1 (null ty)
1931− -> aggr ('Null (PGAvg ty))
1932−
1933−{- |
1934−`Distinction`s are used for the input of `Aggregate` `Expression`s.
1935−`All` invokes the aggregate once for each input row.
1936−`Distinct` invokes the aggregate once for each distinct value of the expression
1937−(or distinct set of values, for multiple expressions) found in the input
1938−-}
1939−data Distinction (expr :: kind -> Type) (ty :: kind)
1940− = All (expr ty)
1941− | Distinct (expr ty)
1942− deriving (GHC.Generic,Show,Eq,Ord)
1943−instance NFData (Distinction (Expression outer commons grp schemas params from) ty)
1944−instance RenderSQL (Distinction (Expression outer commons grp schemas params from) ty) where
1945− renderSQL = \case
1946− All x -> "ALL" <+> renderSQL x
1947− Distinct x -> "DISTINCT" <+> renderSQL x
1948−instance SOP.SListI tys => RenderSQL
1949− (Distinction (NP (Expression outer commons grp schemas params from)) tys) where
1950− renderSQL = \case
1951− All xs -> "ALL" <+> renderCommaSeparated renderSQL xs
1952− Distinct xs -> "DISTINCT" <+> renderCommaSeparated renderSQL xs
1953−
1954−instance Aggregate
1955− (Distinction (Expression outer commons 'Ungrouped schemas params from))
1956− (Distinction (NP (Expression outer commons 'Ungrouped schemas params from)))
1957− (Expression outer commons ('Grouped bys) schemas params from) where
1958− countStar = UnsafeExpression "count(*)"
1959− count = unsafeAggregate1 "count"
1960− sum_ = unsafeAggregate1 "sum"
1961− arrayAgg = unsafeAggregate1 "array_agg"
1962− jsonAgg = unsafeAggregate1 "json_agg"
1963− jsonbAgg = unsafeAggregate1 "jsonb_agg"
1964− bitAnd = unsafeAggregate1 "bit_and"
1965− bitOr = unsafeAggregate1 "bit_or"
1966− boolAnd = unsafeAggregate1 "bool_and"
1967− boolOr = unsafeAggregate1 "bool_or"
1968− every = unsafeAggregate1 "every"
1969− max_ = unsafeAggregate1 "max"
1970− min_ = unsafeAggregate1 "min"
1971− avg = unsafeAggregate1 "avg"
1972− corr = unsafeAggregateN "corr"
1973− covarPop = unsafeAggregateN "covar_pop"
1974− covarSamp = unsafeAggregateN "covar_samp"
1975− regrAvgX = unsafeAggregateN "regr_avgx"
1976− regrAvgY = unsafeAggregateN "regr_avgy"
1977− regrCount = unsafeAggregateN "regr_count"
1978− regrIntercept = unsafeAggregateN "regr_intercept"
1979− regrR2 = unsafeAggregateN "regr_r2"
1980− regrSlope = unsafeAggregateN "regr_slope"
1981− regrSxx = unsafeAggregateN "regr_sxx"
1982− regrSxy = unsafeAggregateN "regr_sxy"
1983− regrSyy = unsafeAggregateN "regr_syy"
1984− stddev = unsafeAggregate1 "stddev"
1985− stddevPop = unsafeAggregate1 "stddev_pop"
1986− stddevSamp = unsafeAggregate1 "stddev_samp"
1987− variance = unsafeAggregate1 "variance"
1988− varPop = unsafeAggregate1 "var_pop"
1989− varSamp = unsafeAggregate1 "var_samp"
1990−instance Aggregate
1991− (Expression outer commons grp schemas params from)
1992− (NP (Expression outer commons grp schemas params from))
1993− (WindowFunction outer commons grp schemas params from) where
1994− countStar = UnsafeWindowFunction "count(*)"
1995− count = unsafeWindowFunction1 "count"
1996− sum_ = unsafeWindowFunction1 "sum"
1997− arrayAgg = unsafeWindowFunction1 "array_agg"
1998− jsonAgg = unsafeWindowFunction1 "json_agg"
1999− jsonbAgg = unsafeWindowFunction1 "jsonb_agg"
2000− bitAnd = unsafeWindowFunction1 "bit_and"
2001− bitOr = unsafeWindowFunction1 "bit_or"
2002− boolAnd = unsafeWindowFunction1 "bool_and"
2003− boolOr = unsafeWindowFunction1 "bool_or"
2004− every = unsafeWindowFunction1 "every"
2005− max_ = unsafeWindowFunction1 "max"
2006− min_ = unsafeWindowFunction1 "min"
2007− avg = unsafeWindowFunction1 "avg"
2008− corr = unsafeWindowFunctionN "corr"
2009− covarPop = unsafeWindowFunctionN "covar_pop"
2010− covarSamp = unsafeWindowFunctionN "covar_samp"
2011− regrAvgX = unsafeWindowFunctionN "regr_avgx"
2012− regrAvgY = unsafeWindowFunctionN "regr_avgy"
2013− regrCount = unsafeWindowFunctionN "regr_count"
2014− regrIntercept = unsafeWindowFunctionN "regr_intercept"
2015− regrR2 = unsafeWindowFunctionN "regr_r2"
2016− regrSlope = unsafeWindowFunctionN "regr_slope"
2017− regrSxx = unsafeWindowFunctionN "regr_sxx"
2018− regrSxy = unsafeWindowFunctionN "regr_sxy"
2019− regrSyy = unsafeWindowFunctionN "regr_syy"
2020− stddev = unsafeWindowFunction1 "stddev"
2021− stddevPop = unsafeWindowFunction1 "stddev_pop"
2022− stddevSamp = unsafeWindowFunction1 "stddev_samp"
2023− variance = unsafeWindowFunction1 "variance"
2024− varPop = unsafeWindowFunction1 "var_pop"
2025− varSamp = unsafeWindowFunction1 "var_samp"
2026−
2027−-- | escape hatch to define aggregate functions
2028−unsafeAggregate1
2029− :: ByteString -- ^ aggregate function
2030− -> Distinction (Expression outer commons 'Ungrouped schemas params from) x
2031− -> Expression outer commons ('Grouped bys) schemas params from y
2032−unsafeAggregate1 fun x = UnsafeExpression $ fun <> parenthesized (renderSQL x)
2033−
2034−-- | A type family that calculates `PGAvg` type of a `PGType`.
2035−type family PGAvg ty where
2036− PGAvg 'PGint2 = 'PGnumeric
2037− PGAvg 'PGint4 = 'PGnumeric
2038− PGAvg 'PGint8 = 'PGnumeric
2039− PGAvg 'PGnumeric = 'PGnumeric
2040− PGAvg 'PGfloat4 = 'PGfloat8
2041− PGAvg 'PGfloat8 = 'PGfloat8
2042− PGAvg 'PGinterval = 'PGinterval
2043− PGAvg pg = TypeError
2044− ('Text "Squeal type error: No average for " ':<>: 'ShowType pg)
2045−
2046−{-----------------------------------------
2047−type expressions
2048−-----------------------------------------}
2049−
2050−-- | `TypeExpression`s are used in `cast`s and
2051−-- `Squeal.PostgreSQL.Definition.createTable` commands.
2052−newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
2053− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
2054− deriving (GHC.Generic,Show,Eq,Ord,NFData)
2055−instance RenderSQL (TypeExpression schemas ty) where
2056− renderSQL = renderTypeExpression
2057−
2058−-- | The enum or composite type in a `Typedef` can be expressed by its alias.
2059−typedef
2060− :: (Has sch schemas schema, Has td schema ('Typedef ty))
2061− => QualifiedAlias sch td
2062− -> TypeExpression schemas (null ty)
2063−typedef = UnsafeTypeExpression . renderSQL
2064−
2065−-- | The composite type corresponding to a `Table` definition can be expressed
2066−-- by its alias.
2067−typetable
2068− :: (Has sch schemas schema, Has tab schema ('Table table))
2069− => QualifiedAlias sch tab
2070− -> TypeExpression schemas (null ('PGcomposite (TableToRow table)))
2071−typetable = UnsafeTypeExpression . renderSQL
2072−
2073−-- | The composite type corresponding to a `View` definition can be expressed
2074−-- by its alias.
2075−typeview
2076− :: (Has sch schemas schema, Has vw schema ('View view))
2077− => QualifiedAlias sch vw
2078− -> TypeExpression schemas (null ('PGcomposite view))
2079−typeview = UnsafeTypeExpression . renderSQL
2080−
2081−-- | logical Boolean (true/false)
2082−bool :: TypeExpression schemas (null 'PGbool)
2083−bool = UnsafeTypeExpression "bool"
2084−-- | signed two-byte integer
2085−int2, smallint :: TypeExpression schemas (null 'PGint2)
2086−int2 = UnsafeTypeExpression "int2"
2087−smallint = UnsafeTypeExpression "smallint"
2088−-- | signed four-byte integer
2089−int4, int, integer :: TypeExpression schemas (null 'PGint4)
2090−int4 = UnsafeTypeExpression "int4"
2091−int = UnsafeTypeExpression "int"
2092−integer = UnsafeTypeExpression "integer"
2093−-- | signed eight-byte integer
2094−int8, bigint :: TypeExpression schemas (null 'PGint8)
2095−int8 = UnsafeTypeExpression "int8"
2096−bigint = UnsafeTypeExpression "bigint"
2097−-- | arbitrary precision numeric type
2098−numeric :: TypeExpression schemas (null 'PGnumeric)
2099−numeric = UnsafeTypeExpression "numeric"
2100−-- | single precision floating-point number (4 bytes)
2101−float4, real :: TypeExpression schemas (null 'PGfloat4)
2102−float4 = UnsafeTypeExpression "float4"
2103−real = UnsafeTypeExpression "real"
2104−-- | double precision floating-point number (8 bytes)
2105−float8, doublePrecision :: TypeExpression schemas (null 'PGfloat8)
2106−float8 = UnsafeTypeExpression "float8"
2107−doublePrecision = UnsafeTypeExpression "double precision"
2108−-- | currency amount
2109−money :: TypeExpression schema (null 'PGmoney)
2110−money = UnsafeTypeExpression "money"
2111−-- | variable-length character string
2112−text :: TypeExpression schemas (null 'PGtext)
2113−text = UnsafeTypeExpression "text"
2114−-- | fixed-length character string
2115−char, character
2116− :: forall n schemas null. (KnownNat n, 1 <= n)
2117− => TypeExpression schemas (null ('PGchar n))
2118−char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
2119−character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
2120−-- | variable-length character string
2121−varchar, characterVarying
2122− :: forall n schemas null. (KnownNat n, 1 <= n)
2123− => TypeExpression schemas (null ('PGvarchar n))
2124−varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
2125−characterVarying = UnsafeTypeExpression $
2126− "character varying(" <> renderNat @n <> ")"
2127−-- | binary data ("byte array")
2128−bytea :: TypeExpression schemas (null 'PGbytea)
2129−bytea = UnsafeTypeExpression "bytea"
2130−-- | date and time (no time zone)
2131−timestamp :: TypeExpression schemas (null 'PGtimestamp)
2132−timestamp = UnsafeTypeExpression "timestamp"
2133−-- | date and time, including time zone
2134−timestampWithTimeZone :: TypeExpression schemas (null 'PGtimestamptz)
2135−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
2136−-- | calendar date (year, month, day)
2137−date :: TypeExpression schemas (null 'PGdate)
2138−date = UnsafeTypeExpression "date"
2139−-- | time of day (no time zone)
2140−time :: TypeExpression schemas (null 'PGtime)
2141−time = UnsafeTypeExpression "time"
2142−-- | time of day, including time zone
2143−timeWithTimeZone :: TypeExpression schemas (null 'PGtimetz)
2144−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
2145−-- | time span
2146−interval :: TypeExpression schemas (null 'PGinterval)
2147−interval = UnsafeTypeExpression "interval"
2148−-- | universally unique identifier
2149−uuid :: TypeExpression schemas (null 'PGuuid)
2150−uuid = UnsafeTypeExpression "uuid"
2151−-- | IPv4 or IPv6 host address
2152−inet :: TypeExpression schemas (null 'PGinet)
2153−inet = UnsafeTypeExpression "inet"
2154−-- | textual JSON data
2155−json :: TypeExpression schemas (null 'PGjson)
2156−json = UnsafeTypeExpression "json"
2157−-- | binary JSON data, decomposed
2158−jsonb :: TypeExpression schemas (null 'PGjsonb)
2159−jsonb = UnsafeTypeExpression "jsonb"
2160−-- | variable length array
2161−vararray
2162− :: TypeExpression schemas pg
2163− -> TypeExpression schemas (null ('PGvararray pg))
2164−vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
2165−-- | fixed length array
2166−--
2167−-- >>> renderSQL (fixarray @'[2] json)
2168−-- "json[2]"
2169−fixarray
2170− :: forall dims schemas null pg. SOP.All KnownNat dims
2171− => TypeExpression schemas pg
2172− -> TypeExpression schemas (null ('PGfixarray dims pg))
2173−fixarray ty = UnsafeTypeExpression $
2174− renderSQL ty <> renderDims @dims
2175− where
2176− renderDims :: forall ns. SOP.All KnownNat ns => ByteString
2177− renderDims =
2178− ("[" <>)
2179− . (<> "]")
2180− . ByteString.intercalate "]["
2181− . hcollapse
2182− $ hcmap (SOP.Proxy @KnownNat)
2183− (K . fromString . show . natVal)
2184− (hpure SOP.Proxy :: NP SOP.Proxy ns)
2185−tsvector :: TypeExpression schemas (null 'PGtsvector)
2186−tsvector = UnsafeTypeExpression "tsvector"
2187−tsquery :: TypeExpression schemas (null 'PGtsquery)
2188−tsquery = UnsafeTypeExpression "tsquery"
2189−
2190−-- | `pgtype` is a demoted version of a `PGType`
2191−class PGTyped schemas (ty :: NullityType) where
2192− pgtype :: TypeExpression schemas ty
2193−instance PGTyped schemas (null 'PGbool) where pgtype = bool
2194−instance PGTyped schemas (null 'PGint2) where pgtype = int2
2195−instance PGTyped schemas (null 'PGint4) where pgtype = int4
2196−instance PGTyped schemas (null 'PGint8) where pgtype = int8
2197−instance PGTyped schemas (null 'PGnumeric) where pgtype = numeric
2198−instance PGTyped schemas (null 'PGfloat4) where pgtype = float4
2199−instance PGTyped schemas (null 'PGfloat8) where pgtype = float8
2200−instance PGTyped schemas (null 'PGmoney) where pgtype = money
2201−instance PGTyped schemas (null 'PGtext) where pgtype = text
2202−instance (KnownNat n, 1 <= n)
2203− => PGTyped schemas (null ('PGchar n)) where pgtype = char @n
2204−instance (KnownNat n, 1 <= n)
2205− => PGTyped schemas (null ('PGvarchar n)) where pgtype = varchar @n
2206−instance PGTyped schemas (null 'PGbytea) where pgtype = bytea
2207−instance PGTyped schemas (null 'PGtimestamp) where pgtype = timestamp
2208−instance PGTyped schemas (null 'PGtimestamptz) where pgtype = timestampWithTimeZone
2209−instance PGTyped schemas (null 'PGdate) where pgtype = date
2210−instance PGTyped schemas (null 'PGtime) where pgtype = time
2211−instance PGTyped schemas (null 'PGtimetz) where pgtype = timeWithTimeZone
2212−instance PGTyped schemas (null 'PGinterval) where pgtype = interval
2213−instance PGTyped schemas (null 'PGuuid) where pgtype = uuid
2214−instance PGTyped schemas (null 'PGjson) where pgtype = json
2215−instance PGTyped schemas (null 'PGjsonb) where pgtype = jsonb
2216−instance PGTyped schemas ty
2217− => PGTyped schemas (null ('PGvararray ty)) where
2218− pgtype = vararray (pgtype @schemas @ty)
2219−instance (SOP.All KnownNat dims, PGTyped schemas ty)
2220− => PGTyped schemas (null ('PGfixarray dims ty)) where
2221− pgtype = fixarray @dims (pgtype @schemas @ty)
2222−instance PGTyped schemas (null 'PGtsvector) where pgtype = tsvector
2223−instance PGTyped schemas (null 'PGtsquery) where pgtype = tsquery
2224−
2225−{-----------------------------------------
2226−Sorting
2227−-----------------------------------------}
2228−
2229−-- | `SortExpression`s are used by `orderBy` to optionally sort the results
2230−-- of a `Squeal.PostgreSQL.Query.Query`. `Asc` or `Desc`
2231−-- set the sort direction of a `NotNull` result
2232−-- column to ascending or descending. Ascending order puts smaller values
2233−-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
2234−-- descending order is determined with the `.>` operator. `AscNullsFirst`,
2235−-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
2236−-- determine whether nulls appear before or after non-null values in the sort
2237−-- ordering of a `Null` result column.
2238−data SortExpression outer commons grp schemas params from where
2239− Asc
2240− :: Expression outer commons grp schemas params from ('NotNull ty)
2241− -> SortExpression outer commons grp schemas params from
2242− Desc
2243− :: Expression outer commons grp schemas params from ('NotNull ty)
2244− -> SortExpression outer commons grp schemas params from
2245− AscNullsFirst
2246− :: Expression outer commons grp schemas params from ('Null ty)
2247− -> SortExpression outer commons grp schemas params from
2248− AscNullsLast
2249− :: Expression outer commons grp schemas params from ('Null ty)
2250− -> SortExpression outer commons grp schemas params from
2251− DescNullsFirst
2252− :: Expression outer commons grp schemas params from ('Null ty)
2253− -> SortExpression outer commons grp schemas params from
2254− DescNullsLast
2255− :: Expression outer commons grp schemas params from ('Null ty)
2256− -> SortExpression outer commons grp schemas params from
2257−deriving instance Show (SortExpression outer commons grp schemas params from)
2258−
2259−{- |
2260−The `orderBy` clause causes the result rows of a `Squeal.PostgreSQL.Query.TableExpression`
2261−to be sorted according to the specified `SortExpression`(s).
2262−If two rows are equal according to the leftmost expression,
2263−they are compared according to the next expression and so on.
2264−If they are equal according to all specified expressions,
2265−they are returned in an implementation-dependent order.
2266−
2267−You can also control the order in which rows are processed by window functions
2268−using `orderBy` within `Squeal.PostgreSQL.Query.Over`.
2269−-}
2270−class OrderBy expr where
2271− orderBy
2272− :: [SortExpression outer commons grp schemas params from]
2273− -> expr outer commons grp schemas params from
2274− -> expr outer commons grp schemas params from
2275−
2276−-- | Render a `SortExpression`.
2277−instance RenderSQL (SortExpression outer commons grp schemas params from) where
2278− renderSQL = \case
2279− Asc expression -> renderSQL expression <+> "ASC"
2280− Desc expression -> renderSQL expression <+> "DESC"
2281− AscNullsFirst expression -> renderSQL expression
2282− <+> "ASC NULLS FIRST"
2283− DescNullsFirst expression -> renderSQL expression
2284− <+> "DESC NULLS FIRST"
2285− AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
2286− DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
2287−
2288−-- | A `WindowDefinition` is a set of table rows that are somehow related
2289−-- to the current row
2290−data WindowDefinition outer commons grp schemas params from where
2291− WindowDefinition
2292− :: SListI bys
2293− => NP (Expression outer commons grp schemas params from) bys
2294− -> [SortExpression outer commons grp schemas params from]
2295− -> WindowDefinition outer commons grp schemas params from
2296−
2297−instance OrderBy WindowDefinition where
2298− orderBy sortsR (WindowDefinition parts sortsL)
2299− = WindowDefinition parts (sortsL ++ sortsR)
2300−
2301−instance RenderSQL (WindowDefinition outer commons schemas from grp params) where
2302− renderSQL (WindowDefinition part ord) =
2303− renderPartitionByClause part <> renderOrderByClause ord
2304− where
2305− renderPartitionByClause = \case
2306− Nil -> ""
2307− parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
2308− renderOrderByClause = \case
2309− [] -> ""
2310− srts -> " ORDER" <+> "BY"
2311− <+> commaSeparated (renderSQL <$> srts)
2312−
2313−{- |
2314−The `partitionBy` clause within `Squeal.PostgreSQL.Query.Over` divides the rows into groups,
2315−or partitions, that share the same values of the `partitionBy` `Expression`(s).
2316−For each row, the window function is computed across the rows that fall into
2317−the same partition as the current row.
2318−-}
2319−partitionBy
2320− :: SListI bys
2321− => NP (Expression outer commons grp schemas params from) bys
2322− -> WindowDefinition outer commons grp schemas params from
2323−partitionBy bys = WindowDefinition bys []
2324−
2325−{- |
2326−A window function performs a calculation across a set of table rows
2327−that are somehow related to the current row. This is comparable to the type
2328−of calculation that can be done with an aggregate function.
2329−However, window functions do not cause rows to become grouped into a single
2330−output row like non-window aggregate calls would.
2331−Instead, the rows retain their separate identities.
2332−Behind the scenes, the window function is able to access more than
2333−just the current row of the query result.
2334−-}
2335−newtype WindowFunction
2336− (outer :: FromType)
2337− (commons :: FromType)
2338− (grp :: Grouping)
2339− (schemas :: SchemasType)
2340− (params :: [NullityType])
2341− (from :: FromType)
2342− (ty :: NullityType)
2343− = UnsafeWindowFunction { renderWindowFunction :: ByteString }
2344− deriving (GHC.Generic,Show,Eq,Ord,NFData)
2345−
2346−instance RenderSQL (WindowFunction outer commons grp schemas params from ty) where
2347− renderSQL = renderWindowFunction
2348−
2349−type WinFun0 x
2350− = forall outer commons grp schemas params from
2351− . WindowFunction outer commons grp schemas params from x
2352− -- ^ cannot reference aliases
2353−
2354−type WinFun1 x y
2355− = forall outer commons grp schemas params from
2356− . Expression outer commons grp schemas params from x
2357− -- ^ input
2358− -> WindowFunction outer commons grp schemas params from y
2359− -- ^ output
2360−
2361−type WinFunN xs y
2362− = forall outer commons grp schemas params from
2363− . NP (Expression outer commons grp schemas params from) xs
2364− -- ^ inputs
2365− -> WindowFunction outer commons grp schemas params from y
2366− -- ^ output
2367−
2368−unsafeWindowFunction1 :: ByteString -> WinFun1 x y
2369−unsafeWindowFunction1 fun x
2370− = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x)
2371−
2372−unsafeWindowFunctionN :: SOP.SListI xs => ByteString -> WinFunN xs y
2373−unsafeWindowFunctionN fun xs = UnsafeWindowFunction $ fun <>
2374− parenthesized (renderCommaSeparated renderSQL xs)
2375−
2376−{- | rank of the current row with gaps; same as `rowNumber` of its first peer
2377−>>> printSQL rank
2378−rank()
2379−-}
2380−rank :: WinFun0 ('NotNull 'PGint8)
2381−rank = UnsafeWindowFunction "rank()"
2382−
2383−{- | number of the current row within its partition, counting from 1
2384−>>> printSQL rowNumber
2385−row_number()
2386−-}
2387−rowNumber :: WinFun0 ('NotNull 'PGint8)
2388−rowNumber = UnsafeWindowFunction "row_number()"
2389−
2390−{- | rank of the current row without gaps; this function counts peer groups
2391−>>> printSQL denseRank
2392−dense_rank()
2393−-}
2394−denseRank :: WinFun0 ('NotNull 'PGint8)
2395−denseRank = UnsafeWindowFunction "dense_rank()"
2396−
2397−{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
2398−>>> printSQL percentRank
2399−percent_rank()
2400−-}
2401−percentRank :: WinFun0 ('NotNull 'PGfloat8)
2402−percentRank = UnsafeWindowFunction "percent_rank()"
2403−
2404−{- | cumulative distribution: (number of partition rows
2405−preceding or peer with current row) / total partition rows
2406−>>> printSQL cumeDist
2407−cume_dist()
2408−-}
2409−cumeDist :: WinFun0 ('NotNull 'PGfloat8)
2410−cumeDist = UnsafeWindowFunction "cume_dist()"
2411−
2412−{- | integer ranging from 1 to the argument value,
2413−dividing the partition as equally as possible
2414−-}
2415−ntile :: WinFun1 ('NotNull 'PGint4) ('NotNull 'PGint4)
2416−ntile = unsafeWindowFunction1 "ntile"
2417−
2418−{- | returns value evaluated at the row that is offset rows before the current
2419−row within the partition; if there is no such row, instead return default
2420−(which must be of the same type as value). Both offset and default are
2421−evaluated with respect to the current row.
2422−-}
2423−lag :: WinFunN '[ty, 'NotNull 'PGint4, ty] ty
2424−lag = unsafeWindowFunctionN "lag"
2425−
2426−{- | returns value evaluated at the row that is offset rows after the current
2427−row within the partition; if there is no such row, instead return default
2428−(which must be of the same type as value). Both offset and default are
2429−evaluated with respect to the current row.
2430−-}
2431−lead :: WinFunN '[ty, 'NotNull 'PGint4, ty] ty
2432−lead = unsafeWindowFunctionN "lag"
2433−
2434−{- | returns value evaluated at the row that is the
2435−first row of the window frame
2436−-}
2437−firstValue :: WinFun1 ty ty
2438−firstValue = unsafeWindowFunction1 "first_value"
2439−
2440−{- | returns value evaluated at the row that is the
2441−last row of the window frame
2442−-}
2443−lastValue :: WinFun1 ty ty
2444−lastValue = unsafeWindowFunction1 "last_value"
2445−
2446−{- | returns value evaluated at the row that is the nth
2447−row of the window frame (counting from 1); null if no such row
2448−-}
2449−nthValue :: WinFunN '[null ty, 'NotNull 'PGint4] ('Null ty)
2450−nthValue = unsafeWindowFunctionN "nth_value"
2451−
2452−{-|
2453−Create date from year, month and day fields
2454−
2455−>>> printSQL (makeDate (1984 :* 7 *: 3))
2456−make_date(1984, 7, 3)
2457−-}
2458−makeDate :: FunctionN
2459− '[ null 'PGint4, null 'PGint4, null 'PGint4 ]
2460− ( null 'PGdate )
2461−makeDate = unsafeFunctionN "make_date"
2462−
2463−{-|
2464−Create time from hour, minute and seconds fields
2465−
2466−>>> printSQL (makeTime (8 :* 15 *: 23.5))
2467−make_time(8, 15, 23.5)
2468−-}
2469−makeTime :: FunctionN
2470− '[ null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2471− ( null 'PGtime )
2472−makeTime = unsafeFunctionN "make_time"
2473−
2474−{-|
2475−Create timestamp from year, month, day, hour, minute and seconds fields
2476−
2477−>>> printSQL (makeTimestamp (2013 :* 7 :* 15 :* 8 :* 15 *: 23.5))
2478−make_timestamp(2013, 7, 15, 8, 15, 23.5)
2479−-}
2480−makeTimestamp :: FunctionN
2481− '[ null 'PGint4, null 'PGint4, null 'PGint4
2482− , null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2483− ( null 'PGtimestamp )
2484−makeTimestamp = unsafeFunctionN "make_timestamp"
2485−
2486−{-|
2487−Create timestamp with time zone from
2488−year, month, day, hour, minute and seconds fields;
2489−the current time zone is used
2490−
2491−>>> printSQL (makeTimestamptz (2013 :* 7 :* 15 :* 8 :* 15 *: 23.5))
2492−make_timestamptz(2013, 7, 15, 8, 15, 23.5)
2493−-}
2494−makeTimestamptz :: FunctionN
2495− '[ null 'PGint4, null 'PGint4, null 'PGint4
2496− , null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2497− ( null 'PGtimestamptz )
2498−makeTimestamptz = unsafeFunctionN "make_timestamptz"
2499−
2500−{-|
2501−Affine space operations on time types.
2502−-}
2503−class TimeOp time diff | time -> diff where
2504− {-|
2505− >>> printSQL (makeDate (1984 :* 7 *: 3) !+ 365)
2506− (make_date(1984, 7, 3) + 365)
2507− -}
2508− (!+) :: Operator (null time) (null diff) (null time)
2509− (!+) = unsafeBinaryOp "+"
2510− {-|
2511− >>> printSQL (365 +! makeDate (1984 :* 7 *: 3))
2512− (365 + make_date(1984, 7, 3))
2513− -}
2514− (+!) :: Operator (null diff) (null time) (null time)
2515− (+!) = unsafeBinaryOp "+"
2516− {-|
2517− >>> printSQL (makeDate (1984 :* 7 *: 3) !- 365)
2518− (make_date(1984, 7, 3) - 365)
2519− -}
2520− (!-) :: Operator (null time) (null diff) (null time)
2521− (!-) = unsafeBinaryOp "-"
2522− {-|
2523− >>> printSQL (makeDate (1984 :* 7 *: 3) !-! currentDate)
2524− (make_date(1984, 7, 3) - CURRENT_DATE)
2525− -}
2526− (!-!) :: Operator (null time) (null time) (null diff)
2527− (!-!) = unsafeBinaryOp "-"
2528−instance TimeOp 'PGtimestamp 'PGinterval
2529−instance TimeOp 'PGtimestamptz 'PGinterval
2530−instance TimeOp 'PGtime 'PGinterval
2531−instance TimeOp 'PGtimetz 'PGinterval
2532−instance TimeOp 'PGinterval 'PGinterval
2533−instance TimeOp 'PGdate 'PGint4
2534−infixl 6 !+
2535−infixl 6 +!
2536−infixl 6 !-
2537−infixl 6 !-!
2538−
2539−data TimeUnit
2540− = Years | Months | Weeks | Days
2541− | Hours | Minutes | Seconds
2542− | Microseconds | Milliseconds
2543− | Decades | Centuries | Millennia
2544− deriving (Eq, Ord, Show, Read, Enum, GHC.Generic)
2545−instance SOP.Generic TimeUnit
2546−instance SOP.HasDatatypeInfo TimeUnit
2547−instance RenderSQL TimeUnit where
2548− renderSQL = \case
2549− Years -> "years"
2550− Months -> "months"
2551− Weeks -> "weeks"
2552− Days -> "days"
2553− Hours -> "hours"
2554− Minutes -> "minutes"
2555− Seconds -> "seconds"
2556− Microseconds -> "microseconds"
2557− Milliseconds -> "milliseconds"
2558− Decades -> "decades"
2559− Centuries -> "centuries"
2560− Millennia -> "millennia"
2561−
2562−-- | >>> printSQL $ interval_ 7 Days
2563−-- (INTERVAL '7.0 days')
2564−interval_ :: Double -> TimeUnit -> Expr (null 'PGinterval)
2565−interval_ num unit = UnsafeExpression . parenthesized $ "INTERVAL" <+>
2566− "'" <> fromString (show num) <+> renderSQL unit <> "'"
2567−
2568−class Literal hask where
2569− literal :: hask -> Expr (null (PG hask))
2570−instance JSON.ToJSON hask => Literal (Json hask) where
2571− literal = cast json . UnsafeExpression
2572− . singleQuotedUtf8 . toStrict . JSON.encode . getJson
2573−instance JSON.ToJSON hask => Literal (Jsonb hask) where
2574− literal = cast jsonb . UnsafeExpression
2575− . singleQuotedUtf8 . toStrict . JSON.encode . getJsonb
2576−instance Literal Char where
2577− literal chr = UnsafeExpression $
2578− "E\'" <> fromString (escape chr) <> "\'"
2579−instance Literal String where literal = fromString
2580−instance Literal Int16 where literal = fromIntegral
2581−instance Literal Int32 where literal = fromIntegral
2582−instance Literal Int64 where literal = fromIntegral
2583−instance Literal Float where literal = fromRational . toRational
2584−instance Literal Double where literal = fromRational . toRational
2585−instance Literal Text where literal = fromString . Text.unpack
2586−instance Literal Lazy.Text where literal = fromString . Lazy.Text.unpack
2587−instance ToParam (Enumerated enum) (PG (Enumerated enum))
2588− => Literal (Enumerated enum) where
2589− literal
2590− = UnsafeExpression
2591− . singleQuotedUtf8
2592− . builderBytes
2593− . unK
2594− . toParam @(Enumerated enum) @(PG (Enumerated enum))