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