@@ -1,13 +1,14 @@
2Module: Squeal.PostgreSQL.Expression
2Module: Squeal.PostgreSQL.Expression
3Description: Squeal expressions
3Description: Squeal expressions
4−Copyright: (c) Eitan Chatav, 2019
4+Copyright: (c) Eitan Chatav, 2017
5Maintainer: eitan@morphism.tech
5Maintainer: eitan@morphism.tech
6Stability: experimental
6Stability: experimental
8Squeal expressions are the atoms used to build statements.
8Squeal expressions are the atoms used to build statements.
11+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
11{-# LANGUAGE
12{-# LANGUAGE
12 AllowAmbiguousTypes
13 AllowAmbiguousTypes
13 , ConstraintKinds
14 , ConstraintKinds
@@ -34,54 +35,254 @@ module Squeal.PostgreSQL.Expression
34 ( -- * Expression
35 ( -- * Expression
35 Expression (..)
36 Expression (..)
37− , type (-->)
38+ , (:-->)
39 , unsafeFunction
39 , unsafeFunction
40− , function
40+ , unsafeUnaryOpL
41− , unsafeLeftOp
41+ , unsafeUnaryOpR
45 , Operator
42 , Operator
47 , unsafeBinaryOp
43 , unsafeBinaryOp
49 , FunctionVar
44 , FunctionVar
50 , unsafeFunctionVar
45 , unsafeFunctionVar
51− , type (--->)
46+ , FunctionN
53 , unsafeFunctionN
47 , unsafeFunctionN
54− , functionN
48+ , Literal (..)
49+ , HasParameter (parameter)
55 , PGSubset (..)
68 , PGSubset (..)
56− , PGIntersect (..)
69+ -- * Numerical
97+ , notBetweenSymmetric
127+ -- ** Json and Jsonb operators
132+ -- ** Jsonb operators
156+ , jsonExtractPathAsText
157+ , jsonbExtractPathAsText
176+ , websearchToTSquery
191+ -- * Window Functions
192+ , WindowDefinition (..)
194+ , WindowFunction (..)
207+ , SortExpression (..)
210+ , TypeExpression (..)
237+ , timestampWithTimeZone
57 -- * Re-export
250 -- * Re-export
63import Control.Category
256import Control.Category
64import Control.DeepSeq
257import Control.DeepSeq
65import Data.ByteString (ByteString)
258import Data.ByteString (ByteString)
259+import Data.ByteString.Lazy (toStrict)
260+import ByteString.StrictBuilder (builderBytes)
66import Data.Function ((&))
261import Data.Function ((&))
67import Data.Semigroup hiding (All)
263import Data.Semigroup hiding (All)
264+import qualified Data.Aeson as JSON
68import Data.String
266import Data.String
267+import Data.Text (Text)
69import Generics.SOP hiding (All, from)
269import Generics.SOP hiding (All, from)
70import GHC.OverloadedLabels
270import GHC.OverloadedLabels
71import GHC.TypeLits
271import GHC.TypeLits
72import Numeric
272import Numeric
73import Prelude hiding (id, (.))
273import Prelude hiding (id, (.))
275+import qualified Data.ByteString as ByteString
276+import qualified Data.Text as Text
277+import qualified Data.Text.Lazy as Lazy (Text)
278+import qualified Data.Text.Lazy as Lazy.Text
75import qualified GHC.Generics as GHC
279import qualified GHC.Generics as GHC
280+import qualified Generics.SOP as SOP
77−import Squeal.PostgreSQL.Alias
282+import Squeal.PostgreSQL.Binary
78−import Squeal.PostgreSQL.List
79import Squeal.PostgreSQL.Render
283import Squeal.PostgreSQL.Render
80import Squeal.PostgreSQL.Schema
284import Squeal.PostgreSQL.Schema
83−-- >>> import Squeal.PostgreSQL
85{-----------------------------------------
286{-----------------------------------------
86column expressions
287column expressions
87-----------------------------------------}
288-----------------------------------------}
@@ -91,7 +292,7 @@ such as in the target `Squeal.PostgreSQL.Query.List` of the
91`Squeal.PostgreSQL.Query.select` command,
292`Squeal.PostgreSQL.Query.select` command,
92as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
293as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
93`Squeal.PostgreSQL.Manipulation.update`,
294`Squeal.PostgreSQL.Manipulation.update`,
94−or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
295+or in search `Condition`s in a number of commands.
96The expression syntax allows the calculation of
297The expression syntax allows the calculation of
97values from primitive expression using arithmetic, logical,
298values from primitive expression using arithmetic, logical,
@@ -125,7 +326,7 @@ instance RenderSQL (Expression outer commons grp schemas params from ty) where
125 renderSQL = renderExpression
326 renderSQL = renderExpression
127-- | An `Expr` is a closed `Expression`.
328-- | An `Expr` is a closed `Expression`.
128−-- It is a F@RankNType@ but don't be scared.
329+-- It is a F`RankNType` but don't be scared.
129-- Think of it as an expression which sees no
330-- Think of it as an expression which sees no
130-- namespaces, so you can't use parameters
331-- namespaces, so you can't use parameters
131-- or alias references. It can be used as
332-- or alias references. It can be used as
@@ -135,7 +336,7 @@ type Expr x
135 . Expression outer commons grp schemas params from x
336 . Expression outer commons grp schemas params from x
136 -- ^ cannot reference aliases
337 -- ^ cannot reference aliases
138−-- | A @RankNType@ for binary operators.
339+-- | A `RankNType` for binary operators.
139type Operator x1 x2 y
340type Operator x1 x2 y
140 = forall outer commons grp schemas params from
341 = forall outer commons grp schemas params from
141 . Expression outer commons grp schemas params from x1
342 . Expression outer commons grp schemas params from x1
@@ -145,55 +346,32 @@ type Operator x1 x2 y
145 -> Expression outer commons grp schemas params from y
346 -> Expression outer commons grp schemas params from y
146 -- ^ output
347 -- ^ output
148−type OperatorDB schemas x1 x2 y
149− = forall outer commons grp params from
150− . Expression outer commons grp schemas params from x1
152− -> Expression outer commons grp schemas params from x2
154− -> Expression outer commons grp schemas params from y
157−-- | A @RankNType@ for functions with a single argument.
349+-- | A `RankNType` for functions with a single argument.
158-- These could be either function calls or unary operators.
350-- These could be either function calls or unary operators.
159-- This is a subtype of the usual Haskell function type `Prelude.->`,
351-- This is a subtype of the usual Haskell function type `Prelude.->`,
160-- indeed a subcategory as it is closed under the usual
352-- indeed a subcategory as it is closed under the usual
161-- `Prelude..` and `Prelude.id`.
353-- `Prelude..` and `Prelude.id`.
162−type (-->) x y
354+type (:-->) x y
163 = forall outer commons grp schemas params from
355 = forall outer commons grp schemas params from
164 . Expression outer commons grp schemas params from x
356 . Expression outer commons grp schemas params from x
165 -- ^ input
357 -- ^ input
166 -> Expression outer commons grp schemas params from y
358 -> Expression outer commons grp schemas params from y
167 -- ^ output
359 -- ^ output
169−type FunctionDB schemas x y
170− = forall outer commons grp params from
171− . Expression outer commons grp schemas params from x
173− -> Expression outer commons grp schemas params from y
176−{- | A @RankNType@ for functions with a fixed-length list of heterogeneous arguments.
361+{- | A `RankNType` for functions with a fixed-length list of heterogeneous arguments.
177Use the `*:` operator to end your argument lists, like so.
362Use the `*:` operator to end your argument lists, like so.
179>>> printSQL (unsafeFunctionN "fun" (true :* false :* localTime *: true))
364>>> printSQL (unsafeFunctionN "fun" (true :* false :* localTime *: true))
180fun(TRUE, FALSE, LOCALTIME, TRUE)
365fun(TRUE, FALSE, LOCALTIME, TRUE)
182−type (--->) xs y
367+type FunctionN xs y
183 = forall outer commons grp schemas params from
368 = forall outer commons grp schemas params from
184 . NP (Expression outer commons grp schemas params from) xs
369 . NP (Expression outer commons grp schemas params from) xs
185 -- ^ inputs
370 -- ^ inputs
186 -> Expression outer commons grp schemas params from y
371 -> Expression outer commons grp schemas params from y
187 -- ^ output
372 -- ^ output
189−type FunctionNDB schemas xs y
190− = forall outer commons grp params from
191− . NP (Expression outer commons grp schemas params from) xs
193− -> Expression outer commons grp schemas params from y
196−{- | A @RankNType@ for functions with a variable-length list of
374+{- | A `RankNType` for functions with a variable-length list of
197homogeneous arguments and at least 1 more argument.
375homogeneous arguments and at least 1 more argument.
199type FunctionVar x0 x1 y
377type FunctionVar x0 x1 y
@@ -212,6 +390,46 @@ unsafeFunctionVar :: ByteString -> FunctionVar x0 x1 y
212unsafeFunctionVar fun xs x = UnsafeExpression $ fun <> parenthesized
390unsafeFunctionVar fun xs x = UnsafeExpression $ fun <> parenthesized
213 (commaSeparated (renderSQL <$> xs) <> ", " <> renderSQL x)
391 (commaSeparated (renderSQL <$> xs) <> ", " <> renderSQL x)
393+{- | A `HasParameter` constraint is used to indicate a value that is
394+supplied externally to a SQL statement.
395+`Squeal.PostgreSQL.PQ.manipulateParams`,
396+`Squeal.PostgreSQL.PQ.queryParams` and
397+`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
398+separately from the SQL command string, in which case `param`s are used to
399+refer to the out-of-line data values.
401+class KnownNat n => HasParameter
403+ (params :: [NullityType])
405+ | n params -> ty where
406+ -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
408+ -- >>> let expr = parameter @1 int4 :: Expression outer '[] grp schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
409+ -- >>> printSQL expr
412+ :: TypeExpression schemas ty
413+ -> Expression outer commons grp schemas params from ty
414+ parameter ty = UnsafeExpression $ parenthesized $
415+ "$" <> renderNat @n <+> "::"
417+instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
418+instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
419+ => HasParameter n (ty' : params) ty
421+-- | `param` takes a `Nat` using type application and for basic types,
422+-- infers a `TypeExpression`.
424+-- >>> let expr = param @1 :: Expression outer commons grp schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
428+ :: forall n outer commons schemas params from grp ty
429+ . (PGTyped schemas ty, HasParameter n params ty)
430+ => Expression outer commons grp schemas params from ty -- ^ param
431+param = parameter @n (pgtype @schemas)
215instance (HasUnique tab (Join outer from) row, Has col row ty)
433instance (HasUnique tab (Join outer from) row, Has col row ty)
216 => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
434 => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
217 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
435 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
@@ -308,73 +526,242 @@ instance
308 (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
526 (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
309 tab ! col = tab ! col :* Nil
527 tab ! col = tab ! col :* Nil
529+-- | analagous to `Nothing`
531+-- >>> printSQL null_
533+null_ :: Expr ('Null ty)
534+null_ = UnsafeExpression "NULL"
536+-- | analagous to `Just`
538+-- >>> printSQL $ notNull true
540+notNull :: 'NotNull ty :--> 'Null ty
541+notNull = UnsafeExpression . renderSQL
543+-- | return the leftmost value which is not NULL
545+-- >>> printSQL $ coalesce [null_, true] false
546+-- COALESCE(NULL, TRUE, FALSE)
547+coalesce :: FunctionVar ('Null ty) ('NotNull ty) ('NotNull ty)
548+coalesce nullxs notNullx = UnsafeExpression $
549+ "COALESCE" <> parenthesized (commaSeparated
550+ ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
552+-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
554+-- >>> printSQL $ fromNull true null_
555+-- COALESCE(NULL, TRUE)
557+ :: Expression outer commons grp schemas params from ('NotNull ty)
558+ -- ^ what to convert @NULL@ to
559+ -> Expression outer commons grp schemas params from ('Null ty)
560+ -> Expression outer commons grp schemas params from ('NotNull ty)
561+fromNull notNullx nullx = coalesce [nullx] notNullx
563+-- | >>> printSQL $ null_ & isNull
565+isNull :: 'Null ty :--> null 'PGbool
566+isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
568+-- | >>> printSQL $ null_ & isNotNull
570+isNotNull :: 'Null ty :--> null 'PGbool
571+isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
573+-- | analagous to `maybe` using @IS NULL@
575+-- >>> printSQL $ matchNull true not_ null_
576+-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
578+ :: Expression outer commons grp schemas params from (nullty)
579+ -- ^ what to convert @NULL@ to
580+ -> ( Expression outer commons grp schemas params from ('NotNull ty)
581+ -> Expression outer commons grp schemas params from (nullty) )
582+ -- ^ function to perform when @NULL@ is absent
583+ -> Expression outer commons grp schemas params from ('Null ty)
584+ -> Expression outer commons grp schemas params from (nullty)
585+matchNull y f x = ifThenElse (isNull x) y
586+ (f (UnsafeExpression (renderSQL x)))
588+{-| right inverse to `fromNull`, if its arguments are equal then
589+`nullIf` gives @NULL@.
591+>>> :set -XTypeApplications -XDataKinds
592+>>> let expr = nullIf (false *: param @1) :: Expression outer commons grp schemas '[ 'NotNull 'PGbool] from ('Null 'PGbool)
594+NULLIF(FALSE, ($1 :: bool))
596+nullIf :: FunctionN '[ 'NotNull ty, 'NotNull ty] ('Null ty)
597+nullIf = unsafeFunctionN "NULLIF"
599+-- | >>> printSQL $ array [null_, false, true]
600+-- ARRAY[NULL, FALSE, TRUE]
602+ :: [Expression outer commons grp schemas params from ty]
604+ -> Expression outer commons grp schemas params from (null ('PGvararray ty))
605+array xs = UnsafeExpression $ "ARRAY" <>
606+ bracketed (commaSeparated (renderSQL <$> xs))
608+{- | construct a 1-dimensional fixed length array
610+>>> printSQL $ array1 (null_ :* false *: true)
611+ARRAY[NULL, FALSE, TRUE]
613+>>> :type array1 (null_ :* false *: true)
614+array1 (null_ :* false *: true)
622+ (null ('PGfixarray '[3] ('Null 'PGbool)))
625+ :: (n ~ Length tys, SOP.All ((~) ty) tys)
626+ => NP (Expression outer commons grp schemas params from) tys
627+ -> Expression outer commons grp schemas params from (null ('PGfixarray '[n] ty))
628+array1 xs = UnsafeExpression $ "ARRAY" <>
629+ bracketed (renderCommaSeparated renderSQL xs)
631+{- | construct a 2-dimensional fixed length array
633+>>> printSQL $ array2 ((null_ :* false *: true) *: (false :* null_ *: true))
634+ARRAY[[NULL, FALSE, TRUE], [FALSE, NULL, TRUE]]
636+>>> :type array2 ((null_ :* false *: true) *: (false :* null_ *: true))
637+array2 ((null_ :* false *: true) *: (false :* null_ *: true))
645+ (null ('PGfixarray '[2, 3] ('Null 'PGbool)))
648+ :: ( SOP.All ((~) tys) tyss
649+ , SOP.All SOP.SListI tyss
651+ , SOP.All ((~) ty) tys
653+ => NP (NP (Expression outer commons grp schemas params from)) tyss
654+ -> Expression outer commons grp schemas params from (null ('PGfixarray '[n1,n2] ty))
655+array2 xss = UnsafeExpression $ "ARRAY" <>
656+ bracketed (renderCommaSeparatedConstraint @SOP.SListI (bracketed . renderCommaSeparated renderSQL) xss)
658+-- | >>> printSQL $ cardinality (array [null_, false, true])
659+-- cardinality(ARRAY[NULL, FALSE, TRUE])
660+cardinality :: null ('PGvararray ty) :--> null 'PGint8
661+cardinality = unsafeFunction "cardinality"
663+-- | >>> printSQL $ array [null_, false, true] & index 2
664+-- (ARRAY[NULL, FALSE, TRUE])[2]
666+ :: Word64 -- ^ index
667+ -> null ('PGvararray ty) :--> NullifyType ty
668+index n expr = UnsafeExpression $
669+ parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
671instance (KnownSymbol label, label `In` labels) => IsPGlabel label
312 (Expression outer commons grp schemas params from (null ('PGenum labels))) where
672 (Expression outer commons grp schemas params from (null ('PGenum labels))) where
313 label = UnsafeExpression $ renderSQL (PGlabel @label)
673 label = UnsafeExpression $ renderSQL (PGlabel @label)
675+-- | A row constructor is an expression that builds a row value
676+-- (also called a composite value) using values for its member fields.
679+-- type Complex = 'PGcomposite
680+-- '[ "real" ::: 'NotNull 'PGfloat8
681+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
684+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer commons grp schemas params from ('NotNull Complex)
689+ => NP (Aliased (Expression outer commons grp schemas params from)) row
690+ -- ^ zero or more expressions for the row field values
691+ -> Expression outer commons grp schemas params from (null ('PGcomposite row))
692+row exprs = UnsafeExpression $ "ROW" <> parenthesized
693+ (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
696+-- type Complex = 'PGcomposite
697+-- '[ "real" ::: 'NotNull 'PGfloat8
698+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
699+-- type Schema = '["complex" ::: 'Typedef Complex]
702+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer '[] grp (Public Schema) from params ('NotNull Complex)
703+-- >>> printSQL $ i & field #complex #imaginary
704+-- (ROW(0, 1)::"complex")."imaginary"
706+ :: ( Has sch schemas schema
707+ , Has tydef schema ('Typedef ('PGcomposite row))
709+ => QualifiedAlias sch tydef -- ^ row type
710+ -> Alias field -- ^ field name
711+ -> Expression outer commons grp schemas params from ('NotNull ('PGcomposite row))
712+ -> Expression outer commons grp schemas params from ty
713+field td fld expr = UnsafeExpression $
714+ parenthesized (renderSQL expr <> "::" <> renderSQL td)
715+ <> "." <> renderSQL fld
718+ (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
719+ (<>) = unsafeBinaryOp "||"
722+ (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
726+-- | >>> let expr = greatest [param @1] currentTimestamp :: Expression outer commons grp schemas '[ 'NotNull 'PGtimestamptz] from ('NotNull 'PGtimestamptz)
728+-- GREATEST(($1 :: timestamp with time zone), CURRENT_TIMESTAMP)
729+greatest :: FunctionVar ty ty ty
730+greatest = unsafeFunctionVar "GREATEST"
732+-- | >>> printSQL $ least [null_] currentTimestamp
733+-- LEAST(NULL, CURRENT_TIMESTAMP)
734+least :: FunctionVar ty ty ty
735+least = unsafeFunctionVar "LEAST"
315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
737-- | >>> printSQL $ unsafeBinaryOp "OR" true false
316-- (TRUE OR FALSE)
738-- (TRUE OR FALSE)
317unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
739unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
740unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
319 renderSQL x <+> op <+> renderSQL y
741 renderSQL x <+> op <+> renderSQL y
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
328−-- | >>> printSQL $ unsafeLeftOp "NOT" true
743+-- | >>> printSQL $ unsafeUnaryOpL "NOT" true
329-- (NOT TRUE)
744-- (NOT TRUE)
330−unsafeLeftOp :: ByteString -> x --> y
745+unsafeUnaryOpL :: ByteString -> x :--> y
331−unsafeLeftOp op x = UnsafeExpression $ parenthesized $ op <+> renderSQL x
746+unsafeUnaryOpL op x = UnsafeExpression $ parenthesized $ op <+> renderSQL x
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
340−-- | >>> printSQL $ true & unsafeRightOp "IS NOT TRUE"
748+-- | >>> printSQL $ true & unsafeUnaryOpR "IS NOT TRUE"
341-- (TRUE IS NOT TRUE)
749-- (TRUE IS NOT TRUE)
342−unsafeRightOp :: ByteString -> x --> y
750+unsafeUnaryOpR :: ByteString -> x :--> y
343−unsafeRightOp op x = UnsafeExpression $ parenthesized $ renderSQL x <+> op
751+unsafeUnaryOpR op x = UnsafeExpression $ parenthesized $ renderSQL x <+> op
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
352-- | >>> printSQL $ unsafeFunction "f" true
753-- | >>> printSQL $ unsafeFunction "f" true
353-- f(TRUE)
754-- f(TRUE)
354−unsafeFunction :: ByteString -> x --> y
755+unsafeFunction :: ByteString -> x :--> y
355unsafeFunction fun x = UnsafeExpression $
756unsafeFunction fun x = UnsafeExpression $
356 fun <> parenthesized (renderSQL x)
757 fun <> parenthesized (renderSQL x)
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
364-- | >>> printSQL $ unsafeFunctionN "f" (currentTime :* localTimestamp :* false *: literal 'a')
759-- | >>> printSQL $ unsafeFunctionN "f" (currentTime :* localTimestamp :* false *: literal 'a')
365-- f(CURRENT_TIME, LOCALTIMESTAMP, FALSE, E'a')
760-- f(CURRENT_TIME, LOCALTIMESTAMP, FALSE, E'a')
366−unsafeFunctionN :: SListI xs => ByteString -> xs ---> y
761+unsafeFunctionN :: SListI xs => ByteString -> FunctionN xs y
367unsafeFunctionN fun xs = UnsafeExpression $
762unsafeFunctionN fun xs = UnsafeExpression $
368 fun <> parenthesized (renderCommaSeparated renderSQL xs)
763 fun <> parenthesized (renderCommaSeparated renderSQL xs)
371− :: ( Has sch schemas schema
372− , Has fun schema ('Function (xs :=> 'Returns y))
374− => QualifiedAlias sch fun
375− -> FunctionNDB schemas xs y
376−functionN = unsafeFunctionN . renderSQL
378instance ty `In` PGNum
765instance ty `In` PGNum
379 => Num (Expression outer commons grp schemas params from (null ty)) where
766 => Num (Expression outer commons grp schemas params from (null ty)) where
380 (+) = unsafeBinaryOp "+"
767 (+) = unsafeBinaryOp "+"
@@ -419,22 +806,364 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
419 acosh x = log (x + sqrt (x*x - 1))
806 acosh x = log (x + sqrt (x*x - 1))
420 atanh x = log ((1 + x) / (1 - x)) / 2
807 atanh x = log ((1 + x) / (1 - x)) / 2
422−-- | Contained by operators
809+-- | >>> :{
423−class PGSubset ty where
810+-- let
424− (@>) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
811+-- expression :: Expr (null 'PGfloat4)
425− (@>) = unsafeBinaryOp "@>"
812+-- expression = atan2_ (pi *: 2)
426− (<@) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
813+-- in printSQL expression
427− (<@) = unsafeBinaryOp "<@"
814+-- :}
428−instance PGSubset 'PGjsonb
815+-- atan2(pi(), 2)
429−instance PGSubset 'PGtsquery
816+atan2_
430−instance PGSubset ('PGvararray ty)
817+ :: float `In` PGFloating
431−instance PGSubset ('PGrange ty)
818+ => FunctionN '[ null float, null float] (null float)
819+atan2_ = unsafeFunctionN "atan2"
821+-- When a `cast` is applied to an `Expression` of a known type, it
822+-- represents a run-time type conversion. The cast will succeed only if a
823+-- suitable type conversion operation has been defined.
825+-- | >>> printSQL $ true & cast int4
828+ :: TypeExpression schemas ty1
829+ -- ^ type to cast as
830+ -> Expression outer commons grp schemas params from ty0
831+ -- ^ value to convert
832+ -> Expression outer commons grp schemas params from ty1
833+cast ty x = UnsafeExpression $ parenthesized $
834+ renderSQL x <+> "::" <+> renderSQL ty
433−class PGIntersect ty where
836+-- | integer division, truncates the result
434− (@&&) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
837+--
840+-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
841+-- expression = 5 `quot_` 2
842+-- in printSQL expression
846+ :: int `In` PGIntegral
847+ => Operator (null int) (null int) (null int)
435− (@&&) = unsafeBinaryOp "&&"
848+quot_ = unsafeBinaryOp "/"
436−instance PGIntersect ('PGvararray ty)
849+
437−instance PGIntersect ('PGrange ty)
850+-- | remainder upon integer division
854+-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
855+-- expression = 5 `rem_` 2
856+-- in printSQL expression
860+ :: int `In` PGIntegral
861+ => Operator (null int) (null int) (null int)
862+rem_ = unsafeBinaryOp "%"
866+-- expression :: Expression outer commons grp schemas params from (null 'PGfloat4)
867+-- expression = trunc pi
868+-- in printSQL expression
871+trunc :: frac `In` PGFloating => null frac :--> null frac
872+trunc = unsafeFunction "trunc"
876+-- expression :: Expression outer commons grp schemas params from (null 'PGfloat4)
877+-- expression = round_ pi
878+-- in printSQL expression
881+round_ :: frac `In` PGFloating => null frac :--> null frac
882+round_ = unsafeFunction "round"
886+-- expression :: Expression outer commons grp schemas params from (null 'PGfloat4)
887+-- expression = ceiling_ pi
888+-- in printSQL expression
891+ceiling_ :: frac `In` PGFloating => null frac :--> null frac
892+ceiling_ = unsafeFunction "ceiling"
894+-- | A `Condition` is an `Expression`, which can evaluate
895+-- to `true`, `false` or `null_`. This is because SQL uses
896+-- a three valued logic.
897+type Condition outer commons grp schemas params from =
898+ Expression outer commons grp schemas params from ('Null 'PGbool)
900+-- | >>> printSQL true
902+true :: Expr (null 'PGbool)
903+true = UnsafeExpression "TRUE"
905+-- | >>> printSQL false
907+false :: Expr (null 'PGbool)
908+false = UnsafeExpression "FALSE"
910+-- | >>> printSQL $ not_ true
912+not_ :: null 'PGbool :--> null 'PGbool
913+not_ = unsafeUnaryOpL "NOT"
915+-- | >>> printSQL $ true .&& false
917+(.&&) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
919+(.&&) = unsafeBinaryOp "AND"
921+-- | >>> printSQL $ true .|| false
923+(.||) :: Operator (null 'PGbool) (null 'PGbool) (null 'PGbool)
925+(.||) = unsafeBinaryOp "OR"
929+-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
930+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
931+-- in printSQL expression
933+-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
935+ :: [ ( Condition outer commons grp schemas params from
936+ , Expression outer commons grp schemas params from ty
938+ -- ^ whens and thens
939+ -> Expression outer commons grp schemas params from ty
941+ -> Expression outer commons grp schemas params from ty
942+caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
946+ [ " WHEN ", renderSQL when_
947+ , " THEN ", renderSQL then_
949+ | (when_,then_) <- whenThens
951+ , " ELSE ", renderSQL else_
957+-- expression :: Expression outer commons grp schemas params from (null 'PGint2)
958+-- expression = ifThenElse true 1 0
959+-- in printSQL expression
961+-- CASE WHEN TRUE THEN 1 ELSE 0 END
963+ :: Condition outer commons grp schemas params from
964+ -> Expression outer commons grp schemas params from ty -- ^ then
965+ -> Expression outer commons grp schemas params from ty -- ^ else
966+ -> Expression outer commons grp schemas params from ty
967+ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
969+-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
970+-- will produce @NULL@s if one of their arguments is @NULL@.
972+-- >>> printSQL $ true .== null_
974+(.==) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
975+(.==) = unsafeBinaryOp "="
978+-- | >>> printSQL $ true ./= null_
980+(./=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
981+(./=) = unsafeBinaryOp "<>"
984+-- | >>> printSQL $ true .>= null_
986+(.>=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
987+(.>=) = unsafeBinaryOp ">="
990+-- | >>> printSQL $ true .< null_
992+(.<) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
993+(.<) = unsafeBinaryOp "<"
996+-- | >>> printSQL $ true .<= null_
998+(.<=) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
999+(.<=) = unsafeBinaryOp "<="
1002+-- | >>> printSQL $ true .> null_
1004+(.>) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
1005+(.>) = unsafeBinaryOp ">"
1008+{- | >>> printSQL $ true `between` (null_, false)
1009+TRUE BETWEEN NULL AND FALSE
1012+ :: Expression outer commons grp schemas params from (null ty)
1013+ -> ( Expression outer commons grp schemas params from (null ty)
1014+ , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1015+ -> Condition outer commons grp schemas params from
1016+between a (x,y) = UnsafeExpression $ renderSQL a <+> "BETWEEN"
1017+ <+> renderSQL x <+> "AND" <+> renderSQL y
1019+{- | >>> printSQL $ true `notBetween` (null_, false)
1020+TRUE NOT BETWEEN NULL AND FALSE
1023+ :: Expression outer commons grp schemas params from (null ty)
1024+ -> ( Expression outer commons grp schemas params from (null ty)
1025+ , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1026+ -> Condition outer commons grp schemas params from
1027+notBetween a (x,y) = UnsafeExpression $ renderSQL a <+> "NOT BETWEEN"
1028+ <+> renderSQL x <+> "AND" <+> renderSQL y
1030+{- | between, after sorting the comparison values
1032+>>> printSQL $ true `betweenSymmetric` (null_, false)
1033+TRUE BETWEEN SYMMETRIC NULL AND FALSE
1036+ :: Expression outer commons grp schemas params from (null ty)
1037+ -> ( Expression outer commons grp schemas params from (null ty)
1038+ , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1039+ -> Condition outer commons grp schemas params from
1040+betweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
1041+ <+> "BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
1043+{- | not between, after sorting the comparison values
1045+>>> printSQL $ true `notBetweenSymmetric` (null_, false)
1046+TRUE NOT BETWEEN SYMMETRIC NULL AND FALSE
1049+ :: Expression outer commons grp schemas params from (null ty)
1050+ -> ( Expression outer commons grp schemas params from (null ty)
1051+ , Expression outer commons grp schemas params from (null ty) ) -- ^ bounds
1052+ -> Condition outer commons grp schemas params from
1053+notBetweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
1054+ <+> "NOT BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
1056+{- | not equal, treating null like an ordinary value
1058+>>> printSQL $ true `isDistinctFrom` null_
1059+(TRUE IS DISTINCT FROM NULL)
1061+isDistinctFrom :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
1062+isDistinctFrom = unsafeBinaryOp "IS DISTINCT FROM"
1064+{- | equal, treating null like an ordinary value
1066+>>> printSQL $ true `isNotDistinctFrom` null_
1067+(TRUE IS NOT DISTINCT FROM NULL)
1069+isNotDistinctFrom :: Operator (null0 ty) (null1 ty) ('NotNull 'PGbool)
1070+isNotDistinctFrom = unsafeBinaryOp "IS NOT DISTINCT FROM"
1074+>>> printSQL $ true & isTrue
1077+isTrue :: null0 'PGbool :--> null1 'PGbool
1078+isTrue = unsafeUnaryOpR "IS TRUE"
1080+{- | is false or unknown
1082+>>> printSQL $ true & isNotTrue
1085+isNotTrue :: null0 'PGbool :--> null1 'PGbool
1086+isNotTrue = unsafeUnaryOpR "IS NOT TRUE"
1090+>>> printSQL $ true & isFalse
1093+isFalse :: null0 'PGbool :--> null1 'PGbool
1094+isFalse = unsafeUnaryOpR "IS FALSE"
1096+{- | is true or unknown
1098+>>> printSQL $ true & isNotFalse
1101+isNotFalse :: null0 'PGbool :--> null1 'PGbool
1102+isNotFalse = unsafeUnaryOpR "IS NOT FALSE"
1106+>>> printSQL $ true & isUnknown
1109+isUnknown :: null0 'PGbool :--> null1 'PGbool
1110+isUnknown = unsafeUnaryOpR "IS UNKNOWN"
1112+{- | is true or false
1114+>>> printSQL $ true & isNotUnknown
1115+(TRUE IS NOT UNKNOWN)
1117+isNotUnknown :: null0 'PGbool :--> null1 'PGbool
1118+isNotUnknown = unsafeUnaryOpR "IS NOT UNKNOWN"
1120+-- | >>> printSQL currentDate
1122+currentDate :: Expr (null 'PGdate)
1123+currentDate = UnsafeExpression "CURRENT_DATE"
1125+-- | >>> printSQL currentTime
1127+currentTime :: Expr (null 'PGtimetz)
1128+currentTime = UnsafeExpression "CURRENT_TIME"
1130+-- | >>> printSQL currentTimestamp
1131+-- CURRENT_TIMESTAMP
1132+currentTimestamp :: Expr (null 'PGtimestamptz)
1133+currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
1135+-- | >>> printSQL localTime
1137+localTime :: Expr (null 'PGtime)
1138+localTime = UnsafeExpression "LOCALTIME"
1140+-- | >>> printSQL localTimestamp
1142+localTimestamp :: Expr (null 'PGtimestamp)
1143+localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
1145+-- | Current date and time (equivalent to `currentTimestamp`)
1149+now :: Expr (null 'PGtimestamptz)
1150+now = UnsafeExpression "now()"
1152+{-----------------------------------------
1154+-----------------------------------------}
1156+escape :: Char -> String
439instance IsString
1168instance IsString
440 (Expression outer commons grp schemas params from (null 'PGtext)) where
1169 (Expression outer commons grp schemas params from (null 'PGtext)) where
@@ -442,19 +1171,13 @@ instance IsString
442 "E\'" <> fromString (escape =<< str) <> "\'"
1171 "E\'" <> fromString (escape =<< str) <> "\'"
443instance IsString
1172instance IsString
444 (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1173 (Expression outer commons grp schemas params from (null 'PGtsvector)) where
445− fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
1174+ fromString str = cast tsvector . UnsafeExpression $
446 "E\'" <> fromString (escape =<< str) <> "\'"
1175 "E\'" <> fromString (escape =<< str) <> "\'"
447instance IsString
1176instance IsString
448 (Expression outer commons grp schemas params from (null 'PGtsquery)) where
1177 (Expression outer commons grp schemas params from (null 'PGtsquery)) where
449− fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
1178+ fromString str = cast tsquery . UnsafeExpression $
450 "E\'" <> fromString (escape =<< str) <> "\'"
1179 "E\'" <> fromString (escape =<< str) <> "\'"
453− (Expression outer commons grp schemas params from (null ('PGvararray ty))) where
454− (<>) = unsafeBinaryOp "||"
456− (Expression outer commons grp schemas params from (null 'PGjsonb)) where
457− (<>) = unsafeBinaryOp "||"
458instance Semigroup
1181instance Semigroup
459 (Expression outer commons grp schemas params from (null 'PGtext)) where
1182 (Expression outer commons grp schemas params from (null 'PGtext)) where
460 (<>) = unsafeBinaryOp "||"
1183 (<>) = unsafeBinaryOp "||"
@@ -470,3 +1193,1399 @@ instance Monoid
470 (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1193 (Expression outer commons grp schemas params from (null 'PGtsvector)) where
471 mempty = fromString ""
1194 mempty = fromString ""
472 mappend = (<>)
1195 mappend = (<>)
1197+-- | >>> printSQL $ lower "ARRRGGG"
1198+-- lower(E'ARRRGGG')
1199+lower :: null 'PGtext :--> null 'PGtext
1200+lower = unsafeFunction "lower"
1202+-- | >>> printSQL $ upper "eeee"
1204+upper :: null 'PGtext :--> null 'PGtext
1205+upper = unsafeFunction "upper"
1207+-- | >>> printSQL $ charLength "four"
1208+-- char_length(E'four')
1209+charLength :: null 'PGtext :--> null 'PGint4
1210+charLength = unsafeFunction "char_length"
1212+-- | The `like` expression returns true if the @string@ matches
1213+-- the supplied @pattern@. If @pattern@ does not contain percent signs
1214+-- or underscores, then the pattern only represents the string itself;
1215+-- in that case `like` acts like the equals operator. An underscore (_)
1216+-- in pattern stands for (matches) any single character; a percent sign (%)
1217+-- matches any sequence of zero or more characters.
1219+-- >>> printSQL $ "abc" `like` "a%"
1220+-- (E'abc' LIKE E'a%')
1221+like :: Operator (null 'PGtext) (null 'PGtext) ('Null 'PGbool)
1222+like = unsafeBinaryOp "LIKE"
1224+-- | The key word ILIKE can be used instead of LIKE to make the
1225+-- match case-insensitive according to the active locale.
1227+-- >>> printSQL $ "abc" `ilike` "a%"
1228+-- (E'abc' ILIKE E'a%')
1229+ilike :: Operator (null 'PGtext) (null 'PGtext) ('Null 'PGbool)
1230+ilike = unsafeBinaryOp "ILIKE"
1232+{-----------------------------------------
1233+ -- json and jsonb support
1235+See https://www.postgresql.org/docs/10/static/functions-json.html -- most
1236+comments lifted directly from this page.
1238+Table 9.44: json and jsonb operators
1239+-----------------------------------------}
1241+-- | Get JSON value (object field or array element) at a key.
1243+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1244+ => Operator (null json) (null key) ('Null json)
1246+(.->) = unsafeBinaryOp "->"
1248+-- | Get JSON value (object field or array element) at a key, as text.
1250+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1251+ => Operator (null json) (null key) ('Null 'PGtext)
1253+(.->>) = unsafeBinaryOp "->>"
1255+-- | Get JSON value at a specified path.
1257+ :: json `In` PGJsonType
1258+ => Operator (null json) (null ('PGvararray ('NotNull 'PGtext))) ('Null json)
1260+(.#>) = unsafeBinaryOp "#>"
1262+-- | Get JSON value at a specified path as text.
1264+ :: json `In` PGJsonType
1265+ => Operator (null json) (null ('PGvararray ('NotNull 'PGtext))) ('Null 'PGtext)
1267+(.#>>) = unsafeBinaryOp "#>>"
1269+-- Additional jsonb operators
1271+class PGSubset container where
1272+ (@>) :: Operator (null0 container) (null1 container) ('Null 'PGbool)
1273+ (@>) = unsafeBinaryOp "@>"
1274+ (<@) :: Operator (null0 container) (null1 container) ('Null 'PGbool)
1275+ (<@) = unsafeBinaryOp "<@"
1276+instance PGSubset 'PGjsonb
1277+instance PGSubset 'PGtsquery
1278+instance PGSubset ('PGvararray ty)
1280+-- | Does the string exist as a top-level key within the JSON value?
1281+(.?) :: Operator (null 'PGjsonb) (null 'PGtext) ('Null 'PGbool)
1283+(.?) = unsafeBinaryOp "?"
1285+-- | Do any of these array strings exist as top-level keys?
1288+ (null ('PGvararray ('NotNull 'PGtext)))
1291+(.?|) = unsafeBinaryOp "?|"
1293+-- | Do all of these array strings exist as top-level keys?
1296+ (null ('PGvararray ('NotNull 'PGtext)))
1299+(.?&) = unsafeBinaryOp "?&"
1302+ (Expression outer commons grp schemas params from (null 'PGjsonb)) where
1303+ (<>) = unsafeBinaryOp "||"
1305+-- | Delete a key or keys from a JSON object, or remove an array element.
1307+-- If the right operand is..
1309+-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1310+-- are matched based on their key value.
1312+-- @ text[] @: Delete multiple key/value pairs or string elements
1313+-- from left operand. Key/value pairs are matched based on their key value.
1315+-- @ integer @: Delete the array element with specified index (Negative integers
1316+-- count from the end). Throws an error if top level container is not an array.
1318+ :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1319+ => Operator (null 'PGjsonb) (null key) (null 'PGjsonb)
1321+(.-.) = unsafeBinaryOp "-"
1323+-- | Delete the field or element with specified path (for JSON arrays, negative
1324+-- integers count from the end)
1325+(#-.) :: Operator (null 'PGjsonb) (null ('PGvararray ('NotNull 'PGtext))) (null 'PGjsonb)
1327+(#-.) = unsafeBinaryOp "#-"
1329+{-----------------------------------------
1330+Table 9.45: JSON creation functions
1331+-----------------------------------------}
1333+-- | Returns the value as json. Arrays and composites are converted
1334+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1335+-- type to json, the cast function will be used to perform the conversion;
1336+-- otherwise, a scalar value is produced. For any scalar type other than a
1337+-- number, a Boolean, or a null value, the text representation will be used, in
1338+-- such a fashion that it is a valid json value.
1339+toJson :: null ty :--> null 'PGjson
1340+toJson = unsafeFunction "to_json"
1342+-- | Returns the value as jsonb. Arrays and composites are converted
1343+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1344+-- type to json, the cast function will be used to perform the conversion;
1345+-- otherwise, a scalar value is produced. For any scalar type other than a
1346+-- number, a Boolean, or a null value, the text representation will be used, in
1347+-- such a fashion that it is a valid jsonb value.
1348+toJsonb :: null ty :--> null 'PGjsonb
1349+toJsonb = unsafeFunction "to_jsonb"
1351+-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1352+-- becomes a JSON array of arrays.
1353+arrayToJson :: null ('PGvararray ty) :--> null 'PGjson
1354+arrayToJson = unsafeFunction "array_to_json"
1356+-- | Returns the row as a JSON object.
1357+rowToJson :: null ('PGcomposite ty) :--> null 'PGjson
1358+rowToJson = unsafeFunction "row_to_json"
1360+-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1362+jsonBuildArray :: SListI tuple => FunctionN tuple (null 'PGjson)
1363+jsonBuildArray = unsafeFunctionN "json_build_array"
1365+-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1366+-- variadic argument list.
1367+jsonbBuildArray :: SListI tuple => FunctionN tuple (null 'PGjsonb)
1368+jsonbBuildArray = unsafeFunctionN "jsonb_build_array"
1370+class PGBuildObject tys where
1371+instance PGBuildObject '[]
1372+instance (PGBuildObject tys, key `In` PGJsonKey)
1373+ => PGBuildObject ('NotNull key ': value ': tys)
1375+-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1376+-- argument list. The elements of the argument list must alternate between text
1379+ :: (SListI elems, PGBuildObject elems)
1380+ => FunctionN elems (null 'PGjson)
1381+jsonBuildObject = unsafeFunctionN "json_build_object"
1383+-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1384+-- variadic argument list. The elements of the argument list must alternate
1385+-- between keys and values.
1387+ :: (SListI elems, PGBuildObject elems)
1388+ => FunctionN elems (null 'PGjsonb)
1389+jsonbBuildObject = unsafeFunctionN "jsonb_build_object"
1391+-- | Builds a JSON object out of a text array.
1392+-- The array must have two dimensions
1393+-- such that each inner array has exactly two elements,
1394+-- which are taken as a key/value pair.
1396+ :: null ('PGfixarray '[n,2] ('NotNull 'PGtext))
1398+jsonObject = unsafeFunction "json_object"
1400+-- | Builds a binary JSON object out of a text array.
1401+-- The array must have two dimensions
1402+-- such that each inner array has exactly two elements,
1403+-- which are taken as a key/value pair.
1405+ :: null ('PGfixarray '[n,2] ('NotNull 'PGtext))
1407+jsonbObject = unsafeFunction "jsonb_object"
1409+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1410+-- keys and one for values, that are zipped pairwise to create a JSON object.
1411+jsonZipObject :: FunctionN
1412+ '[ null ('PGvararray ('NotNull 'PGtext))
1413+ , null ('PGvararray ('NotNull 'PGtext)) ]
1415+jsonZipObject = unsafeFunctionN "json_object"
1417+-- | This is an alternate form of 'jsonbObject' that takes two arrays; one for
1418+-- keys and one for values, that are zipped pairwise to create a binary JSON
1420+jsonbZipObject :: FunctionN
1421+ '[ null ('PGvararray ('NotNull 'PGtext))
1422+ , null ('PGvararray ('NotNull 'PGtext)) ]
1424+jsonbZipObject = unsafeFunctionN "jsonb_object"
1426+{-----------------------------------------
1427+Table 9.46: JSON processing functions
1428+-----------------------------------------}
1430+-- | Returns the number of elements in the outermost JSON array.
1431+jsonArrayLength :: null 'PGjson :--> null 'PGint4
1432+jsonArrayLength = unsafeFunction "json_array_length"
1434+-- | Returns the number of elements in the outermost binary JSON array.
1435+jsonbArrayLength :: null 'PGjsonb :--> null 'PGint4
1436+jsonbArrayLength = unsafeFunction "jsonb_array_length"
1438+-- | Returns JSON value pointed to by the given path (equivalent to #>
1442+ => Expression outer commons grp schemas params from (null 'PGjson)
1443+ -> NP (Expression outer commons grp schemas params from) elems
1444+ -> Expression outer commons grp schemas params from (null 'PGjsonb)
1445+jsonExtractPath x xs =
1446+ unsafeFunctionN "json_extract_path" (x :* xs)
1448+-- | Returns JSON value pointed to by the given path (equivalent to #>
1452+ => Expression outer commons grp schemas params from (null 'PGjsonb)
1453+ -> NP (Expression outer commons grp schemas params from) elems
1454+ -> Expression outer commons grp schemas params from (null 'PGjsonb)
1455+jsonbExtractPath x xs =
1456+ unsafeFunctionN "jsonb_extract_path" (x :* xs)
1458+-- | Returns JSON value pointed to by the given path (equivalent to #>
1459+-- operator), as text.
1460+jsonExtractPathAsText
1462+ => Expression outer commons grp schemas params from (null 'PGjson)
1463+ -> NP (Expression outer commons grp schemas params from) elems
1464+ -> Expression outer commons grp schemas params from (null 'PGjson)
1465+jsonExtractPathAsText x xs =
1466+ unsafeFunctionN "json_extract_path_text" (x :* xs)
1468+-- | Returns JSON value pointed to by the given path (equivalent to #>
1469+-- operator), as text.
1470+jsonbExtractPathAsText
1472+ => Expression outer commons grp schemas params from (null 'PGjsonb)
1473+ -> NP (Expression outer commons grp schemas params from) elems
1474+ -> Expression outer commons grp schemas params from (null 'PGjsonb)
1475+jsonbExtractPathAsText x xs =
1476+ unsafeFunctionN "jsonb_extract_path_text" (x :* xs)
1478+-- | Returns the type of the outermost JSON value as a text string. Possible
1479+-- types are object, array, string, number, boolean, and null.
1480+jsonTypeof :: null 'PGjson :--> null 'PGtext
1481+jsonTypeof = unsafeFunction "json_typeof"
1483+-- | Returns the type of the outermost binary JSON value as a text string.
1484+-- Possible types are object, array, string, number, boolean, and null.
1485+jsonbTypeof :: null 'PGjsonb :--> null 'PGtext
1486+jsonbTypeof = unsafeFunction "jsonb_typeof"
1488+-- | Returns its argument with all object fields that have null values omitted.
1489+-- Other null values are untouched.
1490+jsonStripNulls :: null 'PGjson :--> null 'PGjson
1491+jsonStripNulls = unsafeFunction "json_strip_nulls"
1493+-- | Returns its argument with all object fields that have null values omitted.
1494+-- Other null values are untouched.
1495+jsonbStripNulls :: null 'PGjsonb :--> null 'PGjsonb
1496+jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1498+-- | @ jsonbSet target path new_value create_missing @
1500+-- Returns target with the section designated by path replaced by new_value,
1501+-- or with new_value added if create_missing is true ( default is true) and the
1502+-- item designated by path does not exist. As with the path orientated
1503+-- operators, negative integers that appear in path count from the end of JSON
1506+ :: Expression outer commons grp schemas params from (null 'PGjsonb)
1507+ -> Expression outer commons grp schemas params from (null ('PGvararray ('NotNull 'PGtext)))
1508+ -> Expression outer commons grp schemas params from (null 'PGjsonb)
1509+ -> Maybe (Expression outer commons grp schemas params from (null 'PGbool))
1510+ -> Expression outer commons grp schemas params from (null 'PGjsonb)
1511+jsonbSet tgt path val createMissing = case createMissing of
1512+ Just m -> unsafeFunctionN "jsonb_set" (tgt :* path :* val :* m :* Nil)
1513+ Nothing -> unsafeFunctionN "jsonb_set" (tgt :* path :* val :* Nil)
1515+-- | @ jsonbInsert target path new_value insert_after @
1517+-- Returns target with new_value inserted. If target section designated by
1518+-- path is in a JSONB array, new_value will be inserted before target or after
1519+-- if insert_after is true (default is false). If target section designated by
1520+-- path is in JSONB object, new_value will be inserted only if target does not
1521+-- exist. As with the path orientated operators, negative integers that appear
1522+-- in path count from the end of JSON arrays.
1524+ :: Expression outer commons grp schemas params from (null 'PGjsonb)
1525+ -> Expression outer commons grp schemas params from (null ('PGvararray ('NotNull 'PGtext)))
1526+ -> Expression outer commons grp schemas params from (null 'PGjsonb)
1527+ -> Maybe (Expression outer commons grp schemas params from (null 'PGbool))
1528+ -> Expression outer commons grp schemas params from (null 'PGjsonb)
1529+jsonbInsert tgt path val insertAfter = case insertAfter of
1530+ Just i -> unsafeFunctionN "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1531+ Nothing -> unsafeFunctionN "jsonb_insert" (tgt :* path :* val :* Nil)
1533+-- | Returns its argument as indented JSON text.
1534+jsonbPretty :: null 'PGjsonb :--> null 'PGtext
1535+jsonbPretty = unsafeFunction "jsonb_pretty"
1537+(@@) :: Operator (null 'PGtsvector) (null 'PGtsquery) ('Null 'PGbool)
1538+(@@) = unsafeBinaryOp "@@"
1540+(.&) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1541+(.&) = unsafeBinaryOp "&&"
1543+(.|) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1544+(.|) = unsafeBinaryOp "||"
1546+(.!) :: null 'PGtsquery :--> null 'PGtsquery
1547+(.!) = unsafeUnaryOpL "!!"
1549+(<->) :: Operator (null 'PGtsquery) (null 'PGtsquery) (null 'PGtsquery)
1550+(<->) = unsafeBinaryOp "<->"
1553+ :: null ('PGvararray ('NotNull 'PGtext))
1554+ :--> null 'PGtsvector
1555+arrayToTSvector = unsafeFunction "array_to_tsvector"
1557+tsvectorLength :: null 'PGtsvector :--> null 'PGint4
1558+tsvectorLength = unsafeFunction "length"
1560+numnode :: null 'PGtsquery :--> null 'PGint4
1561+numnode = unsafeFunction "numnode"
1563+plainToTSquery :: null 'PGtext :--> null 'PGtsquery
1564+plainToTSquery = unsafeFunction "plainto_tsquery"
1566+phraseToTSquery :: null 'PGtext :--> null 'PGtsquery
1567+phraseToTSquery = unsafeFunction "phraseto_tsquery"
1569+websearchToTSquery :: null 'PGtext :--> null 'PGtsquery
1570+websearchToTSquery = unsafeFunction "websearch_to_tsquery"
1572+queryTree :: null 'PGtsquery :--> null 'PGtext
1573+queryTree = unsafeFunction "query_tree"
1575+toTSquery :: null 'PGtext :--> null 'PGtsquery
1576+toTSquery = unsafeFunction "to_tsquery"
1579+ :: ty `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1580+ => null ty :--> null 'PGtsvector
1581+toTSvector = unsafeFunction "to_tsvector"
1584+ :: FunctionN '[null 'PGtsvector, null ('PGchar 1)] (null 'PGtsvector)
1585+setWeight = unsafeFunctionN "set_weight"
1587+strip :: null 'PGtsvector :--> null 'PGtsvector
1588+strip = unsafeFunction "strip"
1590+jsonToTSvector :: FunctionN '[null 'PGjson, null 'PGjson] (null 'PGtsvector)
1591+jsonToTSvector = unsafeFunctionN "json_to_tsvector"
1593+jsonbToTSvector :: FunctionN '[null 'PGjsonb, null 'PGjsonb] (null 'PGtsvector)
1594+jsonbToTSvector = unsafeFunctionN "jsonb_to_tsvector"
1596+tsDelete :: FunctionN
1597+ '[null 'PGtsvector, null ('PGvararray ('NotNull 'PGtext))]
1599+tsDelete = unsafeFunctionN "ts_delete"
1601+tsFilter :: FunctionN
1602+ '[null 'PGtsvector, null ('PGvararray ('NotNull ('PGchar 1)))]
1604+tsFilter = unsafeFunctionN "ts_filter"
1607+ :: document `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1608+ => FunctionN '[null document, null 'PGtsquery] (null 'PGtext)
1609+tsHeadline = unsafeFunctionN "ts_headline"
1610+{-----------------------------------------
1612+-----------------------------------------}
1616+ => ByteString -- ^ function
1617+ -> Distinction (NP (Expression outer commons 'Ungrouped schemas params from)) xs
1618+ -> Expression outer commons ('Grouped bys) schemas params from y
1619+unsafeAggregateN fun xs = UnsafeExpression $ fun <> parenthesized (renderSQL xs)
1622+`Aggregate` functions compute a single result from a set of input values.
1623+`Aggregate` functions can be used as `GroupedBy` `Expression`s as well
1624+as `WindowFunction`s.
1626+class Aggregate expr1 exprN aggr
1627+ | aggr -> expr1, aggr -> exprN where
1629+ -- | A special aggregation that does not require an input
1633+ -- expression :: Expression '[] commons ('Grouped bys) schemas params from ('NotNull 'PGint8)
1634+ -- expression = countStar
1635+ -- in printSQL expression
1638+ countStar :: aggr ('NotNull 'PGint8)
1642+ -- expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null ty]] ('NotNull 'PGint8)
1643+ -- expression = count (All #col)
1644+ -- in printSQL expression
1646+ -- count(ALL "col")
1650+ -> aggr ('NotNull 'PGint8)
1654+ -- expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('NotNull 'PGnumeric)
1655+ -- expression = sum_ (Distinct #col)
1656+ -- in printSQL expression
1658+ -- sum(DISTINCT "col")
1662+ -> aggr ('NotNull ty)
1664+ -- | input values, including nulls, concatenated into an array
1667+ -> aggr ('Null ('PGvararray ty))
1669+ -- | aggregates values as a JSON array
1672+ -> aggr ('Null 'PGjson)
1674+ -- | aggregates values as a JSON array
1677+ -> aggr ('Null 'PGjsonb)
1680+ the bitwise AND of all non-null input values, or null if none
1683+ expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGint4]] ('Null 'PGint4)
1684+ expression = bitAnd (Distinct #col)
1685+ in printSQL expression
1687+ bit_and(DISTINCT "col")
1690+ :: int `In` PGIntegral
1691+ => expr1 (null int)
1692+ -- ^ what to aggregate
1693+ -> aggr ('Null int)
1696+ the bitwise OR of all non-null input values, or null if none
1700+ expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGint4]] ('Null 'PGint4)
1701+ expression = bitOr (All #col)
1702+ in printSQL expression
1707+ :: int `In` PGIntegral
1708+ => expr1 (null int)
1709+ -- ^ what to aggregate
1710+ -> aggr ('Null int)
1713+ true if all input values are true, otherwise false
1717+ winFun :: WindowFunction '[] commons 'Ungrouped schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1718+ winFun = boolAnd #col
1724+ :: expr1 (null 'PGbool)
1725+ -- ^ what to aggregate
1726+ -> aggr ('Null 'PGbool)
1729+ true if at least one input value is true, otherwise false
1733+ expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1734+ expression = boolOr (All #col)
1735+ in printSQL expression
1740+ :: expr1 (null 'PGbool)
1741+ -- ^ what to aggregate
1742+ -> aggr ('Null 'PGbool)
1745+ equivalent to `boolAnd`
1749+ expression :: Expression '[] commons ('Grouped bys) schemas params '[tab ::: '["col" ::: null 'PGbool]] ('Null 'PGbool)
1750+ expression = every (Distinct #col)
1751+ in printSQL expression
1753+ every(DISTINCT "col")
1756+ :: expr1 (null 'PGbool)
1757+ -- ^ what to aggregate
1758+ -> aggr ('Null 'PGbool)
1760+ {- |maximum value of expression across all input values-}
1763+ -- ^ what to maximize
1766+ -- | minimum value of expression across all input values
1769+ -- ^ what to minimize
1772+ -- | the average (arithmetic mean) of all input values
1775+ -- ^ what to average
1776+ -> aggr ('Null (PGAvg ty))
1778+ {- | correlation coefficient
1781+ expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1782+ expression = corr (All (#y *: #x))
1783+ in printSQL expression
1788+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1789+ -> aggr ('Null 'PGfloat8)
1791+ {- | population covariance
1794+ expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1795+ expression = covarPop (All (#y *: #x))
1796+ in printSQL expression
1798+ covar_pop(ALL "y", "x")
1801+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1802+ -> aggr ('Null 'PGfloat8)
1804+ {- | sample covariance
1807+ winFun :: WindowFunction '[] c 'Ungrouped s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1808+ winFun = covarSamp (#y *: #x)
1811+ covar_samp("y", "x")
1814+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1815+ -> aggr ('Null 'PGfloat8)
1817+ {- | average of the independent variable (sum(X)/N)
1820+ expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1821+ expression = regrAvgX (All (#y *: #x))
1822+ in printSQL expression
1824+ regr_avgx(ALL "y", "x")
1827+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1828+ -> aggr ('Null 'PGfloat8)
1830+ {- | average of the dependent variable (sum(Y)/N)
1833+ winFun :: WindowFunction '[] c 'Ungrouped s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1834+ winFun = regrAvgY (#y *: #x)
1837+ regr_avgy("y", "x")
1840+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1841+ -> aggr ('Null 'PGfloat8)
1843+ {- | number of input rows in which both expressions are nonnull
1846+ winFun :: WindowFunction '[] c 'Ungrouped s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGint8)
1847+ winFun = regrCount (#y *: #x)
1850+ regr_count("y", "x")
1853+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1854+ -> aggr ('Null 'PGint8)
1856+ {- | y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs
1859+ expression :: Expression '[] c ('Grouped g) s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1860+ expression = regrIntercept (All (#y *: #x))
1861+ in printSQL expression
1863+ regr_intercept(ALL "y", "x")
1866+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1867+ -> aggr ('Null 'PGfloat8)
1869+ -- | @regr_r2(Y, X)@, square of the correlation coefficient
1871+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1872+ -> aggr ('Null 'PGfloat8)
1874+ -- | @regr_slope(Y, X)@, slope of the least-squares-fit linear equation
1875+ -- determined by the (X, Y) pairs
1877+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1878+ -> aggr ('Null 'PGfloat8)
1880+ -- | @regr_sxx(Y, X)@, sum(X^2) - sum(X)^2/N
1881+ -- (“sum of squares” of the independent variable)
1883+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1884+ -> aggr ('Null 'PGfloat8)
1886+ -- | @regr_sxy(Y, X)@, sum(X*Y) - sum(X) * sum(Y)/N
1887+ -- (“sum of products” of independent times dependent variable)
1889+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1890+ -> aggr ('Null 'PGfloat8)
1892+ -- | @regr_syy(Y, X)@, sum(Y^2) - sum(Y)^2/N
1893+ -- (“sum of squares” of the dependent variable)
1895+ :: exprN '[null 'PGfloat8, null 'PGfloat8]
1896+ -> aggr ('Null 'PGfloat8)
1898+ -- | historical alias for `stddevSamp`
1901+ -> aggr ('Null (PGAvg ty))
1903+ -- | population standard deviation of the input values
1906+ -> aggr ('Null (PGAvg ty))
1908+ -- | sample standard deviation of the input values
1911+ -> aggr ('Null (PGAvg ty))
1913+ -- | historical alias for `varSamp`
1916+ -> aggr ('Null (PGAvg ty))
1918+ -- | population variance of the input values
1919+ -- (square of the population standard deviation)
1922+ -> aggr ('Null (PGAvg ty))
1924+ -- | sample variance of the input values
1925+ -- (square of the sample standard deviation)
1928+ -> aggr ('Null (PGAvg ty))
1931+`Distinction`s are used for the input of `Aggregate` `Expression`s.
1932+`All` invokes the aggregate once for each input row.
1933+`Distinct` invokes the aggregate once for each distinct value of the expression
1934+(or distinct set of values, for multiple expressions) found in the input
1936+data Distinction (expr :: kind -> Type) (ty :: kind)
1938+ | Distinct (expr ty)
1939+ deriving (GHC.Generic,Show,Eq,Ord)
1940+instance NFData (Distinction (Expression outer commons grp schemas params from) ty)
1941+instance RenderSQL (Distinction (Expression outer commons grp schemas params from) ty) where
1943+ All x -> "ALL" <+> renderSQL x
1944+ Distinct x -> "DISTINCT" <+> renderSQL x
1945+instance SOP.SListI tys => RenderSQL
1946+ (Distinction (NP (Expression outer commons grp schemas params from)) tys) where
1948+ All xs -> "ALL" <+> renderCommaSeparated renderSQL xs
1949+ Distinct xs -> "DISTINCT" <+> renderCommaSeparated renderSQL xs
1952+ (Distinction (Expression outer commons 'Ungrouped schemas params from))
1953+ (Distinction (NP (Expression outer commons 'Ungrouped schemas params from)))
1954+ (Expression outer commons ('Grouped bys) schemas params from) where
1955+ countStar = UnsafeExpression "count(*)"
1956+ count = unsafeAggregate1 "count"
1957+ sum_ = unsafeAggregate1 "sum"
1958+ arrayAgg = unsafeAggregate1 "array_agg"
1959+ jsonAgg = unsafeAggregate1 "json_agg"
1960+ jsonbAgg = unsafeAggregate1 "jsonb_agg"
1961+ bitAnd = unsafeAggregate1 "bit_and"
1962+ bitOr = unsafeAggregate1 "bit_or"
1963+ boolAnd = unsafeAggregate1 "bool_and"
1964+ boolOr = unsafeAggregate1 "bool_or"
1965+ every = unsafeAggregate1 "every"
1966+ max_ = unsafeAggregate1 "max"
1967+ min_ = unsafeAggregate1 "min"
1968+ avg = unsafeAggregate1 "avg"
1969+ corr = unsafeAggregateN "corr"
1970+ covarPop = unsafeAggregateN "covar_pop"
1971+ covarSamp = unsafeAggregateN "covar_samp"
1972+ regrAvgX = unsafeAggregateN "regr_avgx"
1973+ regrAvgY = unsafeAggregateN "regr_avgy"
1974+ regrCount = unsafeAggregateN "regr_count"
1975+ regrIntercept = unsafeAggregateN "regr_intercept"
1976+ regrR2 = unsafeAggregateN "regr_r2"
1977+ regrSlope = unsafeAggregateN "regr_slope"
1978+ regrSxx = unsafeAggregateN "regr_sxx"
1979+ regrSxy = unsafeAggregateN "regr_sxy"
1980+ regrSyy = unsafeAggregateN "regr_syy"
1981+ stddev = unsafeAggregate1 "stddev"
1982+ stddevPop = unsafeAggregate1 "stddev_pop"
1983+ stddevSamp = unsafeAggregate1 "stddev_samp"
1984+ variance = unsafeAggregate1 "variance"
1985+ varPop = unsafeAggregate1 "var_pop"
1986+ varSamp = unsafeAggregate1 "var_samp"
1988+ (Expression outer commons grp schemas params from)
1989+ (NP (Expression outer commons grp schemas params from))
1990+ (WindowFunction outer commons grp schemas params from) where
1991+ countStar = UnsafeWindowFunction "count(*)"
1992+ count = unsafeWindowFunction1 "count"
1993+ sum_ = unsafeWindowFunction1 "sum"
1994+ arrayAgg = unsafeWindowFunction1 "array_agg"
1995+ jsonAgg = unsafeWindowFunction1 "json_agg"
1996+ jsonbAgg = unsafeWindowFunction1 "jsonb_agg"
1997+ bitAnd = unsafeWindowFunction1 "bit_and"
1998+ bitOr = unsafeWindowFunction1 "bit_or"
1999+ boolAnd = unsafeWindowFunction1 "bool_and"
2000+ boolOr = unsafeWindowFunction1 "bool_or"
2001+ every = unsafeWindowFunction1 "every"
2002+ max_ = unsafeWindowFunction1 "max"
2003+ min_ = unsafeWindowFunction1 "min"
2004+ avg = unsafeWindowFunction1 "avg"
2005+ corr = unsafeWindowFunctionN "corr"
2006+ covarPop = unsafeWindowFunctionN "covar_pop"
2007+ covarSamp = unsafeWindowFunctionN "covar_samp"
2008+ regrAvgX = unsafeWindowFunctionN "regr_avgx"
2009+ regrAvgY = unsafeWindowFunctionN "regr_avgy"
2010+ regrCount = unsafeWindowFunctionN "regr_count"
2011+ regrIntercept = unsafeWindowFunctionN "regr_intercept"
2012+ regrR2 = unsafeWindowFunctionN "regr_r2"
2013+ regrSlope = unsafeWindowFunctionN "regr_slope"
2014+ regrSxx = unsafeWindowFunctionN "regr_sxx"
2015+ regrSxy = unsafeWindowFunctionN "regr_sxy"
2016+ regrSyy = unsafeWindowFunctionN "regr_syy"
2017+ stddev = unsafeWindowFunction1 "stddev"
2018+ stddevPop = unsafeWindowFunction1 "stddev_pop"
2019+ stddevSamp = unsafeWindowFunction1 "stddev_samp"
2020+ variance = unsafeWindowFunction1 "variance"
2021+ varPop = unsafeWindowFunction1 "var_pop"
2022+ varSamp = unsafeWindowFunction1 "var_samp"
2024+-- | escape hatch to define aggregate functions
2026+ :: ByteString -- ^ aggregate function
2027+ -> Distinction (Expression outer commons 'Ungrouped schemas params from) x
2028+ -> Expression outer commons ('Grouped bys) schemas params from y
2029+unsafeAggregate1 fun x = UnsafeExpression $ fun <> parenthesized (renderSQL x)
2031+-- | A type family that calculates `PGAvg` type of a `PGType`.
2032+type family PGAvg ty where
2033+ PGAvg 'PGint2 = 'PGnumeric
2034+ PGAvg 'PGint4 = 'PGnumeric
2035+ PGAvg 'PGint8 = 'PGnumeric
2036+ PGAvg 'PGnumeric = 'PGnumeric
2037+ PGAvg 'PGfloat4 = 'PGfloat8
2038+ PGAvg 'PGfloat8 = 'PGfloat8
2039+ PGAvg 'PGinterval = 'PGinterval
2040+ PGAvg pg = TypeError
2041+ ('Text "Squeal type error: No average for " ':<>: 'ShowType pg)
2043+{-----------------------------------------
2045+-----------------------------------------}
2047+-- | `TypeExpression`s are used in `cast`s and
2048+-- `Squeal.PostgreSQL.Definition.createTable` commands.
2049+newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
2050+ = UnsafeTypeExpression { renderTypeExpression :: ByteString }
2051+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
2052+instance RenderSQL (TypeExpression schemas ty) where
2053+ renderSQL = renderTypeExpression
2055+-- | The enum or composite type in a `Typedef` can be expressed by its alias.
2057+ :: (Has sch schemas schema, Has td schema ('Typedef ty))
2058+ => QualifiedAlias sch td
2059+ -> TypeExpression schemas (null ty)
2060+typedef = UnsafeTypeExpression . renderSQL
2062+-- | The composite type corresponding to a `Table` definition can be expressed
2065+ :: (Has sch schemas schema, Has tab schema ('Table table))
2066+ => QualifiedAlias sch tab
2067+ -> TypeExpression schemas (null ('PGcomposite (TableToRow table)))
2068+typetable = UnsafeTypeExpression . renderSQL
2070+-- | The composite type corresponding to a `View` definition can be expressed
2073+ :: (Has sch schemas schema, Has vw schema ('View view))
2074+ => QualifiedAlias sch vw
2075+ -> TypeExpression schemas (null ('PGcomposite view))
2076+typeview = UnsafeTypeExpression . renderSQL
2078+-- | logical Boolean (true/false)
2079+bool :: TypeExpression schemas (null 'PGbool)
2080+bool = UnsafeTypeExpression "bool"
2081+-- | signed two-byte integer
2082+int2, smallint :: TypeExpression schemas (null 'PGint2)
2083+int2 = UnsafeTypeExpression "int2"
2084+smallint = UnsafeTypeExpression "smallint"
2085+-- | signed four-byte integer
2086+int4, int, integer :: TypeExpression schemas (null 'PGint4)
2087+int4 = UnsafeTypeExpression "int4"
2088+int = UnsafeTypeExpression "int"
2089+integer = UnsafeTypeExpression "integer"
2090+-- | signed eight-byte integer
2091+int8, bigint :: TypeExpression schemas (null 'PGint8)
2092+int8 = UnsafeTypeExpression "int8"
2093+bigint = UnsafeTypeExpression "bigint"
2094+-- | arbitrary precision numeric type
2095+numeric :: TypeExpression schemas (null 'PGnumeric)
2096+numeric = UnsafeTypeExpression "numeric"
2097+-- | single precision floating-point number (4 bytes)
2098+float4, real :: TypeExpression schemas (null 'PGfloat4)
2099+float4 = UnsafeTypeExpression "float4"
2100+real = UnsafeTypeExpression "real"
2101+-- | double precision floating-point number (8 bytes)
2102+float8, doublePrecision :: TypeExpression schemas (null 'PGfloat8)
2103+float8 = UnsafeTypeExpression "float8"
2104+doublePrecision = UnsafeTypeExpression "double precision"
2105+-- | currency amount
2106+money :: TypeExpression schema (null 'PGmoney)
2107+money = UnsafeTypeExpression "money"
2108+-- | variable-length character string
2109+text :: TypeExpression schemas (null 'PGtext)
2110+text = UnsafeTypeExpression "text"
2111+-- | fixed-length character string
2113+ :: forall n schemas null. (KnownNat n, 1 <= n)
2114+ => TypeExpression schemas (null ('PGchar n))
2115+char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
2116+character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
2117+-- | variable-length character string
2118+varchar, characterVarying
2119+ :: forall n schemas null. (KnownNat n, 1 <= n)
2120+ => TypeExpression schemas (null ('PGvarchar n))
2121+varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
2122+characterVarying = UnsafeTypeExpression $
2123+ "character varying(" <> renderNat @n <> ")"
2124+-- | binary data ("byte array")
2125+bytea :: TypeExpression schemas (null 'PGbytea)
2126+bytea = UnsafeTypeExpression "bytea"
2127+-- | date and time (no time zone)
2128+timestamp :: TypeExpression schemas (null 'PGtimestamp)
2129+timestamp = UnsafeTypeExpression "timestamp"
2130+-- | date and time, including time zone
2131+timestampWithTimeZone :: TypeExpression schemas (null 'PGtimestamptz)
2132+timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
2133+-- | calendar date (year, month, day)
2134+date :: TypeExpression schemas (null 'PGdate)
2135+date = UnsafeTypeExpression "date"
2136+-- | time of day (no time zone)
2137+time :: TypeExpression schemas (null 'PGtime)
2138+time = UnsafeTypeExpression "time"
2139+-- | time of day, including time zone
2140+timeWithTimeZone :: TypeExpression schemas (null 'PGtimetz)
2141+timeWithTimeZone = UnsafeTypeExpression "time with time zone"
2143+interval :: TypeExpression schemas (null 'PGinterval)
2144+interval = UnsafeTypeExpression "interval"
2145+-- | universally unique identifier
2146+uuid :: TypeExpression schemas (null 'PGuuid)
2147+uuid = UnsafeTypeExpression "uuid"
2148+-- | IPv4 or IPv6 host address
2149+inet :: TypeExpression schemas (null 'PGinet)
2150+inet = UnsafeTypeExpression "inet"
2151+-- | textual JSON data
2152+json :: TypeExpression schemas (null 'PGjson)
2153+json = UnsafeTypeExpression "json"
2154+-- | binary JSON data, decomposed
2155+jsonb :: TypeExpression schemas (null 'PGjsonb)
2156+jsonb = UnsafeTypeExpression "jsonb"
2157+-- | variable length array
2159+ :: TypeExpression schemas pg
2160+ -> TypeExpression schemas (null ('PGvararray pg))
2161+vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
2162+-- | fixed length array
2164+-- >>> renderSQL (fixarray @'[2] json)
2167+ :: forall dims schemas null pg. SOP.All KnownNat dims
2168+ => TypeExpression schemas pg
2169+ -> TypeExpression schemas (null ('PGfixarray dims pg))
2170+fixarray ty = UnsafeTypeExpression $
2171+ renderSQL ty <> renderDims @dims
2173+ renderDims :: forall ns. SOP.All KnownNat ns => ByteString
2177+ . ByteString.intercalate "]["
2179+ $ hcmap (SOP.Proxy @KnownNat)
2180+ (K . fromString . show . natVal)
2181+ (hpure SOP.Proxy :: NP SOP.Proxy ns)
2182+tsvector :: TypeExpression schemas (null 'PGtsvector)
2183+tsvector = UnsafeTypeExpression "tsvector"
2184+tsquery :: TypeExpression schemas (null 'PGtsquery)
2185+tsquery = UnsafeTypeExpression "tsquery"
2187+-- | `pgtype` is a demoted version of a `PGType`
2188+class PGTyped schemas (ty :: NullityType) where
2189+ pgtype :: TypeExpression schemas ty
2190+instance PGTyped schemas (null 'PGbool) where pgtype = bool
2191+instance PGTyped schemas (null 'PGint2) where pgtype = int2
2192+instance PGTyped schemas (null 'PGint4) where pgtype = int4
2193+instance PGTyped schemas (null 'PGint8) where pgtype = int8
2194+instance PGTyped schemas (null 'PGnumeric) where pgtype = numeric
2195+instance PGTyped schemas (null 'PGfloat4) where pgtype = float4
2196+instance PGTyped schemas (null 'PGfloat8) where pgtype = float8
2197+instance PGTyped schemas (null 'PGmoney) where pgtype = money
2198+instance PGTyped schemas (null 'PGtext) where pgtype = text
2199+instance (KnownNat n, 1 <= n)
2200+ => PGTyped schemas (null ('PGchar n)) where pgtype = char @n
2201+instance (KnownNat n, 1 <= n)
2202+ => PGTyped schemas (null ('PGvarchar n)) where pgtype = varchar @n
2203+instance PGTyped schemas (null 'PGbytea) where pgtype = bytea
2204+instance PGTyped schemas (null 'PGtimestamp) where pgtype = timestamp
2205+instance PGTyped schemas (null 'PGtimestamptz) where pgtype = timestampWithTimeZone
2206+instance PGTyped schemas (null 'PGdate) where pgtype = date
2207+instance PGTyped schemas (null 'PGtime) where pgtype = time
2208+instance PGTyped schemas (null 'PGtimetz) where pgtype = timeWithTimeZone
2209+instance PGTyped schemas (null 'PGinterval) where pgtype = interval
2210+instance PGTyped schemas (null 'PGuuid) where pgtype = uuid
2211+instance PGTyped schemas (null 'PGjson) where pgtype = json
2212+instance PGTyped schemas (null 'PGjsonb) where pgtype = jsonb
2213+instance PGTyped schemas ty
2214+ => PGTyped schemas (null ('PGvararray ty)) where
2215+ pgtype = vararray (pgtype @schemas @ty)
2216+instance (SOP.All KnownNat dims, PGTyped schemas ty)
2217+ => PGTyped schemas (null ('PGfixarray dims ty)) where
2218+ pgtype = fixarray @dims (pgtype @schemas @ty)
2219+instance PGTyped schemas (null 'PGtsvector) where pgtype = tsvector
2220+instance PGTyped schemas (null 'PGtsquery) where pgtype = tsquery
2222+{-----------------------------------------
2224+-----------------------------------------}
2226+-- | `SortExpression`s are used by `orderBy` to optionally sort the results
2227+-- of a `Squeal.PostgreSQL.Query.Query`. `Asc` or `Desc`
2228+-- set the sort direction of a `NotNull` result
2229+-- column to ascending or descending. Ascending order puts smaller values
2230+-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
2231+-- descending order is determined with the `.>` operator. `AscNullsFirst`,
2232+-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
2233+-- determine whether nulls appear before or after non-null values in the sort
2234+-- ordering of a `Null` result column.
2235+data SortExpression outer commons grp schemas params from where
2237+ :: Expression outer commons grp schemas params from ('NotNull ty)
2238+ -> SortExpression outer commons grp schemas params from
2240+ :: Expression outer commons grp schemas params from ('NotNull ty)
2241+ -> SortExpression outer commons grp schemas params from
2243+ :: Expression outer commons grp schemas params from ('Null ty)
2244+ -> SortExpression outer commons grp schemas params from
2246+ :: Expression outer commons grp schemas params from ('Null ty)
2247+ -> SortExpression outer commons grp schemas params from
2249+ :: Expression outer commons grp schemas params from ('Null ty)
2250+ -> SortExpression outer commons grp schemas params from
2252+ :: Expression outer commons grp schemas params from ('Null ty)
2253+ -> SortExpression outer commons grp schemas params from
2254+deriving instance Show (SortExpression outer commons grp schemas params from)
2257+The `orderBy` clause causes the result rows of a `Squeal.PostgreSQL.Query.TableExpression`
2258+to be sorted according to the specified `SortExpression`(s).
2259+If two rows are equal according to the leftmost expression,
2260+they are compared according to the next expression and so on.
2261+If they are equal according to all specified expressions,
2262+they are returned in an implementation-dependent order.
2264+You can also control the order in which rows are processed by window functions
2265+using `orderBy` within `Squeal.PostgreSQL.Query.Over`.
2267+class OrderBy expr where
2269+ :: [SortExpression outer commons grp schemas params from]
2270+ -> expr outer commons grp schemas params from
2271+ -> expr outer commons grp schemas params from
2273+-- | Render a `SortExpression`.
2274+instance RenderSQL (SortExpression outer commons grp schemas params from) where
2276+ Asc expression -> renderSQL expression <+> "ASC"
2277+ Desc expression -> renderSQL expression <+> "DESC"
2278+ AscNullsFirst expression -> renderSQL expression
2279+ <+> "ASC NULLS FIRST"
2280+ DescNullsFirst expression -> renderSQL expression
2281+ <+> "DESC NULLS FIRST"
2282+ AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
2283+ DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
2285+-- | A `WindowDefinition` is a set of table rows that are somehow related
2286+-- to the current row
2287+data WindowDefinition outer commons grp schemas params from where
2290+ => NP (Expression outer commons grp schemas params from) bys
2291+ -> [SortExpression outer commons grp schemas params from]
2292+ -> WindowDefinition outer commons grp schemas params from
2294+instance OrderBy WindowDefinition where
2295+ orderBy sortsR (WindowDefinition parts sortsL)
2296+ = WindowDefinition parts (sortsL ++ sortsR)
2298+instance RenderSQL (WindowDefinition outer commons schemas from grp params) where
2299+ renderSQL (WindowDefinition part ord) =
2300+ renderPartitionByClause part <> renderOrderByClause ord
2302+ renderPartitionByClause = \case
2304+ parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
2305+ renderOrderByClause = \case
2307+ srts -> " ORDER" <+> "BY"
2308+ <+> commaSeparated (renderSQL <$> srts)
2311+The `partitionBy` clause within `Squeal.PostgreSQL.Query.Over` divides the rows into groups,
2312+or partitions, that share the same values of the `partitionBy` `Expression`(s).
2313+For each row, the window function is computed across the rows that fall into
2314+the same partition as the current row.
2318+ => NP (Expression outer commons grp schemas params from) bys
2319+ -> WindowDefinition outer commons grp schemas params from
2320+partitionBy bys = WindowDefinition bys []
2323+A window function performs a calculation across a set of table rows
2324+that are somehow related to the current row. This is comparable to the type
2325+of calculation that can be done with an aggregate function.
2326+However, window functions do not cause rows to become grouped into a single
2327+output row like non-window aggregate calls would.
2328+Instead, the rows retain their separate identities.
2329+Behind the scenes, the window function is able to access more than
2330+just the current row of the query result.
2332+newtype WindowFunction
2333+ (outer :: FromType)
2334+ (commons :: FromType)
2336+ (schemas :: SchemasType)
2337+ (params :: [NullityType])
2339+ (ty :: NullityType)
2340+ = UnsafeWindowFunction { renderWindowFunction :: ByteString }
2341+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
2343+instance RenderSQL (WindowFunction outer commons grp schemas params from ty) where
2344+ renderSQL = renderWindowFunction
2347+ = forall outer commons grp schemas params from
2348+ . WindowFunction outer commons grp schemas params from x
2349+ -- ^ cannot reference aliases
2352+ = forall outer commons grp schemas params from
2353+ . Expression outer commons grp schemas params from x
2355+ -> WindowFunction outer commons grp schemas params from y
2359+ = forall outer commons grp schemas params from
2360+ . NP (Expression outer commons grp schemas params from) xs
2362+ -> WindowFunction outer commons grp schemas params from y
2365+unsafeWindowFunction1 :: ByteString -> WinFun1 x y
2366+unsafeWindowFunction1 fun x
2367+ = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x)
2369+unsafeWindowFunctionN :: SOP.SListI xs => ByteString -> WinFunN xs y
2370+unsafeWindowFunctionN fun xs = UnsafeWindowFunction $ fun <>
2371+ parenthesized (renderCommaSeparated renderSQL xs)
2373+{- | rank of the current row with gaps; same as `rowNumber` of its first peer
2377+rank :: WinFun0 ('NotNull 'PGint8)
2378+rank = UnsafeWindowFunction "rank()"
2380+{- | number of the current row within its partition, counting from 1
2381+>>> printSQL rowNumber
2384+rowNumber :: WinFun0 ('NotNull 'PGint8)
2385+rowNumber = UnsafeWindowFunction "row_number()"
2387+{- | rank of the current row without gaps; this function counts peer groups
2388+>>> printSQL denseRank
2391+denseRank :: WinFun0 ('NotNull 'PGint8)
2392+denseRank = UnsafeWindowFunction "dense_rank()"
2394+{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
2395+>>> printSQL percentRank
2398+percentRank :: WinFun0 ('NotNull 'PGfloat8)
2399+percentRank = UnsafeWindowFunction "percent_rank()"
2401+{- | cumulative distribution: (number of partition rows
2402+preceding or peer with current row) / total partition rows
2403+>>> printSQL cumeDist
2406+cumeDist :: WinFun0 ('NotNull 'PGfloat8)
2407+cumeDist = UnsafeWindowFunction "cume_dist()"
2409+{- | integer ranging from 1 to the argument value,
2410+dividing the partition as equally as possible
2412+ntile :: WinFun1 ('NotNull 'PGint4) ('NotNull 'PGint4)
2413+ntile = unsafeWindowFunction1 "ntile"
2415+{- | returns value evaluated at the row that is offset rows before the current
2416+row within the partition; if there is no such row, instead return default
2417+(which must be of the same type as value). Both offset and default are
2418+evaluated with respect to the current row.
2420+lag :: WinFunN '[ty, 'NotNull 'PGint4, ty] ty
2421+lag = unsafeWindowFunctionN "lag"
2423+{- | returns value evaluated at the row that is offset rows after the current
2424+row within the partition; if there is no such row, instead return default
2425+(which must be of the same type as value). Both offset and default are
2426+evaluated with respect to the current row.
2428+lead :: WinFunN '[ty, 'NotNull 'PGint4, ty] ty
2429+lead = unsafeWindowFunctionN "lag"
2431+{- | returns value evaluated at the row that is the
2432+first row of the window frame
2434+firstValue :: WinFun1 ty ty
2435+firstValue = unsafeWindowFunction1 "first_value"
2437+{- | returns value evaluated at the row that is the
2438+last row of the window frame
2440+lastValue :: WinFun1 ty ty
2441+lastValue = unsafeWindowFunction1 "last_value"
2443+{- | returns value evaluated at the row that is the nth
2444+row of the window frame (counting from 1); null if no such row
2446+nthValue :: WinFunN '[null ty, 'NotNull 'PGint4] ('Null ty)
2447+nthValue = unsafeWindowFunctionN "nth_value"
2450+Create date from year, month and day fields
2452+>>> printSQL (makeDate (1984 :* 7 *: 3))
2453+make_date(1984, 7, 3)
2455+makeDate :: FunctionN
2456+ '[ null 'PGint4, null 'PGint4, null 'PGint4 ]
2458+makeDate = unsafeFunctionN "make_date"
2461+Create time from hour, minute and seconds fields
2463+>>> printSQL (makeTime (8 :* 15 *: 23.5))
2464+make_time(8, 15, 23.5)
2466+makeTime :: FunctionN
2467+ '[ null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2469+makeTime = unsafeFunctionN "make_time"
2472+Create timestamp from year, month, day, hour, minute and seconds fields
2474+>>> printSQL (makeTimestamp (2013 :* 7 :* 15 :* 8 :* 15 *: 23.5))
2475+make_timestamp(2013, 7, 15, 8, 15, 23.5)
2477+makeTimestamp :: FunctionN
2478+ '[ null 'PGint4, null 'PGint4, null 'PGint4
2479+ , null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2480+ ( null 'PGtimestamp )
2481+makeTimestamp = unsafeFunctionN "make_timestamp"
2484+Create timestamp with time zone from
2485+year, month, day, hour, minute and seconds fields;
2486+the current time zone is used
2488+>>> printSQL (makeTimestamptz (2013 :* 7 :* 15 :* 8 :* 15 *: 23.5))
2489+make_timestamptz(2013, 7, 15, 8, 15, 23.5)
2491+makeTimestamptz :: FunctionN
2492+ '[ null 'PGint4, null 'PGint4, null 'PGint4
2493+ , null 'PGint4, null 'PGint4, null 'PGfloat8 ]
2494+ ( null 'PGtimestamptz )
2495+makeTimestamptz = unsafeFunctionN "make_timestamptz"
2498+Affine space operations on time types.
2500+class TimeOp time diff | time -> diff where
2502+ >>> printSQL (makeDate (1984 :* 7 *: 3) !+ 365)
2503+ (make_date(1984, 7, 3) + 365)
2505+ (!+) :: Operator (null time) (null diff) (null time)
2506+ (!+) = unsafeBinaryOp "+"
2508+ >>> printSQL (365 +! makeDate (1984 :* 7 *: 3))
2509+ (365 + make_date(1984, 7, 3))
2511+ (+!) :: Operator (null diff) (null time) (null time)
2512+ (+!) = unsafeBinaryOp "+"
2514+ >>> printSQL (makeDate (1984 :* 7 *: 3) !- 365)
2515+ (make_date(1984, 7, 3) - 365)
2517+ (!-) :: Operator (null time) (null diff) (null time)
2518+ (!-) = unsafeBinaryOp "-"
2520+ >>> printSQL (makeDate (1984 :* 7 *: 3) !-! currentDate)
2521+ (make_date(1984, 7, 3) - CURRENT_DATE)
2523+ (!-!) :: Operator (null time) (null time) (null diff)
2524+ (!-!) = unsafeBinaryOp "-"
2525+instance TimeOp 'PGtimestamp 'PGinterval
2526+instance TimeOp 'PGtimestamptz 'PGinterval
2527+instance TimeOp 'PGtime 'PGinterval
2528+instance TimeOp 'PGtimetz 'PGinterval
2529+instance TimeOp 'PGinterval 'PGinterval
2530+instance TimeOp 'PGdate 'PGint4
2537+ = Years | Months | Weeks | Days
2538+ | Hours | Minutes | Seconds
2539+ | Microseconds | Milliseconds
2540+ | Decades | Centuries | Millennia
2541+ deriving (Eq, Ord, Show, Read, Enum, GHC.Generic)
2542+instance SOP.Generic TimeUnit
2543+instance SOP.HasDatatypeInfo TimeUnit
2544+instance RenderSQL TimeUnit where
2551+ Minutes -> "minutes"
2552+ Seconds -> "seconds"
2553+ Microseconds -> "microseconds"
2554+ Milliseconds -> "milliseconds"
2555+ Decades -> "decades"
2556+ Centuries -> "centuries"
2557+ Millennia -> "millennia"
2559+-- | >>> printSQL $ interval_ 7 Days
2560+-- (INTERVAL '7.0 days')
2561+interval_ :: Double -> TimeUnit -> Expr (null 'PGinterval)
2562+interval_ num unit = UnsafeExpression . parenthesized $ "INTERVAL" <+>
2563+ "'" <> fromString (show num) <+> renderSQL unit <> "'"
2565+class Literal hask where
2566+ literal :: hask -> Expr (null (PG hask))
2567+instance JSON.ToJSON hask => Literal (Json hask) where
2568+ literal = cast json . UnsafeExpression
2569+ . singleQuotedUtf8 . toStrict . JSON.encode . getJson
2570+instance JSON.ToJSON hask => Literal (Jsonb hask) where
2571+ literal = cast jsonb . UnsafeExpression
2572+ . singleQuotedUtf8 . toStrict . JSON.encode . getJsonb
2573+instance Literal Char where
2574+ literal chr = UnsafeExpression $
2575+ "E\'" <> fromString (escape chr) <> "\'"
2576+instance Literal String where literal = fromString
2577+instance Literal Int16 where literal = fromIntegral
2578+instance Literal Int32 where literal = fromIntegral
2579+instance Literal Int64 where literal = fromIntegral
2580+instance Literal Float where literal = fromRational . toRational
2581+instance Literal Double where literal = fromRational . toRational
2582+instance Literal Text where literal = fromString . Text.unpack
2583+instance Literal Lazy.Text where literal = fromString . Lazy.Text.unpack
2584+instance ToParam (Enumerated enum) (PG (Enumerated enum))
2585+ => Literal (Enumerated enum) where
2591+ . toParam @(Enumerated enum) @(PG (Enumerated enum))