@@ -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,7 +91,7 @@ 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,
@@ -301,11 +101,12 @@ 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,242 +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)
737317unsafeBinaryOp :: 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 -> 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 -> 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 -> 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 :: SListI xs => ByteString -> FunctionN xs y
366+unsafeFunctionN :: SListI xs => ByteString -> xs ---> y
760367unsafeFunctionN fun xs = UnsafeExpression $
761368 fun <> parenthesized (renderCommaSeparated renderSQL xs)
762369
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+
763378instance ty `In` PGNum
764379 => Num (Expression outer commons grp schemas params from (null ty)) where
765380 (+) = unsafeBinaryOp "+"
@@ -804,364 +419,22 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
804419 acosh x = log (x + sqrt (x*x - 1))
805420 atanh x = log ((1 + x) / (1 - x)) / 2
806421
807−-- | >>> :{
808−-- let
809−-- expression :: Expr (null 'PGfloat4)
810−-- expression = atan2_ (pi *: 2)
811−-- in printSQL expression
812−-- :}
813−-- atan2(pi(), 2)
814−atan2_
815− :: float `In` PGFloating
816− => FunctionN '[ null float, null float] (null float)
817−atan2_ = unsafeFunctionN "atan2"
818−
819−-- When a `cast` is applied to an `Expression` of a known type, it
820−-- represents a run-time type conversion. The cast will succeed only if a
821−-- suitable type conversion operation has been defined.
822−--
823−-- | >>> printSQL $ true & cast int4
824−-- (TRUE :: int4)
825−cast
826− :: TypeExpression schemas ty1
827− -- ^ type to cast as
828− -> Expression outer commons grp schemas params from ty0
829− -- ^ value to convert
830− -> Expression outer commons grp schemas params from ty1
831−cast ty x = UnsafeExpression $ parenthesized $
832− renderSQL x <+> "::" <+> renderSQL ty
833−
834−-- | integer division, truncates the result
835−--
836−-- >>> :{
837−-- let
838−-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
839−-- expression = 5 `quot_` 2
840−-- in printSQL expression
841−-- :}
842−-- (5 / 2)
843−quot_
844− :: int `In` PGIntegral
845− => Operator (null int) (null int) (null int)
846−quot_ = unsafeBinaryOp "/"
847−
848−-- | remainder upon integer division
849−--
850−-- >>> :{
851−-- let
852−-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
853−-- expression = 5 `rem_` 2
854−-- in printSQL expression
855−-- :}
856−-- (5 % 2)
857−rem_
858− :: int `In` PGIntegral
859− => Operator (null int) (null int) (null int)
860−rem_ = unsafeBinaryOp "%"
861−
862−-- | >>> :{
863−-- let
864−-- expression :: Expression outer commons grp schemas params from (null 'PGfloat4)
865−-- expression = trunc pi
866−-- in printSQL expression
867−-- :}
868−-- trunc(pi())
869−trunc :: frac `In` PGFloating => null frac :--> null frac
870−trunc = unsafeFunction "trunc"
871−
872−-- | >>> :{
873−-- let
874−-- expression :: Expression outer commons grp schemas params from (null 'PGfloat4)
875−-- expression = round_ pi
876−-- in printSQL expression
877−-- :}
878−-- round(pi())
879−round_ :: frac `In` PGFloating => null frac :--> null frac
880−round_ = unsafeFunction "round"
881−
882−-- | >>> :{
883−-- let
884−-- expression :: Expression outer commons grp schemas params from (null 'PGfloat4)
885−-- expression = ceiling_ pi
886−-- in printSQL expression
887−-- :}
888−-- ceiling(pi())
889−ceiling_ :: frac `In` PGFloating => null frac :--> null frac
890−ceiling_ = unsafeFunction "ceiling"
891−
892−-- | A `Condition` is an `Expression`, which can evaluate
893−-- to `true`, `false` or `null_`. This is because SQL uses
894−-- a three valued logic.
895−type Condition outer commons grp schemas params from =
896− Expression outer commons grp schemas params from ('Null 'PGbool)
897−
898−-- | >>> printSQL true
899−-- TRUE
900−true :: Expr (null 'PGbool)
901−true = UnsafeExpression "TRUE"
902−
903−-- | >>> printSQL false
904−-- FALSE
905−false :: Expr (null 'PGbool)
906−false = UnsafeExpression "FALSE"
907−
908−-- | >>> printSQL $ not_ true
909−-- (NOT TRUE)
910−not_ :: null 'PGbool :--> null 'PGbool
911−not_ = unsafeUnaryOpL "NOT"
912−
913−-- | >>> printSQL $ true .&& false
914−-- (TRUE AND FALSE)
915−(.&&) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
916−infixr 3 .&&
917−(.&&) = unsafeBinaryOp "AND"
918−
919−-- | >>> printSQL $ true .|| false
920−-- (TRUE OR FALSE)
921−(.||) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
922−infixr 2 .||
923−(.||) = unsafeBinaryOp "OR"
924−
925−-- | >>> :{
926−-- let
927−-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
928−-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
929−-- in printSQL expression
930−-- :}
931−-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
932−caseWhenThenElse
933− :: [ ( Condition outer commons grp schemas params from
934− , Expression outer commons grp schemas params from ty
935− ) ]
936− -- ^ whens and thens
937− -> Expression outer commons grp schemas params from ty
938− -- ^ else
939− -> Expression outer commons grp schemas params from ty
940−caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
941− [ "CASE"
942− , mconcat
943− [ mconcat
944− [ " WHEN ", renderSQL when_
945− , " THEN ", renderSQL then_
946− ]
947− | (when_,then_) <- whenThens
948− ]
949− , " ELSE ", renderSQL else_
950− , " END"
951− ]
952−
953−-- | >>> :{
954−-- let
955−-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
956−-- expression = ifThenElse true 1 0
957−-- in printSQL expression
958−-- :}
959−-- CASE WHEN TRUE THEN 1 ELSE 0 END
960−ifThenElse
961− :: Condition outer commons grp schemas params from
962− -> Expression outer commons grp schemas params from ty -- ^ then
963− -> Expression outer commons grp schemas params from ty -- ^ else
964− -> Expression outer commons grp schemas params from ty
965−ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
966−
967−-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
968−-- will produce @NULL@s if one of their arguments is @NULL@.
969−--
970−-- >>> printSQL $ true .== null_
971−-- (TRUE = NULL)
972−(.==) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
973−(.==) = unsafeBinaryOp "="
974−infix 4 .==
975−
976−-- | >>> printSQL $ true ./= null_
977−-- (TRUE <> NULL)
978−(./=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
979−(./=) = unsafeBinaryOp "<>"
980−infix 4 ./=
981−
982−-- | >>> printSQL $ true .>= null_
983−-- (TRUE >= NULL)
984−(.>=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
985−(.>=) = unsafeBinaryOp ">="
986−infix 4 .>=
987−
988−-- | >>> printSQL $ true .< null_
989−-- (TRUE < NULL)
990−(.<) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
991−(.<) = unsafeBinaryOp "<"
992−infix 4 .<
993−
994−-- | >>> printSQL $ true .<= null_
995−-- (TRUE <= NULL)
996−(.<=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
997−(.<=) = unsafeBinaryOp "<="
998−infix 4 .<=
999−
1000−-- | >>> printSQL $ true .> null_
1001−-- (TRUE > NULL)
1002−(.>) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
1003−(.>) = unsafeBinaryOp ">"
1004−infix 4 .>
1005−
1006−{- | >>> printSQL $ true `between` (null_, false)
1007−TRUE BETWEEN NULL AND FALSE
1008−-}
1009−between
1010− :: Expression outer commons grp schemas params from (null ty)
1011− -> ( Expression outer commons grp schemas params from (null ty)
1012− , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1013− -> Condition outer commons grp schemas params from
1014−between a (x,y) = UnsafeExpression $ renderSQL a <+> "BETWEEN"
1015− <+> renderSQL x <+> "AND" <+> renderSQL y
1016−
1017−{- | >>> printSQL $ true `notBetween` (null_, false)
1018−TRUE NOT BETWEEN NULL AND FALSE
1019−-}
1020−notBetween
1021− :: Expression outer commons grp schemas params from (null ty)
1022− -> ( Expression outer commons grp schemas params from (null ty)
1023− , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1024− -> Condition outer commons grp schemas params from
1025−notBetween a (x,y) = UnsafeExpression $ renderSQL a <+> "NOT BETWEEN"
1026− <+> renderSQL x <+> "AND" <+> renderSQL y
1027−
1028−{- | between, after sorting the comparison values
1029−
1030−>>> printSQL $ true `betweenSymmetric` (null_, false)
1031−TRUE BETWEEN SYMMETRIC NULL AND FALSE
1032−-}
1033−betweenSymmetric
1034− :: Expression outer commons grp schemas params from (null ty)
1035− -> ( Expression outer commons grp schemas params from (null ty)
1036− , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1037− -> Condition outer commons grp schemas params from
1038−betweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
1039− <+> "BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
1040−
1041−{- | not between, after sorting the comparison values
1042−
1043−>>> printSQL $ true `notBetweenSymmetric` (null_, false)
1044−TRUE NOT BETWEEN SYMMETRIC NULL AND FALSE
1045−-}
1046−notBetweenSymmetric
1047− :: Expression outer commons grp schemas params from (null ty)
1048− -> ( Expression outer commons grp schemas params from (null ty)
1049− , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1050− -> Condition outer commons grp schemas params from
1051−notBetweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
1052− <+> "NOT BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
1053−
1054−{- | not equal, treating null like an ordinary value
1055−
1056−>>> printSQL $ true `isDistinctFrom` null_
1057−(TRUE IS DISTINCT FROM NULL)
1058−-}
1059−isDistinctFrom :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
1060−isDistinctFrom = unsafeBinaryOp "IS DISTINCT FROM"
1061−
1062−{- | equal, treating null like an ordinary value
1063−
1064−>>> printSQL $ true `isNotDistinctFrom` null_
1065−(TRUE IS NOT DISTINCT FROM NULL)
1066−-}
1067−isNotDistinctFrom :: Operator (null0 ty) (null1 ty) ('NotNull 'PGbool)
1068−isNotDistinctFrom = unsafeBinaryOp "IS NOT DISTINCT FROM"
1069−
1070−{- | is true
1071−
1072−>>> printSQL $ true & isTrue
1073−(TRUE IS TRUE)
1074−-}
1075−isTrue :: null0 'PGbool :--> null1 'PGbool
1076−isTrue = unsafeUnaryOpR "IS TRUE"
1077−
1078−{- | is false or unknown
1079−
1080−>>> printSQL $ true & isNotTrue
1081−(TRUE IS NOT TRUE)
1082−-}
1083−isNotTrue :: null0 'PGbool :--> null1 'PGbool
1084−isNotTrue = unsafeUnaryOpR "IS NOT TRUE"
1085−
1086−{- | is false
1087−
1088−>>> printSQL $ true & isFalse
1089−(TRUE IS FALSE)
1090−-}
1091−isFalse :: null0 'PGbool :--> null1 'PGbool
1092−isFalse = unsafeUnaryOpR "IS FALSE"
1093−
1094−{- | is true or unknown
1095−
1096−>>> printSQL $ true & isNotFalse
1097−(TRUE IS NOT FALSE)
1098−-}
1099−isNotFalse :: null0 'PGbool :--> null1 'PGbool
1100−isNotFalse = unsafeUnaryOpR "IS NOT FALSE"
1101−
1102−{- | is unknown
1103−
1104−>>> printSQL $ true & isUnknown
1105−(TRUE IS UNKNOWN)
1106−-}
1107−isUnknown :: null0 'PGbool :--> null1 'PGbool
1108−isUnknown = unsafeUnaryOpR "IS UNKNOWN"
1109−
1110−{- | is true or false
1111−
1112−>>> printSQL $ true & isNotUnknown
1113−(TRUE IS NOT UNKNOWN)
1114−-}
1115−isNotUnknown :: null0 'PGbool :--> null1 'PGbool
1116−isNotUnknown = unsafeUnaryOpR "IS NOT UNKNOWN"
1117−
1118−-- | >>> printSQL currentDate
1119−-- CURRENT_DATE
1120−currentDate :: Expr (null 'PGdate)
1121−currentDate = UnsafeExpression "CURRENT_DATE"
1122−
1123−-- | >>> printSQL currentTime
1124−-- CURRENT_TIME
1125−currentTime :: Expr (null 'PGtimetz)
1126−currentTime = UnsafeExpression "CURRENT_TIME"
1127−
1128−-- | >>> printSQL currentTimestamp
1129−-- CURRENT_TIMESTAMP
1130−currentTimestamp :: Expr (null 'PGtimestamptz)
1131−currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
1132−
1133−-- | >>> printSQL localTime
1134−-- LOCALTIME
1135−localTime :: Expr (null 'PGtime)
1136−localTime = UnsafeExpression "LOCALTIME"
1137−
1138−-- | >>> printSQL localTimestamp
1139−-- LOCALTIMESTAMP
1140−localTimestamp :: Expr (null 'PGtimestamp)
1141−localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
1142−
1143−-- | Current date and time (equivalent to `currentTimestamp`)
1144−--
1145−-- >>> printSQL now
1146−-- now()
1147−now :: Expr (null 'PGtimestamptz)
1148−now = UnsafeExpression "now()"
1149−
1150−{-----------------------------------------
1151−text
1152−-----------------------------------------}
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)
1153432
1154−escape :: Char -> String
1155−escape = \case
1156− '\NUL' -> "\\0"
1157− '\'' -> "''"
1158− '"' -> "\\\""
1159− '\b' -> "\\b"
1160− '\n' -> "\\n"
1161− '\r' -> "\\r"
1162− '\t' -> "\\t"
1163− '\\' -> "\\\\"
1164− 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)
1165438
1166439instance IsString
1167440 (Expression outer commons grp schemas params from (null 'PGtext)) where
@@ -1169,13 +442,19 @@ instance IsString
1169442 "E\'" <> fromString (escape =<< str) <> "\'"
1170443instance IsString
1171444 (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1172− fromString str = cast tsvector . UnsafeExpression $
445+ fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
1173446 "E\'" <> fromString (escape =<< str) <> "\'"
1174447instance IsString
1175448 (Expression outer commons grp schemas params from (null 'PGtsquery)) where
1176− fromString str = cast tsquery . UnsafeExpression $
449+ fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
1177450 "E\'" <> fromString (escape =<< str) <> "\'"
1178451
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 "||"
1179458instance Semigroup
1180459 (Expression outer commons grp schemas params from (null 'PGtext)) where
1181460 (<>) = unsafeBinaryOp "||"
@@ -1191,1391 +470,3 @@ instance Monoid
1191470 (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1192471 mempty = fromString ""
1193472 mappend = (<>)
1194−
1195−-- | >>> printSQL $ lower "ARRRGGG"
1196−-- lower(E'ARRRGGG')
1197−lower :: null 'PGtext :--> null 'PGtext
1198−lower = unsafeFunction "lower"
1199−
1200−-- | >>> printSQL $ upper "eeee"
1201−-- upper(E'eeee')
1202−upper :: null 'PGtext :--> null 'PGtext
1203−upper = unsafeFunction "upper"
1204−
1205−-- | >>> printSQL $ charLength "four"
1206−-- char_length(E'four')
1207−charLength :: null 'PGtext :--> null 'PGint4
1208−charLength = unsafeFunction "char_length"
1209−
1210−-- | The `like` expression returns true if the @string@ matches
1211−-- the supplied @pattern@. If @pattern@ does not contain percent signs
1212−-- or underscores, then the pattern only represents the string itself;
1213−-- in that case `like` acts like the equals operator. An underscore (_)
1214−-- in pattern stands for (matches) any single character; a percent sign (%)
1215−-- matches any sequence of zero or more characters.
1216−--
1217−-- >>> printSQL $ "abc" `like` "a%"
1218−-- (E'abc' LIKE E'a%')
1219−like :: Operator (null 'PGtext) (null 'PGtext) ('Null 'PGbool)
1220−like = unsafeBinaryOp "LIKE"
1221−
1222−-- | The key word ILIKE can be used instead of LIKE to make the
1223−-- match case-insensitive according to the active locale.
1224−--
1225−-- >>> printSQL $ "abc" `ilike` "a%"
1226−-- (E'abc' ILIKE E'a%')
1227−ilike :: Operator (null 'PGtext) (null 'PGtext) ('Null 'PGbool)
1228−ilike = unsafeBinaryOp "ILIKE"
1229−
1230−{-----------------------------------------
1231− -- json and jsonb support
1232−
1233−See https://www.postgresql.org/docs/10/static/functions-json.html -- most
1234−comments lifted directly from this page.
1235−
1236−Table 9.44: json and jsonb operators
1237−-----------------------------------------}
1238−
1239−-- | Get JSON value (object field or array element) at a key.
1240−(.->)
1241− :: (json `In` PGJsonType, key `In` PGJsonKey)
1242− => Operator (null json) (null key) ('Null json)
1243−infixl 8 .->
1244−(.->) = unsafeBinaryOp "->"
1245−
1246−-- | Get JSON value (object field or array element) at a key, as text.
1247−(.->>)
1248− :: (json `In` PGJsonType, key `In` PGJsonKey)
1249− => Operator (null json) (null key) ('Null 'PGtext)
1250−infixl 8 .->>
1251−(.->>) = unsafeBinaryOp "->>"
1252−
1253−-- | Get JSON value at a specified path.
1254−(.#>)
1255− :: json `In` PGJsonType
1256− => Operator (null json) (null ('PGvararray ('NotNull 'PGtext))) ('Null json)
1257−infixl 8 .#>
1258−(.#>) = unsafeBinaryOp "#>"
1259−
1260−-- | Get JSON value at a specified path as text.
1261−(.#>>)
1262− :: json `In` PGJsonType
1263− => Operator (null json) (null ('PGvararray ('NotNull 'PGtext))) ('Null 'PGtext)
1264−infixl 8 .#>>
1265−(.#>>) = unsafeBinaryOp "#>>"
1266−
1267−-- Additional jsonb operators
1268−
1269−class PGSubset container where
1270− (@>) :: Operator (null0 container) (null1 container) ('Null 'PGbool)
1271− (@>) = unsafeBinaryOp "@>"
1272− (<@) :: Operator (null0 container) (null1 container) ('Null 'PGbool)
1273− (<@) = unsafeBinaryOp "<@"
1274−instance PGSubset 'PGjsonb
1275−instance PGSubset 'PGtsquery
1276−instance PGSubset ('PGvararray ty)
1277−
1278−-- | Does the string exist as a top-level key within the JSON value?
1279−(.?) :: Operator (null 'PGjsonb) (null 'PGtext) ('Null 'PGbool)
1280−infixl 9 .?
1281−(.?) = unsafeBinaryOp "?"
1282−
1283−-- | Do any of these array strings exist as top-level keys?
1284−(.?|) :: Operator
1285− (null 'PGjsonb)
1286− (null ('PGvararray ('NotNull 'PGtext)))
1287− ('Null 'PGbool)
1288−infixl 9 .?|
1289−(.?|) = unsafeBinaryOp "?|"
1290−
1291−-- | Do all of these array strings exist as top-level keys?
1292−(.?&) :: Operator
1293− (null 'PGjsonb)
1294− (null ('PGvararray ('NotNull 'PGtext)))
1295− ('Null 'PGbool)
1296−infixl 9 .?&
1297−(.?&) = unsafeBinaryOp "?&"
1298−
1299−instance Semigroup
1300− (Expression outer commons grp schemas params from (null 'PGjsonb)) where
1301− (<>) = unsafeBinaryOp "||"
1302−
1303−-- | Delete a key or keys from a JSON object, or remove an array element.
1304−--
1305−-- If the right operand is..
1306−--
1307−-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1308−-- are matched based on their key value.
1309−--
1310−-- @ text[] @: Delete multiple key/value pairs or string elements
1311−-- from left operand. Key/value pairs are matched based on their key value.
1312−--
1313−-- @ integer @: Delete the array element with specified index (Negative integers
1314−-- count from the end). Throws an error if top level container is not an array.
1315−(.-.)
1316− :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1317− => Operator (null 'PGjsonb) (null key) (null 'PGjsonb)
1318−infixl 6 .-.
1319−(.-.) = unsafeBinaryOp "-"
1320−
1321−-- | Delete the field or element with specified path (for JSON arrays, negative
1322−-- integers count from the end)
1323−(#-.) :: Operator (null 'PGjsonb) (null ('PGvararray ('NotNull 'PGtext))) (null 'PGjsonb)
1324−infixl 6 #-.
1325−(#-.) = unsafeBinaryOp "#-"
1326−
1327−{-----------------------------------------
1328−Table 9.45: JSON creation functions
1329−-----------------------------------------}
1330−
1331−-- | Returns the value as json. Arrays and composites are converted
1332−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1333−-- type to json, the cast function will be used to perform the conversion;
1334−-- otherwise, a scalar value is produced. For any scalar type other than a
1335−-- number, a Boolean, or a null value, the text representation will be used, in
1336−-- such a fashion that it is a valid json value.
1337−toJson :: null ty :--> null 'PGjson
1338−toJson = unsafeFunction "to_json"
1339−
1340−-- | Returns the value as jsonb. Arrays and composites are converted
1341−-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1342−-- type to json, the cast function will be used to perform the conversion;
1343−-- otherwise, a scalar value is produced. For any scalar type other than a
1344−-- number, a Boolean, or a null value, the text representation will be used, in
1345−-- such a fashion that it is a valid jsonb value.
1346−toJsonb :: null ty :--> null 'PGjsonb
1347−toJsonb = unsafeFunction "to_jsonb"
1348−
1349−-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1350−-- becomes a JSON array of arrays.
1351−arrayToJson :: null ('PGvararray ty) :--> null 'PGjson
1352−arrayToJson = unsafeFunction "array_to_json"
1353−
1354−-- | Returns the row as a JSON object.
1355−rowToJson :: null ('PGcomposite ty) :--> null 'PGjson
1356−rowToJson = unsafeFunction "row_to_json"
1357−
1358−-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1359−-- argument list.
1360−jsonBuildArray :: SListI tuple => FunctionN tuple (null 'PGjson)
1361−jsonBuildArray = unsafeFunctionN "json_build_array"
1362−
1363−-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1364−-- variadic argument list.
1365−jsonbBuildArray :: SListI tuple => FunctionN tuple (null 'PGjsonb)
1366−jsonbBuildArray = unsafeFunctionN "jsonb_build_array"
1367−
1368−class PGBuildObject tys where
1369−instance PGBuildObject '[]
1370−instance (PGBuildObject tys, key `In` PGJsonKey)
1371− => PGBuildObject ('NotNull key ': value ': tys)
1372−
1373−-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1374−-- argument list. The elements of the argument list must alternate between text
1375−-- and values.
1376−jsonBuildObject
1377− :: (SListI elems, PGBuildObject elems)
1378− => FunctionN elems (null 'PGjson)
1379−jsonBuildObject = unsafeFunctionN "json_build_object"
1380−
1381−-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1382−-- variadic argument list. The elements of the argument list must alternate
1383−-- between keys and values.
1384−jsonbBuildObject
1385− :: (SListI elems, PGBuildObject elems)
1386− => FunctionN elems (null 'PGjsonb)
1387−jsonbBuildObject = unsafeFunctionN "jsonb_build_object"
1388−
1389−-- | Builds a JSON object out of a text array.
1390−-- The array must have two dimensions
1391−-- such that each inner array has exactly two elements,
1392−-- which are taken as a key/value pair.
1393−jsonObject
1394− :: null ('PGfixarray '[n,2] ('NotNull 'PGtext))
1395− :--> null 'PGjson
1396−jsonObject = unsafeFunction "json_object"
1397−
1398−-- | Builds a binary JSON object out of a text array.
1399−-- The array must have two dimensions
1400−-- such that each inner array has exactly two elements,
1401−-- which are taken as a key/value pair.
1402−jsonbObject
1403− :: null ('PGfixarray '[n,2] ('NotNull 'PGtext))
1404− :--> null 'PGjsonb
1405−jsonbObject = unsafeFunction "jsonb_object"
1406−
1407−-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1408−-- keys and one for values, that are zipped pairwise to create a JSON object.
1409−jsonZipObject :: FunctionN
1410− '[ null ('PGvararray ('NotNull 'PGtext))
1411− , null ('PGvararray ('NotNull 'PGtext)) ]
1412− ( null 'PGjson )
1413−jsonZipObject = unsafeFunctionN "json_object"
1414−
1415−-- | This is an alternate form of 'jsonbObject' that takes two arrays; one for
1416−-- keys and one for values, that are zipped pairwise to create a binary JSON
1417−-- object.
1418−jsonbZipObject :: FunctionN
1419− '[ null ('PGvararray ('NotNull 'PGtext))
1420− , null ('PGvararray ('NotNull 'PGtext)) ]
1421− ( null 'PGjsonb )
1422−jsonbZipObject = unsafeFunctionN "jsonb_object"
1423−
1424−{-----------------------------------------
1425−Table 9.46: JSON processing functions
1426−-----------------------------------------}
1427−
1428−-- | Returns the number of elements in the outermost JSON array.
1429−jsonArrayLength :: null 'PGjson :--> null 'PGint4
1430−jsonArrayLength = unsafeFunction "json_array_length"
1431−
1432−-- | Returns the number of elements in the outermost binary JSON array.
1433−jsonbArrayLength :: null 'PGjsonb :--> null 'PGint4
1434−jsonbArrayLength = unsafeFunction "jsonb_array_length"
1435−
1436−-- | Returns JSON value pointed to by the given path (equivalent to #>
1437−-- operator).
1438−jsonExtractPath
1439− :: SListI elems
1440− => Expression outer commons grp schemas params from (null 'PGjson)
1441− -> NP (Expression outer commons grp schemas params from) elems
1442− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1443−jsonExtractPath x xs =
1444− unsafeFunctionN "json_extract_path" (x :* xs)
1445−
1446−-- | Returns JSON value pointed to by the given path (equivalent to #>
1447−-- operator).
1448−jsonbExtractPath
1449− :: SListI elems
1450− => Expression outer commons grp schemas params from (null 'PGjsonb)
1451− -> NP (Expression outer commons grp schemas params from) elems
1452− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1453−jsonbExtractPath x xs =
1454− unsafeFunctionN "jsonb_extract_path" (x :* xs)
1455−
1456−-- | Returns JSON value pointed to by the given path (equivalent to #>
1457−-- operator), as text.
1458−jsonExtractPathAsText
1459− :: SListI elems
1460− => Expression outer commons grp schemas params from (null 'PGjson)
1461− -> NP (Expression outer commons grp schemas params from) elems
1462− -> Expression outer commons grp schemas params from (null 'PGjson)
1463−jsonExtractPathAsText x xs =
1464− unsafeFunctionN "json_extract_path_text" (x :* xs)
1465−
1466−-- | Returns JSON value pointed to by the given path (equivalent to #>
1467−-- operator), as text.
1468−jsonbExtractPathAsText
1469− :: SListI elems
1470− => Expression outer commons grp schemas params from (null 'PGjsonb)
1471− -> NP (Expression outer commons grp schemas params from) elems
1472− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1473−jsonbExtractPathAsText x xs =
1474− unsafeFunctionN "jsonb_extract_path_text" (x :* xs)
1475−
1476−-- | Returns the type of the outermost JSON value as a text string. Possible
1477−-- types are object, array, string, number, boolean, and null.
1478−jsonTypeof :: null 'PGjson :--> null 'PGtext
1479−jsonTypeof = unsafeFunction "json_typeof"
1480−
1481−-- | Returns the type of the outermost binary JSON value as a text string.
1482−-- Possible types are object, array, string, number, boolean, and null.
1483−jsonbTypeof :: null 'PGjsonb :--> null 'PGtext
1484−jsonbTypeof = unsafeFunction "jsonb_typeof"
1485−
1486−-- | Returns its argument with all object fields that have null values omitted.
1487−-- Other null values are untouched.
1488−jsonStripNulls :: null 'PGjson :--> null 'PGjson
1489−jsonStripNulls = unsafeFunction "json_strip_nulls"
1490−
1491−-- | Returns its argument with all object fields that have null values omitted.
1492−-- Other null values are untouched.
1493−jsonbStripNulls :: null 'PGjsonb :--> null 'PGjsonb
1494−jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1495−
1496−-- | @ jsonbSet target path new_value create_missing @
1497−--
1498−-- Returns target with the section designated by path replaced by new_value,
1499−-- or with new_value added if create_missing is true ( default is true) and the
1500−-- item designated by path does not exist. As with the path orientated
1501−-- operators, negative integers that appear in path count from the end of JSON
1502−-- arrays.
1503−jsonbSet
1504− :: Expression outer commons grp schemas params from (null 'PGjsonb)
1505− -> Expression outer commons grp schemas params from (null ('PGvararray ('NotNull 'PGtext)))
1506− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1507− -> Maybe (Expression outer commons grp schemas params from (null 'PGbool))
1508− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1509−jsonbSet tgt path val createMissing = case createMissing of
1510− Just m -> unsafeFunctionN "jsonb_set" (tgt :* path :* val :* m :* Nil)
1511− Nothing -> unsafeFunctionN "jsonb_set" (tgt :* path :* val :* Nil)
1512−
1513−-- | @ jsonbInsert target path new_value insert_after @
1514−--
1515−-- Returns target with new_value inserted. If target section designated by
1516−-- path is in a JSONB array, new_value will be inserted before target or after
1517−-- if insert_after is true (default is false). If target section designated by
1518−-- path is in JSONB object, new_value will be inserted only if target does not
1519−-- exist. As with the path orientated operators, negative integers that appear
1520−-- in path count from the end of JSON arrays.
1521−jsonbInsert
1522− :: Expression outer commons grp schemas params from (null 'PGjsonb)
1523− -> Expression outer commons grp schemas params from (null ('PGvararray ('NotNull 'PGtext)))
1524− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1525− -> Maybe (Expression outer commons grp schemas params from (null 'PGbool))
1526− -> Expression outer commons grp schemas params from (null 'PGjsonb)
1527−jsonbInsert tgt path val insertAfter = case insertAfter of
1528− Just i -> unsafeFunctionN "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1529− Nothing -> unsafeFunctionN "jsonb_insert" (tgt :* path :* val :* Nil)
1530−
1531−-- | Returns its argument as indented JSON text.
1532−jsonbPretty :: null 'PGjsonb :--> null 'PGtext
1533−jsonbPretty = unsafeFunction "jsonb_pretty"
1534−
1535−(@@) :: Operator (null 'PGtsvector) (null 'PGtsquery) ('Null 'PGbool)
1536−(@@) = unsafeBinaryOp "@@"
1537−
1538−(.&) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1539−(.&) = unsafeBinaryOp "&&"
1540−
1541−(.|) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1542−(.|) = unsafeBinaryOp "||"
1543−
1544−(.!) :: null 'PGtsquery :--> null 'PGtsquery
1545−(.!) = unsafeUnaryOpL "!!"
1546−
1547−(<->) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1548−(<->) = unsafeBinaryOp "<->"
1549−
1550−arrayToTSvector
1551− :: null ('PGvararray ('NotNull 'PGtext))
1552− :--> null 'PGtsvector
1553−arrayToTSvector = unsafeFunction "array_to_tsvector"
1554−
1555−tsvectorLength :: null 'PGtsvector :--> null 'PGint4
1556−tsvectorLength = unsafeFunction "length"
1557−
1558−numnode :: null 'PGtsquery :--> null 'PGint4
1559−numnode = unsafeFunction "numnode"
1560−
1561−plainToTSquery :: null 'PGtext :--> null 'PGtsquery
1562−plainToTSquery = unsafeFunction "plainto_tsquery"
1563−
1564−phraseToTSquery :: null 'PGtext :--> null 'PGtsquery
1565−phraseToTSquery = unsafeFunction "phraseto_tsquery"
1566−
1567−websearchToTSquery :: null 'PGtext :--> null 'PGtsquery
1568−websearchToTSquery = unsafeFunction "websearch_to_tsquery"
1569−
1570−queryTree :: null 'PGtsquery :--> null 'PGtext
1571−queryTree = unsafeFunction "query_tree"
1572−
1573−toTSquery :: null 'PGtext :--> null 'PGtsquery
1574−toTSquery = unsafeFunction "to_tsquery"
1575−
1576−toTSvector
1577− :: ty `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1578− => null ty :--> null 'PGtsvector
1579−toTSvector = unsafeFunction "to_tsvector"
1580−
1581−setWeight
1582− :: FunctionN '[null 'PGtsvector, null ('PGchar 1)] (null 'PGtsvector)
1583−setWeight = unsafeFunctionN "set_weight"
1584−
1585−strip :: null 'PGtsvector :--> null 'PGtsvector
1586−strip = unsafeFunction "strip"
1587−
1588−jsonToTSvector :: FunctionN '[null 'PGjson, null 'PGjson] (null 'PGtsvector)
1589−jsonToTSvector = unsafeFunctionN "json_to_tsvector"
1590−
1591−jsonbToTSvector :: FunctionN '[null 'PGjsonb, null 'PGjsonb] (null 'PGtsvector)
1592−jsonbToTSvector = unsafeFunctionN "jsonb_to_tsvector"
1593−
1594−tsDelete :: FunctionN
1595− '[null 'PGtsvector, null ('PGvararray ('NotNull 'PGtext))]
1596− (null 'PGtsvector)
1597−tsDelete = unsafeFunctionN "ts_delete"
1598−
1599−tsFilter :: FunctionN
1600− '[null 'PGtsvector, null ('PGvararray ('NotNull ('PGchar 1)))]
1601− (null 'PGtsvector)
1602−tsFilter = unsafeFunctionN "ts_filter"
1603−
1604−tsHeadline
1605− :: document `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1606− => FunctionN '[null document, null 'PGtsquery] (null 'PGtext)
1607−tsHeadline = unsafeFunctionN "ts_headline"
1608−{-----------------------------------------
1609−aggregation
1610−-----------------------------------------}
1611−
1612−unsafeAggregateN
1613− :: SOP.SListI xs
1614− => ByteString -- ^ function
1615− -> Distinction (NP (Expression outer commons 'Ungrouped schemas params from)) xs
1616− -> Expression outer commons ('Grouped bys) schemas params from y
1617−unsafeAggregateN fun xs = UnsafeExpression $ fun <> parenthesized (renderSQL xs)
1618−
1619−{- |
1620−`Aggregate` functions compute a single result from a set of input values.
1621−`Aggregate` functions can be used as `GroupedBy` `Expression`s as well
1622−as `WindowFunction`s.
1623−-}
1624−class Aggregate expr1 exprN aggr
1625− | aggr -> expr1, aggr -> exprN where
1626−
1627− -- | A special aggregation that does not require an input
1628− --
1629− -- >>> :{
1630− -- let
1631− -- expression :: Expression '[] commons ('Grouped bys) schemas params from ('NotNull 'PGint8)
1632− -- expression = countStar
1633− -- in printSQL expression
1634− -- :}
1635− -- count(*)
1636− countStar :: aggr ('NotNull 'PGint8)
1637−
1638− -- | >>> :{
1639− -- let
1640− -- expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null ty]] ('NotNull 'PGint8)
1641− -- expression = count (All #col)
1642− -- in printSQL expression
1643− -- :}
1644− -- count(ALL "col")
1645− count
1646− :: expr1 ty
1647− -- ^ what to count
1648− -> aggr ('NotNull 'PGint8)
1649−
1650− -- | >>> :{
1651− -- let
1652− -- expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('NotNull 'PGnumeric)
1653− -- expression = sum_ (Distinct #col)
1654− -- in printSQL expression
1655− -- :}
1656− -- sum(DISTINCT "col")
1657− sum_
1658− :: ty `In` PGNum
1659− => expr1 (null ty)
1660− -> aggr ('NotNull ty)
1661−
1662− -- | input values, including nulls, concatenated into an array
1663− arrayAgg
1664− :: expr1 ty
1665− -> aggr ('Null ('PGvararray ty))
1666−
1667− -- | aggregates values as a JSON array
1668− jsonAgg
1669− :: expr1 ty
1670− -> aggr ('Null 'PGjson)
1671−
1672− -- | aggregates values as a JSON array
1673− jsonbAgg
1674− :: expr1 ty
1675− -> aggr ('Null 'PGjsonb)
1676−
1677− {- |
1678− the bitwise AND of all non-null input values, or null if none
1679− >>> :{
1680− let
1681− expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGint4]] ('Null 'PGint4)
1682− expression = bitAnd (Distinct #col)
1683− in printSQL expression
1684− :}
1685− bit_and(DISTINCT "col")
1686− -}
1687− bitAnd
1688− :: int `In` PGIntegral
1689− => expr1 (null int)
1690− -- ^ what to aggregate
1691− -> aggr ('Null int)
1692−
1693− {- |
1694− the bitwise OR of all non-null input values, or null if none
1695−
1696− >>> :{
1697− let
1698− expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGint4]] ('Null 'PGint4)
1699− expression = bitOr (All #col)
1700− in printSQL expression
1701− :}
1702− bit_or(ALL "col")
1703− -}
1704− bitOr
1705− :: int `In` PGIntegral
1706− => expr1 (null int)
1707− -- ^ what to aggregate
1708− -> aggr ('Null int)
1709−
1710− {- |
1711− true if all input values are true, otherwise false
1712−
1713− >>> :{
1714− let
1715− winFun :: WindowFunction '[] commons 'Ungrouped schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1716− winFun = boolAnd #col
1717− in printSQL winFun
1718− :}
1719− bool_and("col")
1720− -}
1721− boolAnd
1722− :: expr1 (null 'PGbool)
1723− -- ^ what to aggregate
1724− -> aggr ('Null 'PGbool)
1725−
1726− {- |
1727− true if at least one input value is true, otherwise false
1728−
1729− >>> :{
1730− let
1731− expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1732− expression = boolOr (All #col)
1733− in printSQL expression
1734− :}
1735− bool_or(ALL "col")
1736− -}
1737− boolOr
1738− :: expr1 (null 'PGbool)
1739− -- ^ what to aggregate
1740− -> aggr ('Null 'PGbool)
1741−
1742− {- |
1743− equivalent to `boolAnd`
1744−
1745− >>> :{
1746− let
1747− expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1748− expression = every (Distinct #col)
1749− in printSQL expression
1750− :}
1751− every(DISTINCT "col")
1752− -}
1753− every
1754− :: expr1 (null 'PGbool)
1755− -- ^ what to aggregate
1756− -> aggr ('Null 'PGbool)
1757−
1758− {- |maximum value of expression across all input values-}
1759− max_
1760− :: expr1 (null ty)
1761− -- ^ what to maximize
1762− -> aggr ('Null ty)
1763−
1764− -- | minimum value of expression across all input values
1765− min_
1766− :: expr1 (null ty)
1767− -- ^ what to minimize
1768− -> aggr ('Null ty)
1769−
1770− -- | the average (arithmetic mean) of all input values
1771− avg
1772− :: expr1 (null ty)
1773− -- ^ what to average
1774− -> aggr ('Null (PGAvg ty))
1775−
1776− {- | correlation coefficient
1777− >>> :{
1778− let
1779− expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1780− expression = corr (All (#y *: #x))
1781− in printSQL expression
1782− :}
1783− corr(ALL "y", "x")
1784− -}
1785− corr
1786− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1787− -> aggr ('Null 'PGfloat8)
1788−
1789− {- | population covariance
1790− >>> :{
1791− let
1792− expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1793− expression = covarPop (All (#y *: #x))
1794− in printSQL expression
1795− :}
1796− covar_pop(ALL "y", "x")
1797− -}
1798− covarPop
1799− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1800− -> aggr ('Null 'PGfloat8)
1801−
1802− {- | sample covariance
1803− >>> :{
1804− let
1805− winFun :: WindowFunction '[] c 'Ungrouped s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1806− winFun = covarSamp (#y *: #x)
1807− in printSQL winFun
1808− :}
1809− covar_samp("y", "x")
1810− -}
1811− covarSamp
1812− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1813− -> aggr ('Null 'PGfloat8)
1814−
1815− {- | average of the independent variable (sum(X)/N)
1816− >>> :{
1817− let
1818− expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1819− expression = regrAvgX (All (#y *: #x))
1820− in printSQL expression
1821− :}
1822− regr_avgx(ALL "y", "x")
1823− -}
1824− regrAvgX
1825− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1826− -> aggr ('Null 'PGfloat8)
1827−
1828− {- | average of the dependent variable (sum(Y)/N)
1829− >>> :{
1830− let
1831− winFun :: WindowFunction '[] c 'Ungrouped s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1832− winFun = regrAvgY (#y *: #x)
1833− in printSQL winFun
1834− :}
1835− regr_avgy("y", "x")
1836− -}
1837− regrAvgY
1838− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1839− -> aggr ('Null 'PGfloat8)
1840−
1841− {- | number of input rows in which both expressions are nonnull
1842− >>> :{
1843− let
1844− winFun :: WindowFunction '[] c 'Ungrouped s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGint8)
1845− winFun = regrCount (#y *: #x)
1846− in printSQL winFun
1847− :}
1848− regr_count("y", "x")
1849− -}
1850− regrCount
1851− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1852− -> aggr ('Null 'PGint8)
1853−
1854− {- | y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs
1855− >>> :{
1856− let
1857− expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1858− expression = regrIntercept (All (#y *: #x))
1859− in printSQL expression
1860− :}
1861− regr_intercept(ALL "y", "x")
1862− -}
1863− regrIntercept
1864− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1865− -> aggr ('Null 'PGfloat8)
1866−
1867− -- | @regr_r2(Y, X)@, square of the correlation coefficient
1868− regrR2
1869− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1870− -> aggr ('Null 'PGfloat8)
1871−
1872− -- | @regr_slope(Y, X)@, slope of the least-squares-fit linear equation
1873− -- determined by the (X, Y) pairs
1874− regrSlope
1875− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1876− -> aggr ('Null 'PGfloat8)
1877−
1878− -- | @regr_sxx(Y, X)@, sum(X^2) - sum(X)^2/N
1879− -- (“sum of squares” of the independent variable)
1880− regrSxx
1881− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1882− -> aggr ('Null 'PGfloat8)
1883−
1884− -- | @regr_sxy(Y, X)@, sum(X*Y) - sum(X) * sum(Y)/N
1885− -- (“sum of products” of independent times dependent variable)
1886− regrSxy
1887− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1888− -> aggr ('Null 'PGfloat8)
1889−
1890− -- | @regr_syy(Y, X)@, sum(Y^2) - sum(Y)^2/N
1891− -- (“sum of squares” of the dependent variable)
1892− regrSyy
1893− :: exprN '[null 'PGfloat8, null 'PGfloat8]
1894− -> aggr ('Null 'PGfloat8)
1895−
1896− -- | historical alias for `stddevSamp`
1897− stddev
1898− :: expr1 (null ty)
1899− -> aggr ('Null (PGAvg ty))
1900−
1901− -- | population standard deviation of the input values
1902− stddevPop
1903− :: expr1 (null ty)
1904− -> aggr ('Null (PGAvg ty))
1905−
1906− -- | sample standard deviation of the input values
1907− stddevSamp
1908− :: expr1 (null ty)
1909− -> aggr ('Null (PGAvg ty))
1910−
1911− -- | historical alias for `varSamp`
1912− variance
1913− :: expr1 (null ty)
1914− -> aggr ('Null (PGAvg ty))
1915−
1916− -- | population variance of the input values
1917− -- (square of the population standard deviation)
1918− varPop
1919− :: expr1 (null ty)
1920− -> aggr ('Null (PGAvg ty))
1921−
1922− -- | sample variance of the input values
1923− -- (square of the sample standard deviation)
1924− varSamp
1925− :: expr1 (null ty)
1926− -> aggr ('Null (PGAvg ty))
1927−
1928−{- |
1929−`Distinction`s are used for the input of `Aggregate` `Expression`s.
1930−`All` invokes the aggregate once for each input row.
1931−`Distinct` invokes the aggregate once for each distinct value of the expression
1932−(or distinct set of values, for multiple expressions) found in the input
1933−-}
1934−data Distinction (expr :: kind -> Type) (ty :: kind)
1935− = All (expr ty)
1936− | Distinct (expr ty)
1937− deriving (GHC.Generic,Show,Eq,Ord)
1938−instance NFData (Distinction (Expression outer commons grp schemas params from) ty)
1939−instance RenderSQL (Distinction (Expression outer commons grp schemas params from) ty) where
1940− renderSQL = \case
1941− All x -> "ALL" <+> renderSQL x
1942− Distinct x -> "DISTINCT" <+> renderSQL x
1943−instance SOP.SListI tys => RenderSQL
1944− (Distinction (NP (Expression outer commons grp schemas params from)) tys) where
1945− renderSQL = \case
1946− All xs -> "ALL" <+> renderCommaSeparated renderSQL xs
1947− Distinct xs -> "DISTINCT" <+> renderCommaSeparated renderSQL xs
1948−
1949−instance Aggregate
1950− (Distinction (Expression outer commons 'Ungrouped schemas params from))
1951− (Distinction (NP (Expression outer commons 'Ungrouped schemas params from)))
1952− (Expression outer commons ('Grouped bys) schemas params from) where
1953− countStar = UnsafeExpression "count(*)"
1954− count = unsafeAggregate1 "count"
1955− sum_ = unsafeAggregate1 "sum"
1956− arrayAgg = unsafeAggregate1 "array_agg"
1957− jsonAgg = unsafeAggregate1 "json_agg"
1958− jsonbAgg = unsafeAggregate1 "jsonb_agg"
1959− bitAnd = unsafeAggregate1 "bit_and"
1960− bitOr = unsafeAggregate1 "bit_or"
1961− boolAnd = unsafeAggregate1 "bool_and"
1962− boolOr = unsafeAggregate1 "bool_or"
1963− every = unsafeAggregate1 "every"
1964− max_ = unsafeAggregate1 "max"
1965− min_ = unsafeAggregate1 "min"
1966− avg = unsafeAggregate1 "avg"
1967− corr = unsafeAggregateN "corr"
1968− covarPop = unsafeAggregateN "covar_pop"
1969− covarSamp = unsafeAggregateN "covar_samp"
1970− regrAvgX = unsafeAggregateN "regr_avgx"
1971− regrAvgY = unsafeAggregateN "regr_avgy"
1972− regrCount = unsafeAggregateN "regr_count"
1973− regrIntercept = unsafeAggregateN "regr_intercept"
1974− regrR2 = unsafeAggregateN "regr_r2"
1975− regrSlope = unsafeAggregateN "regr_slope"
1976− regrSxx = unsafeAggregateN "regr_sxx"
1977− regrSxy = unsafeAggregateN "regr_sxy"
1978− regrSyy = unsafeAggregateN "regr_syy"
1979− stddev = unsafeAggregate1 "stddev"
1980− stddevPop = unsafeAggregate1 "stddev_pop"
1981− stddevSamp = unsafeAggregate1 "stddev_samp"
1982− variance = unsafeAggregate1 "variance"
1983− varPop = unsafeAggregate1 "var_pop"
1984− varSamp = unsafeAggregate1 "var_samp"
1985−instance Aggregate
1986− (Expression outer commons grp schemas params from)
1987− (NP (Expression outer commons grp schemas params from))
1988− (WindowFunction outer commons grp schemas params from) where
1989− countStar = UnsafeWindowFunction "count(*)"
1990− count = unsafeWindowFunction1 "count"
1991− sum_ = unsafeWindowFunction1 "sum"
1992− arrayAgg = unsafeWindowFunction1 "array_agg"
1993− jsonAgg = unsafeWindowFunction1 "json_agg"
1994− jsonbAgg = unsafeWindowFunction1 "jsonb_agg"
1995− bitAnd = unsafeWindowFunction1 "bit_and"
1996− bitOr = unsafeWindowFunction1 "bit_or"
1997− boolAnd = unsafeWindowFunction1 "bool_and"
1998− boolOr = unsafeWindowFunction1 "bool_or"
1999− every = unsafeWindowFunction1 "every"
2000− max_ = unsafeWindowFunction1 "max"
2001− min_ = unsafeWindowFunction1 "min"
2002− avg = unsafeWindowFunction1 "avg"
2003− corr = unsafeWindowFunctionN "corr"
2004− covarPop = unsafeWindowFunctionN "covar_pop"
2005− covarSamp = unsafeWindowFunctionN "covar_samp"
2006− regrAvgX = unsafeWindowFunctionN "regr_avgx"
2007− regrAvgY = unsafeWindowFunctionN "regr_avgy"
2008− regrCount = unsafeWindowFunctionN "regr_count"
2009− regrIntercept = unsafeWindowFunctionN "regr_intercept"
2010− regrR2 = unsafeWindowFunctionN "regr_r2"
2011− regrSlope = unsafeWindowFunctionN "regr_slope"
2012− regrSxx = unsafeWindowFunctionN "regr_sxx"
2013− regrSxy = unsafeWindowFunctionN "regr_sxy"
2014− regrSyy = unsafeWindowFunctionN "regr_syy"
2015− stddev = unsafeWindowFunction1 "stddev"
2016− stddevPop = unsafeWindowFunction1 "stddev_pop"
2017− stddevSamp = unsafeWindowFunction1 "stddev_samp"
2018− variance = unsafeWindowFunction1 "variance"
2019− varPop = unsafeWindowFunction1 "var_pop"
2020− varSamp = unsafeWindowFunction1 "var_samp"
2021−
2022−-- | escape hatch to define aggregate functions
2023−unsafeAggregate1
2024− :: ByteString -- ^ aggregate function
2025− -> Distinction (Expression outer commons 'Ungrouped schemas params from) x
2026− -> Expression outer commons ('Grouped bys) schemas params from y
2027−unsafeAggregate1 fun x = UnsafeExpression $ fun <> parenthesized (renderSQL x)
2028−
2029−-- | A type family that calculates `PGAvg` type of a `PGType`.
2030−type family PGAvg ty where
2031− PGAvg 'PGint2 = 'PGnumeric
2032− PGAvg 'PGint4 = 'PGnumeric
2033− PGAvg 'PGint8 = 'PGnumeric
2034− PGAvg 'PGnumeric = 'PGnumeric
2035− PGAvg 'PGfloat4 = 'PGfloat8
2036− PGAvg 'PGfloat8 = 'PGfloat8
2037− PGAvg 'PGinterval = 'PGinterval
2038− PGAvg pg = TypeError
2039− ('Text "Squeal type error: No average for " ':<>: 'ShowType pg)
2040−
2041−{-----------------------------------------
2042−type expressions
2043−-----------------------------------------}
2044−
2045−-- | `TypeExpression`s are used in `cast`s and
2046−-- `Squeal.PostgreSQL.Definition.createTable` commands.
2047−newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
2048− = UnsafeTypeExpression { renderTypeExpression :: ByteString }
2049− deriving (GHC.Generic,Show,Eq,Ord,NFData)
2050−instance RenderSQL (TypeExpression schemas ty) where
2051− renderSQL = renderTypeExpression
2052−
2053−-- | The enum or composite type in a `Typedef` can be expressed by its alias.
2054−typedef
2055− :: (Has sch schemas schema, Has td schema ('Typedef ty))
2056− => QualifiedAlias sch td
2057− -> TypeExpression schemas (null ty)
2058−typedef = UnsafeTypeExpression . renderSQL
2059−
2060−-- | The composite type corresponding to a `Table` definition can be expressed
2061−-- by its alias.
2062−typetable
2063− :: (Has sch schemas schema, Has tab schema ('Table table))
2064− => QualifiedAlias sch tab
2065− -> TypeExpression schemas (null ('PGcomposite (TableToRow table)))
2066−typetable = UnsafeTypeExpression . renderSQL
2067−
2068−-- | The composite type corresponding to a `View` definition can be expressed
2069−-- by its alias.
2070−typeview
2071− :: (Has sch schemas schema, Has vw schema ('View view))
2072− => QualifiedAlias sch vw
2073− -> TypeExpression schemas (null ('PGcomposite view))
2074−typeview = UnsafeTypeExpression . renderSQL
2075−
2076−-- | logical Boolean (true/false)
2077−bool :: TypeExpression schemas (null 'PGbool)
2078−bool = UnsafeTypeExpression "bool"
2079−-- | signed two-byte integer
2080−int2, smallint :: TypeExpression schemas (null 'PGint2)
2081−int2 = UnsafeTypeExpression "int2"
2082−smallint = UnsafeTypeExpression "smallint"
2083−-- | signed four-byte integer
2084−int4, int, integer :: TypeExpression schemas (null 'PGint4)
2085−int4 = UnsafeTypeExpression "int4"
2086−int = UnsafeTypeExpression "int"
2087−integer = UnsafeTypeExpression "integer"
2088−-- | signed eight-byte integer
2089−int8, bigint :: TypeExpression schemas (null 'PGint8)
2090−int8 = UnsafeTypeExpression "int8"
2091−bigint = UnsafeTypeExpression "bigint"
2092−-- | arbitrary precision numeric type
2093−numeric :: TypeExpression schemas (null 'PGnumeric)
2094−numeric = UnsafeTypeExpression "numeric"
2095−-- | single precision floating-point number (4 bytes)
2096−float4, real :: TypeExpression schemas (null 'PGfloat4)
2097−float4 = UnsafeTypeExpression "float4"
2098−real = UnsafeTypeExpression "real"
2099−-- | double precision floating-point number (8 bytes)
2100−float8, doublePrecision :: TypeExpression schemas (null 'PGfloat8)
2101−float8 = UnsafeTypeExpression "float8"
2102−doublePrecision = UnsafeTypeExpression "double precision"
2103−-- | currency amount
2104−money :: TypeExpression schema (null 'PGmoney)
2105−money = UnsafeTypeExpression "money"
2106−-- | variable-length character string
2107−text :: TypeExpression schemas (null 'PGtext)
2108−text = UnsafeTypeExpression "text"
2109−-- | fixed-length character string
2110−char, character
2111− :: forall n schemas null. (KnownNat n, 1 <= n)
2112− => TypeExpression schemas (null ('PGchar n))
2113−char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
2114−character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
2115−-- | variable-length character string
2116−varchar, characterVarying
2117− :: forall n schemas null. (KnownNat n, 1 <= n)
2118− => TypeExpression schemas (null ('PGvarchar n))
2119−varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
2120−characterVarying = UnsafeTypeExpression $
2121− "character varying(" <> renderNat @n <> ")"
2122−-- | binary data ("byte array")
2123−bytea :: TypeExpression schemas (null 'PGbytea)
2124−bytea = UnsafeTypeExpression "bytea"
2125−-- | date and time (no time zone)
2126−timestamp :: TypeExpression schemas (null 'PGtimestamp)
2127−timestamp = UnsafeTypeExpression "timestamp"
2128−-- | date and time, including time zone
2129−timestampWithTimeZone :: TypeExpression schemas (null 'PGtimestamptz)
2130−timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
2131−-- | calendar date (year, month, day)
2132−date :: TypeExpression schemas (null 'PGdate)
2133−date = UnsafeTypeExpression "date"
2134−-- | time of day (no time zone)
2135−time :: TypeExpression schemas (null 'PGtime)
2136−time = UnsafeTypeExpression "time"
2137−-- | time of day, including time zone
2138−timeWithTimeZone :: TypeExpression schemas (null 'PGtimetz)
2139−timeWithTimeZone = UnsafeTypeExpression "time with time zone"
2140−-- | time span
2141−interval :: TypeExpression schemas (null 'PGinterval)
2142−interval = UnsafeTypeExpression "interval"
2143−-- | universally unique identifier
2144−uuid :: TypeExpression schemas (null 'PGuuid)
2145−uuid = UnsafeTypeExpression "uuid"
2146−-- | IPv4 or IPv6 host address
2147−inet :: TypeExpression schemas (null 'PGinet)
2148−inet = UnsafeTypeExpression "inet"
2149−-- | textual JSON data
2150−json :: TypeExpression schemas (null 'PGjson)
2151−json = UnsafeTypeExpression "json"
2152−-- | binary JSON data, decomposed
2153−jsonb :: TypeExpression schemas (null 'PGjsonb)
2154−jsonb = UnsafeTypeExpression "jsonb"
2155−-- | variable length array
2156−vararray
2157− :: TypeExpression schemas pg
2158− -> TypeExpression schemas (null ('PGvararray pg))
2159−vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
2160−-- | fixed length array
2161−--
2162−-- >>> renderSQL (fixarray @'[2] json)
2163−-- "json[2]"
2164−fixarray
2165− :: forall dims schemas null pg. SOP.All KnownNat dims
2166− => TypeExpression schemas pg
2167− -> TypeExpression schemas (null ('PGfixarray dims pg))
2168−fixarray ty = UnsafeTypeExpression $
2169− renderSQL ty <> renderDims @dims
2170− where
2171− renderDims :: forall ns. SOP.All KnownNat ns => ByteString
2172− renderDims =
2173− ("[" <>)
2174− . (<> "]")
2175− . ByteString.intercalate "]["
2176− . hcollapse
2177− $ hcmap (SOP.Proxy @KnownNat)
2178− (K . fromString . show . natVal)
2179− (hpure SOP.Proxy :: NP SOP.Proxy ns)
2180−tsvector :: TypeExpression schemas (null 'PGtsvector)
2181−tsvector = UnsafeTypeExpression "tsvector"
2182−tsquery :: TypeExpression schemas (null 'PGtsquery)
2183−tsquery = UnsafeTypeExpression "tsquery"
2184−
2185−-- | `pgtype` is a demoted version of a `PGType`
2186−class PGTyped schemas (ty :: NullityType) where
2187− pgtype :: TypeExpression schemas ty
2188−instance PGTyped schemas (null 'PGbool) where pgtype = bool
2189−instance PGTyped schemas (null 'PGint2) where pgtype = int2
2190−instance PGTyped schemas (null 'PGint4) where pgtype = int4
2191−instance PGTyped schemas (null 'PGint8) where pgtype = int8
2192−instance PGTyped schemas (null 'PGnumeric) where pgtype = numeric
2193−instance PGTyped schemas (null 'PGfloat4) where pgtype = float4
2194−instance PGTyped schemas (null 'PGfloat8) where pgtype = float8
2195−instance PGTyped schemas (null 'PGmoney) where pgtype = money
2196−instance PGTyped schemas (null 'PGtext) where pgtype = text
2197−instance (KnownNat n, 1 <= n)
2198− => PGTyped schemas (null ('PGchar n)) where pgtype = char @n
2199−instance (KnownNat n, 1 <= n)
2200− => PGTyped schemas (null ('PGvarchar n)) where pgtype = varchar @n
2201−instance PGTyped schemas (null 'PGbytea) where pgtype = bytea
2202−instance PGTyped schemas (null 'PGtimestamp) where pgtype = timestamp
2203−instance PGTyped schemas (null 'PGtimestamptz) where pgtype = timestampWithTimeZone
2204−instance PGTyped schemas (null 'PGdate) where pgtype = date
2205−instance PGTyped schemas (null 'PGtime) where pgtype = time
2206−instance PGTyped schemas (null 'PGtimetz) where pgtype = timeWithTimeZone
2207−instance PGTyped schemas (null 'PGinterval) where pgtype = interval
2208−instance PGTyped schemas (null 'PGuuid) where pgtype = uuid
2209−instance PGTyped schemas (null 'PGjson) where pgtype = json
2210−instance PGTyped schemas (null 'PGjsonb) where pgtype = jsonb
2211−instance PGTyped schemas ty
2212− => PGTyped schemas (null ('PGvararray ty)) where
2213− pgtype = vararray (pgtype @schemas @ty)
2214−instance (SOP.All KnownNat dims, PGTyped schemas ty)
2215− => PGTyped schemas (null ('PGfixarray dims ty)) where
2216− pgtype = fixarray @dims (pgtype @schemas @ty)
2217−instance PGTyped schemas (null 'PGtsvector) where pgtype = tsvector
2218−instance PGTyped schemas (null 'PGtsquery) where pgtype = tsquery
2219−
2220−{-----------------------------------------
2221−Sorting
2222−-----------------------------------------}
2223−
2224−-- | `SortExpression`s are used by `orderBy` to optionally sort the results
2225−-- of a `Squeal.PostgreSQL.Query.Query`. `Asc` or `Desc`
2226−-- set the sort direction of a `NotNull` result
2227−-- column to ascending or descending. Ascending order puts smaller values
2228−-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
2229−-- descending order is determined with the `.>` operator. `AscNullsFirst`,
2230−-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
2231−-- determine whether nulls appear before or after non-null values in the sort
2232−-- ordering of a `Null` result column.
2233−data SortExpression outer commons grp schemas params from where
2234− Asc
2235− :: Expression outer commons grp schemas params from ('NotNull ty)
2236− -> SortExpression outer commons grp schemas params from
2237− Desc
2238− :: Expression outer commons grp schemas params from ('NotNull ty)
2239− -> SortExpression outer commons grp schemas params from
2240− AscNullsFirst
2241− :: Expression outer commons grp schemas params from ('Null ty)
2242− -> SortExpression outer commons grp schemas params from
2243− AscNullsLast
2244− :: Expression outer commons grp schemas params from ('Null ty)
2245− -> SortExpression outer commons grp schemas params from
2246− DescNullsFirst
2247− :: Expression outer commons grp schemas params from ('Null ty)
2248− -> SortExpression outer commons grp schemas params from
2249− DescNullsLast
2250− :: Expression outer commons grp schemas params from ('Null ty)
2251− -> SortExpression outer commons grp schemas params from
2252−deriving instance Show (SortExpression outer commons grp schemas params from)
2253−
2254−{- |
2255−The `orderBy` clause causes the result rows of a `Squeal.PostgreSQL.Query.TableExpression`
2256−to be sorted according to the specified `SortExpression`(s).
2257−If two rows are equal according to the leftmost expression,
2258−they are compared according to the next expression and so on.
2259−If they are equal according to all specified expressions,
2260−they are returned in an implementation-dependent order.
2261−
2262−You can also control the order in which rows are processed by window functions
2263−using `orderBy` within `Squeal.PostgreSQL.Query.Over`.
2264−-}
2265−class OrderBy expr where
2266− orderBy
2267− :: [SortExpression outer commons grp schemas params from]
2268− -> expr outer commons grp schemas params from
2269− -> expr outer commons grp schemas params from
2270−
2271−-- | Render a `SortExpression`.
2272−instance RenderSQL (SortExpression outer commons grp schemas params from) where
2273− renderSQL = \case
2274− Asc expression -> renderSQL expression <+> "ASC"
2275− Desc expression -> renderSQL expression <+> "DESC"
2276− AscNullsFirst expression -> renderSQL expression
2277− <+> "ASC NULLS FIRST"
2278− DescNullsFirst expression -> renderSQL expression
2279− <+> "DESC NULLS FIRST"
2280− AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
2281− DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
2282−
2283−-- | A `WindowDefinition` is a set of table rows that are somehow related
2284−-- to the current row
2285−data WindowDefinition outer commons grp schemas params from where
2286− WindowDefinition
2287− :: SListI bys
2288− => NP (Expression outer commons grp schemas params from) bys
2289− -> [SortExpression outer commons grp schemas params from]
2290− -> WindowDefinition outer commons grp schemas params from
2291−
2292−instance OrderBy WindowDefinition where
2293− orderBy sortsR (WindowDefinition parts sortsL)
2294− = WindowDefinition parts (sortsL ++ sortsR)
2295−
2296−instance RenderSQL (WindowDefinition outer commons schemas from grp params) where
2297− renderSQL (WindowDefinition part ord) =
2298− renderPartitionByClause part <> renderOrderByClause ord
2299− where
2300− renderPartitionByClause = \case
2301− Nil -> ""
2302− parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
2303− renderOrderByClause = \case
2304− [] -> ""
2305− srts -> " ORDER" <+> "BY"
2306− <+> commaSeparated (renderSQL <$> srts)
2307−
2308−{- |
2309−The `partitionBy` clause within `Squeal.PostgreSQL.Query.Over` divides the rows into groups,
2310−or partitions, that share the same values of the `partitionBy` `Expression`(s).
2311−For each row, the window function is computed across the rows that fall into
2312−the same partition as the current row.
2313−-}
2314−partitionBy
2315− :: SListI bys
2316− => NP (Expression outer commons grp schemas params from) bys
2317− -> WindowDefinition outer commons grp schemas params from
2318−partitionBy bys = WindowDefinition bys []
2319−
2320−{- |
2321−A window function performs a calculation across a set of table rows
2322−that are somehow related to the current row. This is comparable to the type
2323−of calculation that can be done with an aggregate function.
2324−However, window functions do not cause rows to become grouped into a single
2325−output row like non-window aggregate calls would.
2326−Instead, the rows retain their separate identities.
2327−Behind the scenes, the window function is able to access more than
2328−just the current row of the query result.
2329−-}
2330−newtype WindowFunction
2331− (outer :: FromType)
2332− (commons :: FromType)
2333− (grp :: Grouping)
2334− (schemas :: SchemasType)
2335− (params :: [NullityType])
2336− (from :: FromType)
2337− (ty :: NullityType)
2338− = UnsafeWindowFunction { renderWindowFunction :: ByteString }
2339− deriving (GHC.Generic,Show,Eq,Ord,NFData)
2340−
2341−instance RenderSQL (WindowFunction outer commons grp schemas params from ty) where
2342− renderSQL = renderWindowFunction
2343−
2344−type WinFun0 x
2345− = forall outer commons grp schemas params from
2346− . WindowFunction outer commons grp schemas params from x
2347− -- ^ cannot reference aliases
2348−
2349−type WinFun1 x y
2350− = forall outer commons grp schemas params from
2351− . Expression outer commons grp schemas params from x
2352− -- ^ input
2353− -> WindowFunction outer commons grp schemas params from y
2354− -- ^ output
2355−
2356−type WinFunN xs y
2357− = forall outer commons grp schemas params from
2358− . NP (Expression outer commons grp schemas params from) xs
2359− -- ^ inputs
2360− -> WindowFunction outer commons grp schemas params from y
2361− -- ^ output
2362−
2363−unsafeWindowFunction1 :: ByteString -> WinFun1 x y
2364−unsafeWindowFunction1 fun x
2365− = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x)
2366−
2367−unsafeWindowFunctionN :: SOP.SListI xs => ByteString -> WinFunN xs y
2368−unsafeWindowFunctionN fun xs = UnsafeWindowFunction $ fun <>
2369− parenthesized (renderCommaSeparated renderSQL xs)
2370−
2371−{- | rank of the current row with gaps; same as `rowNumber` of its first peer
2372−>>> printSQL rank
2373−rank()
2374−-}
2375−rank :: WinFun0 ('NotNull 'PGint8)
2376−rank = UnsafeWindowFunction "rank()"
2377−
2378−{- | number of the current row within its partition, counting from 1
2379−>>> printSQL rowNumber
2380−row_number()
2381−-}
2382−rowNumber :: WinFun0 ('NotNull 'PGint8)
2383−rowNumber = UnsafeWindowFunction "row_number()"
2384−
2385−{- | rank of the current row without gaps; this function counts peer groups
2386−>>> printSQL denseRank
2387−dense_rank()
2388−-}
2389−denseRank :: WinFun0 ('NotNull 'PGint8)
2390−denseRank = UnsafeWindowFunction "dense_rank()"
2391−
2392−{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
2393−>>> printSQL percentRank
2394−percent_rank()
2395−-}
2396−percentRank :: WinFun0 ('NotNull 'PGfloat8)
2397−percentRank = UnsafeWindowFunction "percent_rank()"
2398−
2399−{- | cumulative distribution: (number of partition rows
2400−preceding or peer with current row) / total partition rows
2401−>>> printSQL cumeDist
2402−cume_dist()
2403−-}
2404−cumeDist :: WinFun0 ('NotNull 'PGfloat8)
2405−cumeDist = UnsafeWindowFunction "cume_dist()"
2406−
2407−{- | integer ranging from 1 to the argument value,
2408−dividing the partition as equally as possible
2409−-}
2410−ntile :: WinFun1 ('NotNull 'PGint4) ('NotNull 'PGint4)
2411−ntile = unsafeWindowFunction1 "ntile"
2412−
2413−{- | returns value evaluated at the row that is offset rows before the current
2414−row within the partition; if there is no such row, instead return default
2415−(which must be of the same type as value). Both offset and default are
2416−evaluated with respect to the current row.
2417−-}
2418−lag :: WinFunN '[ty, 'NotNull 'PGint4, ty] ty
2419−lag = unsafeWindowFunctionN "lag"
2420−
2421−{- | returns value evaluated at the row that is offset rows after the current
2422−row within the partition; if there is no such row, instead return default
2423−(which must be of the same type as value). Both offset and default are
2424−evaluated with respect to the current row.
2425−-}
2426−lead :: WinFunN '[ty, 'NotNull 'PGint4, ty] ty
2427−lead = unsafeWindowFunctionN "lag"
2428−
2429−{- | returns value evaluated at the row that is the
2430−first row of the window frame
2431−-}
2432−firstValue :: WinFun1 ty ty
2433−firstValue = unsafeWindowFunction1 "first_value"
2434−
2435−{- | returns value evaluated at the row that is the
2436−last row of the window frame
2437−-}
2438−lastValue :: WinFun1 ty ty
2439−lastValue = unsafeWindowFunction1 "last_value"
2440−
2441−{- | returns value evaluated at the row that is the nth
2442−row of the window frame (counting from 1); null if no such row
2443−-}
2444−nthValue :: WinFunN '[null ty, 'NotNull 'PGint4] ('Null ty)
2445−nthValue = unsafeWindowFunctionN "nth_value"
2446−
2447−{-|
2448−Create date from year, month and day fields
2449−
2450−>>> printSQL (makeDate (1984 :* 7 *: 3))
2451−make_date(1984, 7, 3)
2452−-}
2453−makeDate :: FunctionN
2454− '[ null 'PGint4, null 'PGint4, null 'PGint4 ]
2455− ( null 'PGdate )
2456−makeDate = unsafeFunctionN "make_date"
2457−
2458−{-|
2459−Create time from hour, minute and seconds fields
2460−
2461−>>> printSQL (makeTime (8 :* 15 *: 23.5))
2462−make_time(8, 15, 23.5)
2463−-}
2464−makeTime :: FunctionN
2465− '[ null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2466− ( null 'PGtime )
2467−makeTime = unsafeFunctionN "make_time"
2468−
2469−{-|
2470−Create timestamp from year, month, day, hour, minute and seconds fields
2471−
2472−>>> printSQL (makeTimestamp (2013 :* 7 :* 15 :* 8 :* 15 *: 23.5))
2473−make_timestamp(2013, 7, 15, 8, 15, 23.5)
2474−-}
2475−makeTimestamp :: FunctionN
2476− '[ null 'PGint4, null 'PGint4, null 'PGint4
2477− , null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2478− ( null 'PGtimestamp )
2479−makeTimestamp = unsafeFunctionN "make_timestamp"
2480−
2481−{-|
2482−Create timestamp with time zone from
2483−year, month, day, hour, minute and seconds fields;
2484−the current time zone is used
2485−
2486−>>> printSQL (makeTimestamptz (2013 :* 7 :* 15 :* 8 :* 15 *: 23.5))
2487−make_timestamptz(2013, 7, 15, 8, 15, 23.5)
2488−-}
2489−makeTimestamptz :: FunctionN
2490− '[ null 'PGint4, null 'PGint4, null 'PGint4
2491− , null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2492− ( null 'PGtimestamptz )
2493−makeTimestamptz = unsafeFunctionN "make_timestamptz"
2494−
2495−{-|
2496−Affine space operations on time types.
2497−-}
2498−class TimeOp time diff | time -> diff where
2499− {-|
2500− >>> printSQL (makeDate (1984 :* 7 *: 3) !+ 365)
2501− (make_date(1984, 7, 3) + 365)
2502− -}
2503− (!+) :: Operator (null time) (null diff) (null time)
2504− (!+) = unsafeBinaryOp "+"
2505− {-|
2506− >>> printSQL (365 +! makeDate (1984 :* 7 *: 3))
2507− (365 + make_date(1984, 7, 3))
2508− -}
2509− (+!) :: Operator (null diff) (null time) (null time)
2510− (+!) = unsafeBinaryOp "+"
2511− {-|
2512− >>> printSQL (makeDate (1984 :* 7 *: 3) !- 365)
2513− (make_date(1984, 7, 3) - 365)
2514− -}
2515− (!-) :: Operator (null time) (null diff) (null time)
2516− (!-) = unsafeBinaryOp "-"
2517− {-|
2518− >>> printSQL (makeDate (1984 :* 7 *: 3) !-! currentDate)
2519− (make_date(1984, 7, 3) - CURRENT_DATE)
2520− -}
2521− (!-!) :: Operator (null time) (null time) (null diff)
2522− (!-!) = unsafeBinaryOp "-"
2523−instance TimeOp 'PGtimestamp 'PGinterval
2524−instance TimeOp 'PGtimestamptz 'PGinterval
2525−instance TimeOp 'PGtime 'PGinterval
2526−instance TimeOp 'PGtimetz 'PGinterval
2527−instance TimeOp 'PGinterval 'PGinterval
2528−instance TimeOp 'PGdate 'PGint4
2529−infixl 6 !+
2530−infixl 6 +!
2531−infixl 6 !-
2532−infixl 6 !-!
2533−
2534−data TimeUnit
2535− = Years | Months | Weeks | Days
2536− | Hours | Minutes | Seconds
2537− | Microseconds | Milliseconds
2538− | Decades | Centuries | Millennia
2539− deriving (Eq, Ord, Show, Read, Enum, GHC.Generic)
2540−instance SOP.Generic TimeUnit
2541−instance SOP.HasDatatypeInfo TimeUnit
2542−instance RenderSQL TimeUnit where
2543− renderSQL = \case
2544− Years -> "years"
2545− Months -> "months"
2546− Weeks -> "weeks"
2547− Days -> "days"
2548− Hours -> "hours"
2549− Minutes -> "minutes"
2550− Seconds -> "seconds"
2551− Microseconds -> "microseconds"
2552− Milliseconds -> "milliseconds"
2553− Decades -> "decades"
2554− Centuries -> "centuries"
2555− Millennia -> "millennia"
2556−
2557−-- | >>> printSQL $ interval_ 7 Days
2558−-- (INTERVAL '7.0 days')
2559−interval_ :: Double -> TimeUnit -> Expr (null 'PGinterval)
2560−interval_ num unit = UnsafeExpression . parenthesized $ "INTERVAL" <+>
2561− "'" <> fromString (show num) <+> renderSQL unit <> "'"
2562−
2563−class Literal hask where
2564− literal :: hask -> Expr (null (PG hask))
2565−instance JSON.ToJSON hask => Literal (Json hask) where
2566− literal = cast json . UnsafeExpression
2567− . singleQuotedUtf8 . toStrict . JSON.encode . getJson
2568−instance JSON.ToJSON hask => Literal (Jsonb hask) where
2569− literal = cast jsonb . UnsafeExpression
2570− . singleQuotedUtf8 . toStrict . JSON.encode . getJsonb
2571−instance Literal Char where
2572− literal chr = UnsafeExpression $
2573− "E\'" <> fromString (escape chr) <> "\'"
2574−instance Literal String where literal = fromString
2575−instance Literal Int16 where literal = fromIntegral
2576−instance Literal Int32 where literal = fromIntegral
2577−instance Literal Int64 where literal = fromIntegral
2578−instance Literal Float where literal = fromRational . toRational
2579−instance Literal Double where literal = fromRational . toRational
2580−instance Literal Text where literal = fromString . Text.unpack
2581−instance Literal Lazy.Text where literal = fromString . Lazy.Text.unpack