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