@@ -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
@@ -33,214 +34,339 @@ Squeal expressions are the atoms used to build statements.
33module Squeal.PostgreSQL.Expression
34module Squeal.PostgreSQL.Expression
34 ( -- * Expression
35 ( -- * Expression
35 Expression (..)
36 Expression (..)
36− , Expr
37+ , ClosedExpression
45 , Operator
38 , Operator
46− , OperatorDB
39+ , ComparisonOperator
40+ , HasParameter (parameter)
47 , unsafeBinaryOp
58 , unsafeBinaryOp
48− , binaryOp
59+ , unsafeUnaryOp
49− , FunctionVar
60+ , unsafeFunction
50− , unsafeFunctionVar
61+ , unsafeFunction2
51− , type (--->)
62+ , unsafeVariadicFunction
52− , FunctionNDB
63+ , atan2_
53− , unsafeFunctionN
64+ , cast
54− , functionN
65+ , quot_
55− , PGSubset (..)
66+ , rem_
56− , PGIntersect (..)
67+ , trunc
90+ , notBetweenSymmetric
117+ -- *** Json and Jsonb operators
122+ -- *** Jsonb operators
149+ , jsonExtractPathAsText
150+ , jsonbExtractPathAsText
168+ -- * Window Functions
169+ , WindowDefinition (..)
171+ , WindowFunction (..)
184+ , SortExpression (..)
187+ , TypeExpression (..)
213+ , timestampWithTimeZone
57 -- * Re-export
231 -- * Re-export
63import Control.Category
238import Control.Category
64import Control.DeepSeq
239import Control.DeepSeq
65import Data.ByteString (ByteString)
240import Data.ByteString (ByteString)
241+import Data.ByteString.Lazy (toStrict)
66import Data.Function ((&))
242import Data.Function ((&))
67import Data.Semigroup hiding (All)
243import Data.Semigroup hiding (All)
244+import qualified Data.Aeson as JSON
68import Data.String
245import Data.String
69import Generics.SOP hiding (All, from)
247import Generics.SOP hiding (All, from)
248+import GHC.Generics ((:*:) (..))
70import GHC.OverloadedLabels
249import GHC.OverloadedLabels
71import GHC.TypeLits
250import GHC.TypeLits
72import Numeric
251import Numeric
73import Prelude hiding (id, (.))
252import Prelude hiding (id, (.))
254+import qualified Data.ByteString as ByteString
75import qualified GHC.Generics as GHC
255import qualified GHC.Generics as GHC
256+import qualified Generics.SOP as SOP
77−import Squeal.PostgreSQL.Alias
78−import Squeal.PostgreSQL.List
79import Squeal.PostgreSQL.Render
258import Squeal.PostgreSQL.Render
80import Squeal.PostgreSQL.Schema
259import Squeal.PostgreSQL.Schema
83−-- >>> import Squeal.PostgreSQL
85{-----------------------------------------
261{-----------------------------------------
86column expressions
262column expressions
87-----------------------------------------}
263-----------------------------------------}
89{- | `Expression`s are used in a variety of contexts,
265{- | `Expression`s are used in a variety of contexts,
90−such as in the target `Squeal.PostgreSQL.Query.List` of the
91−`Squeal.PostgreSQL.Query.select` command,
266+such as in the target list of the `Squeal.PostgreSQL.Query.select` command,
92as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
267as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
93`Squeal.PostgreSQL.Manipulation.update`,
268`Squeal.PostgreSQL.Manipulation.update`,
94−or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
269+or in search `Condition`s in a number of commands.
96The expression syntax allows the calculation of
271The expression syntax allows the calculation of
97values from primitive expression using arithmetic, logical,
272values from primitive expression using arithmetic, logical,
98and other operations.
273and other operations.
100−The type parameters of `Expression` are
102−* @outer :: @ `FromType`, the @from@ clauses of any outer queries in which
103− the `Expression` is a correlated subquery expression;
104−* @commons :: @ `FromType`, the `Squeal.PostgreSQL.Query.CommonTableExpression`s
105− that are in scope for the `Expression`;
106−* @grp :: @ `Grouping`, the `Grouping` of the @from@ clause which may limit
107− which columns may be referenced by alias;
108−* @schemas :: @ `SchemasType`, the schemas of your database that are in
109− scope for the `Expression`;
110−* @from :: @ `FromType`, the @from@ clause which the `Expression` may use
111− to reference columns by alias;
112−* @ty :: @ `NullityType`, the type of the `Expression`.
114newtype Expression
275newtype Expression
115 (outer :: FromType)
276 (outer :: FromType)
116− (commons :: FromType)
117 (grp :: Grouping)
277 (grp :: Grouping)
278+ (commons :: FromType)
118 (schemas :: SchemasType)
279 (schemas :: SchemasType)
119 (params :: [NullityType])
280 (params :: [NullityType])
120 (from :: FromType)
281 (from :: FromType)
121 (ty :: NullityType)
282 (ty :: NullityType)
122 = UnsafeExpression { renderExpression :: ByteString }
283 = UnsafeExpression { renderExpression :: ByteString }
123 deriving (GHC.Generic,Show,Eq,Ord,NFData)
284 deriving (GHC.Generic,Show,Eq,Ord,NFData)
124−instance RenderSQL (Expression outer commons grp schemas params from ty) where
285+instance RenderSQL (Expression outer grp commons schemas params from ty) where
125 renderSQL = renderExpression
286 renderSQL = renderExpression
127−-- | An `Expr` is a closed `Expression`.
288+type ClosedExpression ty
128−-- It is a F@RankNType@ but don't be scared.
289+ = forall outer grp commons schemas params from
129−-- Think of it as an expression which sees no
290+ . Expression outer grp commons schemas params from ty
130−-- namespaces, so you can't use parameters
291+
131−-- or alias references. It can be used as
292+type Operator ty1 ty2 ty3
132−-- a simple piece of more complex `Expression`s.
293+ = forall outer grp commons schemas params from
133−type Expr x
294+ . Expression outer grp commons schemas params from ty1
134− = forall outer commons grp schemas params from
295+ -> Expression outer grp commons schemas params from ty2
135− . Expression outer commons grp schemas params from x
296+ -> Expression outer grp commons schemas params from ty3
136− -- ^ cannot reference aliases
297+
137−
298+type ComparisonOperator ty1 ty2
138−-- | A @RankNType@ for binary operators.
299+ = Operator ty1 ty2 ('Null 'PGbool)
139−type Operator x1 x2 y
300+
140− = forall outer commons grp schemas params from
301+{- | A `HasParameter` constraint is used to indicate a value that is
141− . Expression outer commons grp schemas params from x1
302+supplied externally to a SQL statement.
142− -- ^ left input
303+`Squeal.PostgreSQL.PQ.manipulateParams`,
143− -> Expression outer commons grp schemas params from x2
304+`Squeal.PostgreSQL.PQ.queryParams` and
144− -- ^ right input
305+`Squeal.PostgreSQL.PQ.traversePrepared` support specifying data values
145− -> Expression outer commons grp schemas params from y
306+separately from the SQL command string, in which case `param`s are used to
146− -- ^ output
307+refer to the out-of-line data values.
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.
158−-- These could be either function calls or unary operators.
159−-- This is a subtype of the usual Haskell function type `Prelude.->`,
160−-- indeed a subcategory as it is closed under the usual
161−-- `Prelude..` and `Prelude.id`.
163− = forall outer commons grp schemas params from
164− . Expression outer commons grp schemas params from x
166− -> Expression outer commons grp schemas params from y
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.
177−Use the `*:` operator to end your argument lists, like so.
179−>>> printSQL (unsafeFunctionN "fun" (true :* false :* localTime *: true))
180−fun(TRUE, FALSE, LOCALTIME, TRUE)
183− = forall outer commons grp schemas params from
184− . NP (Expression outer commons grp schemas params from) xs
186− -> Expression outer commons grp schemas params from y
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
197−homogeneous arguments and at least 1 more argument.
199−type FunctionVar x0 x1 y
309+class KnownNat n => HasParameter
200− = forall outer commons grp schemas params from
310+ (n :: Nat)
201− . [Expression outer commons grp schemas params from x0]
311+ (params :: [NullityType])
202− -- ^ inputs
312+ (ty :: NullityType)
203− -> Expression outer commons grp schemas params from x1
313+ | n params -> ty where
204− -- ^ must have at least 1 input
314+ -- | `parameter` takes a `Nat` using type application and a `TypeExpression`.
205− -> Expression outer commons grp schemas params from y
316+ -- >>> let expr = parameter @1 int4 :: Expression outer grp '[] schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
206− -- ^ output
317+ -- >>> printSQL expr
208−{- | >>> printSQL (unsafeFunctionVar "greatest" [true, null_] false)
319+ parameter
209−greatest(TRUE, NULL, FALSE)
320+ :: TypeExpression schemas ty
210−-}
321+ -> Expression outer grp commons schemas params from ty
211−unsafeFunctionVar :: ByteString -> FunctionVar x0 x1 y
212−unsafeFunctionVar fun xs x = UnsafeExpression $ fun <> parenthesized
322+ parameter ty = UnsafeExpression $ parenthesized $
213− (commaSeparated (renderSQL <$> xs) <> ", " <> renderSQL x)
323+ "$" <> renderNat @n <+> "::"
325+instance {-# OVERLAPPING #-} HasParameter 1 (ty1:tys) ty1
326+instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
327+ => HasParameter n (ty' : params) ty
329+-- | `param` takes a `Nat` using type application and for basic types,
330+-- infers a `TypeExpression`.
332+-- >>> let expr = param @1 :: Expression outer grp commons schemas '[ 'Null 'PGint4] from ('Null 'PGint4)
336+ :: forall n outer commons schemas params from grp ty
337+ . (PGTyped schemas ty, HasParameter n params ty)
338+ => Expression outer grp commons schemas params from ty -- ^ param
339+param = parameter @n (pgtype @schemas)
215instance (HasUnique tab (Join outer from) row, Has col row ty)
341instance (HasUnique tab (Join outer from) row, Has col row ty)
216− => IsLabel col (Expression outer commons 'Ungrouped schemas params from ty) where
342+ => IsLabel col (Expression outer 'Ungrouped commons schemas params from ty) where
217 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
343 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
218instance (HasUnique tab (Join outer from) row, Has col row ty, tys ~ '[ty])
344instance (HasUnique tab (Join outer from) row, Has col row ty, tys ~ '[ty])
219− => IsLabel col (NP (Expression outer commons 'Ungrouped schemas params from) tys) where
345+ => IsLabel col (NP (Expression outer 'Ungrouped commons schemas params from) tys) where
220 fromLabel = fromLabel @col :* Nil
346 fromLabel = fromLabel @col :* Nil
221instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
347instance (HasUnique tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
222 => IsLabel col
348 => IsLabel col
223− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
349+ (Aliased (Expression outer 'Ungrouped commons schemas params from) column) where
224 fromLabel = fromLabel @col `As` Alias
350 fromLabel = fromLabel @col `As` Alias
225instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
351instance (HasUnique tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
226 => IsLabel col
352 => IsLabel col
227− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
353+ (NP (Aliased (Expression outer 'Ungrouped commons schemas params from)) columns) where
228 fromLabel = fromLabel @col :* Nil
354 fromLabel = fromLabel @col :* Nil
230instance (Has tab (Join outer from) row, Has col row ty)
356instance (Has tab (Join outer from) row, Has col row ty)
231− => IsQualified tab col (Expression outer commons 'Ungrouped schemas params from ty) where
357+ => IsQualified tab col (Expression outer 'Ungrouped commons schemas params from ty) where
232 tab ! col = UnsafeExpression $
358 tab ! col = UnsafeExpression $
233 renderSQL tab <> "." <> renderSQL col
359 renderSQL tab <> "." <> renderSQL col
234instance (Has tab (Join outer from) row, Has col row ty, tys ~ '[ty])
360instance (Has tab (Join outer from) row, Has col row ty, tys ~ '[ty])
235− => IsQualified tab col (NP (Expression outer commons 'Ungrouped schemas params from) tys) where
361+ => IsQualified tab col (NP (Expression outer 'Ungrouped commons schemas params from) tys) where
236 tab ! col = tab ! col :* Nil
362 tab ! col = tab ! col :* Nil
237instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
363instance (Has tab (Join outer from) row, Has col row ty, column ~ (col ::: ty))
238 => IsQualified tab col
364 => IsQualified tab col
239− (Aliased (Expression outer commons 'Ungrouped schemas params from) column) where
365+ (Aliased (Expression outer 'Ungrouped commons schemas params from) column) where
240 tab ! col = tab ! col `As` col
366 tab ! col = tab ! col `As` col
241instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
367instance (Has tab (Join outer from) row, Has col row ty, columns ~ '[col ::: ty])
242 => IsQualified tab col
368 => IsQualified tab col
243− (NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns) where
369+ (NP (Aliased (Expression outer 'Ungrouped commons schemas params from)) columns) where
244 tab ! col = tab ! col :* Nil
370 tab ! col = tab ! col :* Nil
@@ -248,7 +374,7 @@ instance
248 , Has col row ty
374 , Has col row ty
249 , GroupedBy tab col bys
375 , GroupedBy tab col bys
250 ) => IsLabel col
376 ) => IsLabel col
251− (Expression outer commons ('Grouped bys) schemas params from ty) where
377+ (Expression outer ('Grouped bys) commons schemas params from ty) where
252 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
378 fromLabel = UnsafeExpression $ renderSQL (Alias @col)
254 ( HasUnique tab (Join outer from) row
380 ( HasUnique tab (Join outer from) row
@@ -256,7 +382,7 @@ instance
256 , GroupedBy tab col bys
382 , GroupedBy tab col bys
257 , tys ~ '[ty]
383 , tys ~ '[ty]
258 ) => IsLabel col
384 ) => IsLabel col
259− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
385+ (NP (Expression outer ('Grouped bys) commons schemas params from) tys) where
260 fromLabel = fromLabel @col :* Nil
386 fromLabel = fromLabel @col :* Nil
262 ( HasUnique tab (Join outer from) row
388 ( HasUnique tab (Join outer from) row
@@ -264,7 +390,7 @@ instance
264 , GroupedBy tab col bys
390 , GroupedBy tab col bys
265 , column ~ (col ::: ty)
391 , column ~ (col ::: ty)
266 ) => IsLabel col
392 ) => IsLabel col
267− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
393+ (Aliased (Expression outer ('Grouped bys) commons schemas params from) column) where
268 fromLabel = fromLabel @col `As` Alias
394 fromLabel = fromLabel @col `As` Alias
270 ( HasUnique tab (Join outer from) row
396 ( HasUnique tab (Join outer from) row
@@ -272,7 +398,7 @@ instance
272 , GroupedBy tab col bys
398 , GroupedBy tab col bys
273 , columns ~ '[col ::: ty]
399 , columns ~ '[col ::: ty]
274 ) => IsLabel col
400 ) => IsLabel col
275− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
401+ (NP (Aliased (Expression outer ('Grouped bys) commons schemas params from)) columns) where
276 fromLabel = fromLabel @col :* Nil
402 fromLabel = fromLabel @col :* Nil
@@ -280,7 +406,7 @@ instance
280 , Has col row ty
406 , Has col row ty
281 , GroupedBy tab col bys
407 , GroupedBy tab col bys
282 ) => IsQualified tab col
408 ) => IsQualified tab col
283− (Expression outer commons ('Grouped bys) schemas params from ty) where
409+ (Expression outer ('Grouped bys) commons schemas params from ty) where
284 tab ! col = UnsafeExpression $
410 tab ! col = UnsafeExpression $
285 renderSQL tab <> "." <> renderSQL col
411 renderSQL tab <> "." <> renderSQL col
@@ -289,7 +415,7 @@ instance
289 , GroupedBy tab col bys
415 , GroupedBy tab col bys
290 , tys ~ '[ty]
416 , tys ~ '[ty]
291 ) => IsQualified tab col
417 ) => IsQualified tab col
292− (NP (Expression outer commons ('Grouped bys) schemas params from) tys) where
418+ (NP (Expression outer ('Grouped bys) commons schemas params from) tys) where
293 tab ! col = tab ! col :* Nil
419 tab ! col = tab ! col :* Nil
295 ( Has tab (Join outer from) row
421 ( Has tab (Join outer from) row
@@ -297,7 +423,7 @@ instance
297 , GroupedBy tab col bys
423 , GroupedBy tab col bys
298 , column ~ (col ::: ty)
424 , column ~ (col ::: ty)
299 ) => IsQualified tab col
425 ) => IsQualified tab col
300− (Aliased (Expression outer commons ('Grouped bys) schemas params from) column) where
426+ (Aliased (Expression outer ('Grouped bys) commons schemas params from) column) where
301 tab ! col = tab ! col `As` col
427 tab ! col = tab ! col `As` col
303 ( Has tab (Join outer from) row
429 ( Has tab (Join outer from) row
@@ -305,78 +431,253 @@ instance
305 , GroupedBy tab col bys
431 , GroupedBy tab col bys
306 , columns ~ '[col ::: ty]
432 , columns ~ '[col ::: ty]
307 ) => IsQualified tab col
433 ) => IsQualified tab col
308− (NP (Aliased (Expression outer commons ('Grouped bys) schemas params from)) columns) where
434+ (NP (Aliased (Expression outer ('Grouped bys) commons schemas params from)) columns) where
309 tab ! col = tab ! col :* Nil
435 tab ! col = tab ! col :* Nil
437+-- | analagous to `Nothing`
439+-- >>> printSQL null_
441+null_ :: Expression outer grp commons schemas params from ('Null ty)
442+null_ = UnsafeExpression "NULL"
444+-- | analagous to `Just`
446+-- >>> printSQL $ notNull true
449+ :: Expression outer grp commons schemas params from ('NotNull ty)
450+ -> Expression outer grp commons schemas params from ('Null ty)
451+notNull = UnsafeExpression . renderSQL
453+-- | return the leftmost value which is not NULL
455+-- >>> printSQL $ coalesce [null_, true] false
456+-- COALESCE(NULL, TRUE, FALSE)
458+ :: [Expression outer grp commons schemas params from ('Null ty)]
459+ -- ^ @NULL@s may be present
460+ -> Expression outer grp commons schemas params from ('NotNull ty)
461+ -- ^ @NULL@ is absent
462+ -> Expression outer grp commons schemas params from ('NotNull ty)
463+coalesce nullxs notNullx = UnsafeExpression $
464+ "COALESCE" <> parenthesized (commaSeparated
465+ ((renderSQL <$> nullxs) <> [renderSQL notNullx]))
467+-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
469+-- >>> printSQL $ fromNull true null_
470+-- COALESCE(NULL, TRUE)
472+ :: Expression outer grp commons schemas params from ('NotNull ty)
473+ -- ^ what to convert @NULL@ to
474+ -> Expression outer grp commons schemas params from ('Null ty)
475+ -> Expression outer grp commons schemas params from ('NotNull ty)
476+fromNull notNullx nullx = coalesce [nullx] notNullx
478+-- | >>> printSQL $ null_ & isNull
481+ :: Expression outer grp commons schemas params from ('Null ty)
482+ -- ^ possibly @NULL@
483+ -> Condition outer grp commons schemas params from
484+isNull x = UnsafeExpression $ renderSQL x <+> "IS NULL"
486+-- | >>> printSQL $ null_ & isNotNull
489+ :: Expression outer grp commons schemas params from ('Null ty)
490+ -- ^ possibly @NULL@
491+ -> Condition outer grp commons schemas params from
492+isNotNull x = UnsafeExpression $ renderSQL x <+> "IS NOT NULL"
494+-- | analagous to `maybe` using @IS NULL@
496+-- >>> printSQL $ matchNull true not_ null_
497+-- CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END
499+ :: Expression outer grp commons schemas params from (nullty)
500+ -- ^ what to convert @NULL@ to
501+ -> ( Expression outer grp commons schemas params from ('NotNull ty)
502+ -> Expression outer grp commons schemas params from (nullty) )
503+ -- ^ function to perform when @NULL@ is absent
504+ -> Expression outer grp commons schemas params from ('Null ty)
505+ -> Expression outer grp commons schemas params from (nullty)
506+matchNull y f x = ifThenElse (isNull x) y
507+ (f (UnsafeExpression (renderSQL x)))
509+{-| right inverse to `fromNull`, if its arguments are equal then
510+`nullIf` gives @NULL@.
512+>>> :set -XTypeApplications -XDataKinds
513+>>> let expr = nullIf false (param @1) :: Expression outer grp commons schemas '[ 'NotNull 'PGbool] from ('Null 'PGbool)
515+NULL IF (FALSE, ($1 :: bool))
518+ :: Expression outer grp commons schemas params from ('NotNull ty)
519+ -- ^ @NULL@ is absent
520+ -> Expression outer grp commons schemas params from ('NotNull ty)
521+ -- ^ @NULL@ is absent
522+ -> Expression outer grp commons schemas params from ('Null ty)
523+nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
524+ (renderSQL x <> ", " <> renderSQL y)
526+-- | >>> printSQL $ array [null_, false, true]
527+-- ARRAY[NULL, FALSE, TRUE]
529+ :: [Expression outer grp commons schemas params from ty]
531+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ty))
532+array xs = UnsafeExpression $
533+ "ARRAY[" <> commaSeparated (renderSQL <$> xs) <> "]"
535+-- | >>> printSQL $ cardinality (array [null_, false, true])
536+-- cardinality(ARRAY[NULL, FALSE, TRUE])
538+ :: Expression outer grp commons schemas params from (nullity ('PGvararray ty))
539+ -> Expression outer grp commons schemas params from (nullity 'PGint8)
540+cardinality = unsafeFunction "cardinality"
542+-- | >>> printSQL $ array [null_, false, true] & index 2
543+-- (ARRAY[NULL, FALSE, TRUE])[2]
545+ :: Word64 -- ^ index
546+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ty)) -- ^ array
547+ -> Expression outer grp commons schemas params from (NullifyType ty)
548+index n expr = UnsafeExpression $
549+ parenthesized (renderSQL expr) <> "[" <> fromString (show n) <> "]"
311instance (KnownSymbol label, label `In` labels) => IsPGlabel label
551instance (KnownSymbol label, label `In` labels) => IsPGlabel label
312− (Expression outer commons grp schemas params from (null ('PGenum labels))) where
552+ (Expression outer grp commons schemas params from (nullity ('PGenum labels))) where
313 label = UnsafeExpression $ renderSQL (PGlabel @label)
553 label = UnsafeExpression $ renderSQL (PGlabel @label)
555+-- | A row constructor is an expression that builds a row value
556+-- (also called a composite value) using values for its member fields.
559+-- type Complex = 'PGcomposite
560+-- '[ "real" ::: 'NotNull 'PGfloat8
561+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
564+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer grp commons schemas params from ('NotNull Complex)
569+ => NP (Aliased (Expression outer grp commons schemas params from)) row
570+ -- ^ zero or more expressions for the row field values
571+ -> Expression outer grp commons schemas params from (nullity ('PGcomposite row))
572+row exprs = UnsafeExpression $ "ROW" <> parenthesized
573+ (renderCommaSeparated (\ (expr `As` _) -> renderSQL expr) exprs)
576+-- type Complex = 'PGcomposite
577+-- '[ "real" ::: 'NotNull 'PGfloat8
578+-- , "imaginary" ::: 'NotNull 'PGfloat8 ]
579+-- type Schema = '["complex" ::: 'Typedef Complex]
582+-- >>> let i = row (0 `as` #real :* 1 `as` #imaginary) :: Expression outer grp '[] (Public Schema) from params ('NotNull Complex)
583+-- >>> printSQL $ i & field #complex #imaginary
584+-- (ROW(0, 1)::"complex")."imaginary"
586+ :: ( Has sch schemas schema
587+ , Has tydef schema ('Typedef ('PGcomposite row))
589+ => QualifiedAlias sch tydef -- ^ row type
590+ -> Alias field -- ^ field name
591+ -> Expression outer grp commons schemas params from ('NotNull ('PGcomposite row))
592+ -> Expression outer grp commons schemas params from ty
593+field td fld expr = UnsafeExpression $
594+ parenthesized (renderSQL expr <> "::" <> renderSQL td)
595+ <> "." <> renderSQL fld
598+ (Expression outer grp commons schemas params from (nullity ('PGvararray ty))) where
599+ (<>) = unsafeBinaryOp "||"
602+ (Expression outer grp commons schemas params from (nullity ('PGvararray ty))) where
606+-- | >>> let expr = greatest currentTimestamp [param @1] :: Expression outer grp commons schemas '[ 'NotNull 'PGtimestamptz] from ('NotNull 'PGtimestamptz)
608+-- GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))
610+ :: Expression outer grp commons schemas params from (nullty)
611+ -- ^ needs at least 1 argument
612+ -> [Expression outer grp commons schemas params from (nullty)]
614+ -> Expression outer grp commons schemas params from (nullty)
615+greatest x xs = UnsafeExpression $ "GREATEST("
616+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
618+-- | >>> printSQL $ least currentTimestamp [null_]
619+-- LEAST(CURRENT_TIMESTAMP, NULL)
621+ :: Expression outer grp commons schemas params from (nullty)
622+ -- ^ needs at least 1 argument
623+ -> [Expression outer grp commons schemas params from (nullty)]
625+ -> Expression outer grp commons schemas params from (nullty)
626+least x xs = UnsafeExpression $ "LEAST("
627+ <> commaSeparated (renderSQL <$> (x:xs)) <> ")"
315-- | >>> printSQL $ unsafeBinaryOp "OR" true false
629-- | >>> printSQL $ unsafeBinaryOp "OR" true false
316-- (TRUE OR FALSE)
630-- (TRUE OR FALSE)
317−unsafeBinaryOp :: ByteString -> Operator ty0 ty1 ty2
631+unsafeBinaryOp
634+ -> Expression outer grp commons schemas params from (ty0)
635+ -> Expression outer grp commons schemas params from (ty1)
636+ -> Expression outer grp commons schemas params from (ty2)
318unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
637unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
319 renderSQL x <+> op <+> renderSQL y
638 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
640+-- | >>> printSQL $ unsafeUnaryOp "NOT" true
329-- (NOT TRUE)
641-- (NOT TRUE)
330−unsafeLeftOp :: ByteString -> x --> y
643+ :: ByteString
331−unsafeLeftOp op x = UnsafeExpression $ parenthesized $ op <+> renderSQL x
644+ -- ^ operator
332−
645+ -> Expression outer grp commons schemas params from (ty0)
333−leftOp
646+ -> Expression outer grp commons schemas params from (ty1)
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"
341−-- (TRUE IS NOT TRUE)
342−unsafeRightOp :: ByteString -> x --> y
343−unsafeRightOp op x = UnsafeExpression $ parenthesized $ renderSQL x <+> op
647+unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
344−
648+ op <+> renderSQL x
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
650-- | >>> printSQL $ unsafeFunction "f" true
353-- f(TRUE)
651-- f(TRUE)
354−unsafeFunction :: ByteString -> x --> y
652+unsafeFunction
655+ -> Expression outer grp commons schemas params from xty
656+ -> Expression outer grp commons schemas params from yty
355unsafeFunction fun x = UnsafeExpression $
657unsafeFunction fun x = UnsafeExpression $
356 fun <> parenthesized (renderSQL x)
658 fun <> parenthesized (renderSQL x)
358−function
660+unsafeFunction2
359− :: (Has sch schemas schema, Has fun schema ('Function ('[x] :=> 'Returns y)))
661+ :: ByteString
360− => QualifiedAlias sch fun
662+ -- ^ function
361− -> FunctionDB schemas x y
663+ -> Expression outer grp commons schemas params from ty1
362−function = unsafeFunction . renderSQL
664+ -> Expression outer grp commons schemas params from ty2
665+ -> Expression outer grp commons schemas params from ty
666+unsafeFunction2 fun x1 x2 = UnsafeExpression $
667+ fun <> parenthesized (commaSeparated [renderSQL x1, renderSQL x2])
364−-- | >>> printSQL $ unsafeFunctionN "f" (currentTime :* localTimestamp :* false *: literal 'a')
669+-- | Helper for defining variadic functions.
365−-- f(CURRENT_TIME, LOCALTIMESTAMP, FALSE, E'a')
670+unsafeVariadicFunction
366−unsafeFunctionN :: SListI xs => ByteString -> xs ---> y
672+ => ByteString
674+ -> NP (Expression outer grp commons schemas params from) elems
675+ -> Expression outer grp commons schemas params from ret
367−unsafeFunctionN fun xs = UnsafeExpression $
676+unsafeVariadicFunction fun x = UnsafeExpression $
368− fun <> parenthesized (renderCommaSeparated renderSQL xs)
677+ fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderSQL) x)))
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
679instance ty `In` PGNum
379− => Num (Expression outer commons grp schemas params from (null ty)) where
680+ => Num (Expression outer grp commons schemas params from (nullity ty)) where
380 (+) = unsafeBinaryOp "+"
681 (+) = unsafeBinaryOp "+"
381 (-) = unsafeBinaryOp "-"
682 (-) = unsafeBinaryOp "-"
382 (*) = unsafeBinaryOp "*"
683 (*) = unsafeBinaryOp "*"
@@ -388,7 +689,7 @@ instance ty `In` PGNum
390instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
691instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
391− (Expression outer commons grp schemas params from (null ty)) where
692+ (Expression outer grp commons schemas params from (nullity ty)) where
392 (/) = unsafeBinaryOp "/"
693 (/) = unsafeBinaryOp "/"
393 fromRational
694 fromRational
394 = UnsafeExpression
695 = UnsafeExpression
@@ -398,7 +699,7 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
398 . fromRat @Double
699 . fromRat @Double
400instance (ty `In` PGNum, ty `In` PGFloating) => Floating
701instance (ty `In` PGNum, ty `In` PGFloating) => Floating
401− (Expression outer commons grp schemas params from (null ty)) where
702+ (Expression outer grp commons schemas params from (nullity ty)) where
402 pi = UnsafeExpression "pi()"
703 pi = UnsafeExpression "pi()"
403 exp = unsafeFunction "exp"
704 exp = unsafeFunction "exp"
404 log = unsafeFunction "ln"
705 log = unsafeFunction "ln"
@@ -419,54 +720,1974 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
419 acosh x = log (x + sqrt (x*x - 1))
720 acosh x = log (x + sqrt (x*x - 1))
420 atanh x = log ((1 + x) / (1 - x)) / 2
721 atanh x = log ((1 + x) / (1 - x)) / 2
422−-- | Contained by operators
723+-- | >>> :{
423−class PGSubset ty where
724+-- let
424− (@>) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
725+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
425− (@>) = unsafeBinaryOp "@>"
726+-- expression = atan2_ pi 2
426− (<@) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
727+-- in printSQL expression
427− (<@) = unsafeBinaryOp "<@"
728+-- :}
428−instance PGSubset 'PGjsonb
729+-- atan2(pi(), 2)
429−instance PGSubset 'PGtsquery
730+atan2_
430−instance PGSubset ('PGvararray ty)
731+ :: float `In` PGFloating
431−instance PGSubset ('PGrange ty)
732+ => Expression outer grp commons schemas params from (nullity float)
433−class PGIntersect ty where
734+ -> Expression outer grp commons schemas params from (nullity float)
434− (@&&) :: Operator (null0 ty) (null1 ty) ('Null 'PGbool)
735+ -- ^ denominator
435− (@&&) = unsafeBinaryOp "&&"
736+ -> Expression outer grp commons schemas params from (nullity float)
436−instance PGIntersect ('PGvararray ty)
737+atan2_ y x = UnsafeExpression $
437−instance PGIntersect ('PGrange ty)
738+ "atan2(" <> renderSQL y <> ", " <> renderSQL x <> ")"
740+-- When a `cast` is applied to an `Expression` of a known type, it
741+-- represents a run-time type conversion. The cast will succeed only if a
742+-- suitable type conversion operation has been defined.
744+-- | >>> printSQL $ true & cast int4
747+ :: TypeExpression schemas ty1
748+ -- ^ type to cast as
749+ -> Expression outer grp commons schemas params from ty0
750+ -- ^ value to convert
751+ -> Expression outer grp commons schemas params from ty1
752+cast ty x = UnsafeExpression $ parenthesized $
753+ renderSQL x <+> "::" <+> renderSQL ty
755+-- | integer division, truncates the result
759+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
760+-- expression = 5 `quot_` 2
761+-- in printSQL expression
765+ :: int `In` PGIntegral
766+ => Expression outer grp commons schemas params from (nullity int)
768+ -> Expression outer grp commons schemas params from (nullity int)
770+ -> Expression outer grp commons schemas params from (nullity int)
771+quot_ = unsafeBinaryOp "/"
773+-- | remainder upon integer division
777+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
778+-- expression = 5 `rem_` 2
779+-- in printSQL expression
783+ :: int `In` PGIntegral
784+ => Expression outer grp commons schemas params from (nullity int)
786+ -> Expression outer grp commons schemas params from (nullity int)
788+ -> Expression outer grp commons schemas params from (nullity int)
789+rem_ = unsafeBinaryOp "%"
793+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
794+-- expression = trunc pi
795+-- in printSQL expression
799+ :: frac `In` PGFloating
800+ => Expression outer grp commons schemas params from (nullity frac)
801+ -- ^ fractional number
802+ -> Expression outer grp commons schemas params from (nullity frac)
803+trunc = unsafeFunction "trunc"
807+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
808+-- expression = round_ pi
809+-- in printSQL expression
813+ :: frac `In` PGFloating
814+ => Expression outer grp commons schemas params from (nullity frac)
815+ -- ^ fractional number
816+ -> Expression outer grp commons schemas params from (nullity frac)
817+round_ = unsafeFunction "round"
821+-- expression :: Expression outer grp commons schemas params from (nullity 'PGfloat4)
822+-- expression = ceiling_ pi
823+-- in printSQL expression
827+ :: frac `In` PGFloating
828+ => Expression outer grp commons schemas params from (nullity frac)
829+ -- ^ fractional number
830+ -> Expression outer grp commons schemas params from (nullity frac)
831+ceiling_ = unsafeFunction "ceiling"
833+-- | A `Condition` is an `Expression`, which can evaluate
834+-- to `true`, `false` or `null_`. This is because SQL uses
835+-- a three valued logic.
836+type Condition outer grp commons schemas params from =
837+ Expression outer grp commons schemas params from ('Null 'PGbool)
839+-- | >>> printSQL true
841+true :: Expression outer grp commons schemas params from (nullity 'PGbool)
842+true = UnsafeExpression "TRUE"
844+-- | >>> printSQL false
846+false :: Expression outer grp commons schemas params from (nullity 'PGbool)
847+false = UnsafeExpression "FALSE"
849+-- | >>> printSQL $ not_ true
852+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
853+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
854+not_ = unsafeUnaryOp "NOT"
856+-- | >>> printSQL $ true .&& false
859+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
860+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
861+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
863+(.&&) = unsafeBinaryOp "AND"
865+-- | >>> printSQL $ true .|| false
868+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
869+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
870+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
872+(.||) = unsafeBinaryOp "OR"
876+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
877+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
878+-- in printSQL expression
880+-- CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END
882+ :: [ ( Condition outer grp commons schemas params from
883+ , Expression outer grp commons schemas params from ty
885+ -- ^ whens and thens
886+ -> Expression outer grp commons schemas params from ty
888+ -> Expression outer grp commons schemas params from ty
889+caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
893+ [ " WHEN ", renderSQL when_
894+ , " THEN ", renderSQL then_
896+ | (when_,then_) <- whenThens
898+ , " ELSE ", renderSQL else_
904+-- expression :: Expression outer grp commons schemas params from (nullity 'PGint2)
905+-- expression = ifThenElse true 1 0
906+-- in printSQL expression
908+-- CASE WHEN TRUE THEN 1 ELSE 0 END
910+ :: Condition outer grp commons schemas params from
911+ -> Expression outer grp commons schemas params from ty -- ^ then
912+ -> Expression outer grp commons schemas params from ty -- ^ else
913+ -> Expression outer grp commons schemas params from ty
914+ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
916+-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
917+-- will produce @NULL@s if one of their arguments is @NULL@.
919+-- >>> printSQL $ true .== null_
922+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
923+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
924+ -> Condition outer grp commons schemas params from
925+(.==) = unsafeBinaryOp "="
928+-- | >>> printSQL $ true ./= null_
931+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
932+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
933+ -> Condition outer grp commons schemas params from
934+(./=) = unsafeBinaryOp "<>"
937+-- | >>> printSQL $ true .>= null_
940+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
941+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
942+ -> Condition outer grp commons schemas params from
943+(.>=) = unsafeBinaryOp ">="
946+-- | >>> printSQL $ true .< null_
949+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
950+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
951+ -> Condition outer grp commons schemas params from
952+(.<) = unsafeBinaryOp "<"
955+-- | >>> printSQL $ true .<= null_
958+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
959+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
960+ -> Condition outer grp commons schemas params from
961+(.<=) = unsafeBinaryOp "<="
964+-- | >>> printSQL $ true .> null_
967+ :: Expression outer grp commons schemas params from (nullity0 ty) -- ^ lhs
968+ -> Expression outer grp commons schemas params from (nullity1 ty) -- ^ rhs
969+ -> Condition outer grp commons schemas params from
970+(.>) = unsafeBinaryOp ">"
974+>>> printSQL $ true `between` (null_, false)
975+TRUE BETWEEN NULL AND FALSE
978+ :: Expression outer grp commons schemas params from (nullity ty)
979+ -> ( Expression outer grp commons schemas params from (nullity ty)
980+ , Expression outer grp commons schemas params from (nullity ty) ) -- ^ bounds
981+ -> Condition outer grp commons schemas params from
982+between a (x,y) = UnsafeExpression $ renderSQL a <+> "BETWEEN"
983+ <+> renderSQL x <+> "AND" <+> renderSQL y
986+>>> printSQL $ true `notBetween` (null_, false)
987+TRUE NOT BETWEEN NULL AND FALSE
990+ :: Expression outer grp commons schemas params from (nullity ty)
991+ -> ( Expression outer grp commons schemas params from (nullity ty)
992+ , Expression outer grp commons schemas params from (nullity ty) ) -- ^ bounds
993+ -> Condition outer grp commons schemas params from
994+notBetween a (x,y) = UnsafeExpression $ renderSQL a <+> "NOT BETWEEN"
995+ <+> renderSQL x <+> "AND" <+> renderSQL y
997+{- | between, after sorting the comparison values
998+>>> printSQL $ true `betweenSymmetric` (null_, false)
999+TRUE BETWEEN SYMMETRIC NULL AND FALSE
1002+ :: Expression outer grp commons schemas params from (nullity ty)
1003+ -> ( Expression outer grp commons schemas params from (nullity ty)
1004+ , Expression outer grp commons schemas params from (nullity ty) ) -- ^ bounds
1005+ -> Condition outer grp commons schemas params from
1006+betweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
1007+ <+> "BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
1009+{- | not between, after sorting the comparison values
1010+>>> printSQL $ true `notBetweenSymmetric` (null_, false)
1011+TRUE NOT BETWEEN SYMMETRIC NULL AND FALSE
1014+ :: Expression outer grp commons schemas params from (nullity ty)
1015+ -> ( Expression outer grp commons schemas params from (nullity ty)
1016+ , Expression outer grp commons schemas params from (nullity ty) ) -- ^ bounds
1017+ -> Condition outer grp commons schemas params from
1018+notBetweenSymmetric a (x,y) = UnsafeExpression $ renderSQL a
1019+ <+> "NOT BETWEEN SYMMETRIC" <+> renderSQL x <+> "AND" <+> renderSQL y
1021+{- | not equal, treating null like an ordinary value
1022+>>> printSQL $ true `isDistinctFrom` null_
1023+(TRUE IS DISTINCT FROM NULL)
1026+ :: Expression outer grp commons schemas params from (nullity ty)
1027+ -> Expression outer grp commons schemas params from (nullity ty)
1028+ -> Condition outer grp commons schemas params from
1029+isDistinctFrom = unsafeBinaryOp "IS DISTINCT FROM"
1031+{- | equal, treating null like an ordinary value
1032+>>> printSQL $ true `isNotDistinctFrom` null_
1033+(TRUE IS NOT DISTINCT FROM NULL)
1036+ :: Expression outer grp commons schemas params from (nullity ty)
1037+ -> Expression outer grp commons schemas params from (nullity ty)
1038+ -> Condition outer grp commons schemas params from
1039+isNotDistinctFrom = unsafeBinaryOp "IS NOT DISTINCT FROM"
1042+>>> printSQL $ true & isTrue
1046+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1047+ -> Condition outer grp commons schemas params from
1048+isTrue b = UnsafeExpression $ renderSQL b <+> "IS TRUE"
1050+{- | is false or unknown
1051+>>> printSQL $ true & isNotTrue
1055+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1056+ -> Condition outer grp commons schemas params from
1057+isNotTrue b = UnsafeExpression $ renderSQL b <+> "IS NOT TRUE"
1060+>>> printSQL $ true & isFalse
1064+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1065+ -> Condition outer grp commons schemas params from
1066+isFalse b = UnsafeExpression $ renderSQL b <+> "IS FALSE"
1068+{- | is true or unknown
1069+>>> printSQL $ true & isNotFalse
1073+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1074+ -> Condition outer grp commons schemas params from
1075+isNotFalse b = UnsafeExpression $ renderSQL b <+> "IS NOT FALSE"
1078+>>> printSQL $ true & isUnknown
1082+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1083+ -> Condition outer grp commons schemas params from
1084+isUnknown b = UnsafeExpression $ renderSQL b <+> "IS UNKNOWN"
1086+{- | is true or false
1087+>>> printSQL $ true & isNotUnknown
1091+ :: Expression outer grp commons schemas params from (nullity 'PGbool)
1092+ -> Condition outer grp commons schemas params from
1093+isNotUnknown b = UnsafeExpression $ renderSQL b <+> "IS NOT UNKNOWN"
1095+-- | >>> printSQL currentDate
1098+ :: Expression outer grp commons schemas params from (nullity 'PGdate)
1099+currentDate = UnsafeExpression "CURRENT_DATE"
1101+-- | >>> printSQL currentTime
1104+ :: Expression outer grp commons schemas params from (nullity 'PGtimetz)
1105+currentTime = UnsafeExpression "CURRENT_TIME"
1107+-- | >>> printSQL currentTimestamp
1108+-- CURRENT_TIMESTAMP
1110+ :: Expression outer grp commons schemas params from (nullity 'PGtimestamptz)
1111+currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
1113+-- | >>> printSQL localTime
1116+ :: Expression outer grp commons schemas params from (nullity 'PGtime)
1117+localTime = UnsafeExpression "LOCALTIME"
1119+-- | >>> printSQL localTimestamp
1122+ :: Expression outer grp commons schemas params from (nullity 'PGtimestamp)
1123+localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
1125+{-----------------------------------------
1127+-----------------------------------------}
1129+escape :: Char -> String
439instance IsString
1141instance IsString
440− (Expression outer commons grp schemas params from (null 'PGtext)) where
1142+ (Expression outer grp commons schemas params from (nullity 'PGtext)) where
441 fromString str = UnsafeExpression $
1143 fromString str = UnsafeExpression $
442 "E\'" <> fromString (escape =<< str) <> "\'"
1144 "E\'" <> fromString (escape =<< str) <> "\'"
443instance IsString
1145instance IsString
444− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1146+ (Expression outer grp commons schemas params from (nullity 'PGtsvector)) where
445− fromString str = UnsafeExpression . parenthesized . (<> " :: tsvector") $
1147+ fromString str = cast tsvector . UnsafeExpression $
446 "E\'" <> fromString (escape =<< str) <> "\'"
1148 "E\'" <> fromString (escape =<< str) <> "\'"
447instance IsString
1149instance IsString
448− (Expression outer commons grp schemas params from (null 'PGtsquery)) where
1150+ (Expression outer grp commons schemas params from (nullity 'PGtsquery)) where
449− fromString str = UnsafeExpression . parenthesized . (<> " :: tsquery") $
1151+ fromString str = cast tsquery . UnsafeExpression $
450 "E\'" <> fromString (escape =<< str) <> "\'"
1152 "E\'" <> fromString (escape =<< str) <> "\'"
452instance Semigroup
1154instance Semigroup
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
1155+ (Expression outer grp commons schemas params from (nullity 'PGtext)) where
457 (<>) = unsafeBinaryOp "||"
1156 (<>) = unsafeBinaryOp "||"
458instance Semigroup
1157instance Semigroup
459− (Expression outer commons grp schemas params from (null 'PGtext)) where
460− (<>) = unsafeBinaryOp "||"
462− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1158+ (Expression outer grp commons schemas params from (nullity 'PGtsvector)) where
463 (<>) = unsafeBinaryOp "||"
1159 (<>) = unsafeBinaryOp "||"
465instance Monoid
1161instance Monoid
466− (Expression outer commons grp schemas params from (null 'PGtext)) where
1162+ (Expression outer grp commons schemas params from (nullity 'PGtext)) where
467 mempty = fromString ""
1163 mempty = fromString ""
468 mappend = (<>)
1164 mappend = (<>)
469instance Monoid
1165instance Monoid
470− (Expression outer commons grp schemas params from (null 'PGtsvector)) where
1166+ (Expression outer grp commons schemas params from (nullity 'PGtsvector)) where
471 mempty = fromString ""
1167 mempty = fromString ""
472 mappend = (<>)
1168 mappend = (<>)
1170+-- | >>> printSQL $ lower "ARRRGGG"
1171+-- lower(E'ARRRGGG')
1173+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1174+ -- ^ string to lower case
1175+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1176+lower = unsafeFunction "lower"
1178+-- | >>> printSQL $ upper "eeee"
1181+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1182+ -- ^ string to upper case
1183+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1184+upper = unsafeFunction "upper"
1186+-- | >>> printSQL $ charLength "four"
1187+-- char_length(E'four')
1189+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1190+ -- ^ string to measure
1191+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1192+charLength = unsafeFunction "char_length"
1194+-- | The `like` expression returns true if the @string@ matches
1195+-- the supplied @pattern@. If @pattern@ does not contain percent signs
1196+-- or underscores, then the pattern only represents the string itself;
1197+-- in that case `like` acts like the equals operator. An underscore (_)
1198+-- in pattern stands for (matches) any single character; a percent sign (%)
1199+-- matches any sequence of zero or more characters.
1201+-- >>> printSQL $ "abc" `like` "a%"
1202+-- (E'abc' LIKE E'a%')
1204+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1206+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1208+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
1209+like = unsafeBinaryOp "LIKE"
1211+-- | The key word ILIKE can be used instead of LIKE to make the
1212+-- match case-insensitive according to the active locale.
1214+-- >>> printSQL $ "abc" `ilike` "a%"
1215+-- (E'abc' ILIKE E'a%')
1217+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1219+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1221+ -> Expression outer grp commons schemas params from (nullity 'PGbool)
1222+ilike = unsafeBinaryOp "ILIKE"
1224+{-----------------------------------------
1225+ -- json and jsonb support
1227+See https://www.postgresql.org/docs/10/static/functions-json.html -- most
1228+comments lifted directly from this page.
1230+Table 9.44: json and jsonb operators
1231+-----------------------------------------}
1233+-- | Get JSON value (object field or array element) at a key.
1235+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1236+ => Expression outer grp commons schemas params from (nullity json)
1237+ -> Expression outer grp commons schemas params from (nullity key)
1238+ -> Expression outer grp commons schemas params from ('Null json)
1240+(.->) = unsafeBinaryOp "->"
1242+-- | Get JSON value (object field or array element) at a key, as text.
1244+ :: (json `In` PGJsonType, key `In` PGJsonKey)
1245+ => Expression outer grp commons schemas params from (nullity json)
1246+ -> Expression outer grp commons schemas params from (nullity key)
1247+ -> Expression outer grp commons schemas params from ('Null 'PGtext)
1249+(.->>) = unsafeBinaryOp "->>"
1251+-- | Get JSON value at a specified path.
1253+ :: (json `In` PGJsonType, PGTextArray "(.#>)" path)
1254+ => Expression outer grp commons schemas params from (nullity json)
1255+ -> Expression outer grp commons schemas params from (nullity path)
1256+ -> Expression outer grp commons schemas params from ('Null json)
1258+(.#>) = unsafeBinaryOp "#>"
1260+-- | Get JSON value at a specified path as text.
1262+ :: (json `In` PGJsonType, PGTextArray "(.#>>)" path)
1263+ => Expression outer grp commons schemas params from (nullity json)
1264+ -> Expression outer grp commons schemas params from (nullity path)
1265+ -> Expression outer grp commons schemas params from ('Null 'PGtext)
1267+(.#>>) = unsafeBinaryOp "#>>"
1269+-- Additional jsonb operators
1271+-- | Does the left JSON value contain the right JSON path/value entries at the
1274+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1275+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1276+ -> Condition outer grp commons schemas params from
1278+(.@>) = unsafeBinaryOp "@>"
1280+-- | Are the left JSON path/value entries contained at the top level within the
1281+-- right JSON value?
1283+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1284+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1285+ -> Condition outer grp commons schemas params from
1287+(.<@) = unsafeBinaryOp "<@"
1289+-- | Does the string exist as a top-level key within the JSON value?
1291+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1292+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1293+ -> Condition outer grp commons schemas params from
1295+(.?) = unsafeBinaryOp "?"
1297+-- | Do any of these array strings exist as top-level keys?
1299+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1300+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1301+ -> Condition outer grp commons schemas params from
1303+(.?|) = unsafeBinaryOp "?|"
1305+-- | Do all of these array strings exist as top-level keys?
1307+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1308+ -> Expression outer grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1309+ -> Condition outer grp commons schemas params from
1311+(.?&) = unsafeBinaryOp "?&"
1313+-- | Concatenate two jsonb values into a new jsonb value.
1315+ (Expression outer grp commons schemas params from (nullity 'PGjsonb)) where
1316+ (<>) = unsafeBinaryOp "||"
1318+-- | Delete a key or keys from a JSON object, or remove an array element.
1320+-- If the right operand is..
1322+-- @ text @: Delete key/value pair or string element from left operand. Key/value pairs
1323+-- are matched based on their key value.
1325+-- @ text[] @: Delete multiple key/value pairs or string elements
1326+-- from left operand. Key/value pairs are matched based on their key value.
1328+-- @ integer @: Delete the array element with specified index (Negative integers
1329+-- count from the end). Throws an error if top level container is not an array.
1331+ :: (key `In` '[ 'PGtext, 'PGvararray ('NotNull 'PGtext), 'PGint4, 'PGint2 ]) -- hlint error without parens here
1332+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1333+ -> Expression outer grp commons schemas params from (nullity key)
1334+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1336+(.-.) = unsafeBinaryOp "-"
1338+-- | Delete the field or element with specified path (for JSON arrays, negative
1339+-- integers count from the end)
1341+ :: PGTextArray "(#-.)" arrayty
1342+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1343+ -> Expression outer grp commons schemas params from (nullity arrayty)
1344+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1346+(#-.) = unsafeBinaryOp "#-"
1348+{-----------------------------------------
1349+Table 9.45: JSON creation functions
1350+-----------------------------------------}
1352+-- | Literal binary JSON
1355+ => x -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1356+jsonbLit = cast jsonb . UnsafeExpression
1357+ . singleQuotedUtf8 . toStrict . JSON.encode
1362+ => x -> Expression outer grp commons schemas params from (nullity 'PGjson)
1363+jsonLit = cast json . UnsafeExpression
1364+ . singleQuotedUtf8 . toStrict . JSON.encode
1366+-- | Returns the value as json. Arrays and composites are converted
1367+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1368+-- type to json, the cast function will be used to perform the conversion;
1369+-- otherwise, a scalar value is produced. For any scalar type other than a
1370+-- number, a Boolean, or a null value, the text representation will be used, in
1371+-- such a fashion that it is a valid json value.
1373+ :: Expression outer grp commons schemas params from (nullity ty)
1374+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1375+toJson = unsafeFunction "to_json"
1377+-- | Returns the value as jsonb. Arrays and composites are converted
1378+-- (recursively) to arrays and objects; otherwise, if there is a cast from the
1379+-- type to json, the cast function will be used to perform the conversion;
1380+-- otherwise, a scalar value is produced. For any scalar type other than a
1381+-- number, a Boolean, or a null value, the text representation will be used, in
1382+-- such a fashion that it is a valid jsonb value.
1384+ :: Expression outer grp commons schemas params from (nullity ty)
1385+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1386+toJsonb = unsafeFunction "to_jsonb"
1388+-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
1389+-- becomes a JSON array of arrays.
1391+ :: PGArray "arrayToJson" arr
1392+ => Expression outer grp commons schemas params from (nullity arr)
1393+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1394+arrayToJson = unsafeFunction "array_to_json"
1396+-- | Returns the row as a JSON object.
1398+ :: Expression outer grp commons schemas params from (nullity ('PGcomposite ty))
1399+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1400+rowToJson = unsafeFunction "row_to_json"
1402+-- | Builds a possibly-heterogeneously-typed JSON array out of a variadic
1406+ => NP (Expression outer grp commons schemas params from) elems
1407+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1408+jsonBuildArray = unsafeVariadicFunction "json_build_array"
1410+-- | Builds a possibly-heterogeneously-typed (binary) JSON array out of a
1411+-- variadic argument list.
1414+ => NP (Expression outer grp commons schemas params from) elems
1415+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1416+jsonbBuildArray = unsafeVariadicFunction "jsonb_build_array"
1419+ :: SOP.SListI elems
1420+ => NP (Aliased (Expression outer grp commons schemas params from)) elems
1423+ (`appEndo` []) . hcfoldMap (Proxy :: SOP.Proxy SOP.Top)
1424+ (\(col `As` name) -> Endo $ \xs ->
1425+ renderAliasString name : renderSQL col : xs)
1427+ renderAliasString :: KnownSymbol alias => Alias alias -> ByteString
1428+ renderAliasString = singleQuotedText . fromString . symbolVal
1430+-- | Builds a possibly-heterogeneously-typed JSON object out of a variadic
1431+-- argument list. The elements of the argument list must alternate between text
1434+ :: SOP.SListI elems
1435+ => NP (Aliased (Expression outer grp commons schemas params from)) elems
1436+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1438+ = unsafeFunction "json_build_object"
1441+ . unsafeRowFunction
1443+-- | Builds a possibly-heterogeneously-typed (binary) JSON object out of a
1444+-- variadic argument list. The elements of the argument list must alternate
1445+-- between text and values.
1447+ :: SOP.SListI elems
1448+ => NP (Aliased (Expression outer grp commons schemas params from)) elems
1449+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1451+ = unsafeFunction "jsonb_build_object"
1454+ . unsafeRowFunction
1456+-- | Builds a JSON object out of a text array. The array must have either
1457+-- exactly one dimension with an even number of members, in which case they are
1458+-- taken as alternating key/value pairs, or two dimensions such that each inner
1459+-- array has exactly two elements, which are taken as a key/value pair.
1461+ :: PGArrayOf "jsonObject" arr ('NotNull 'PGtext)
1462+ => Expression outer grp commons schemas params from (nullity arr)
1463+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1464+jsonObject = unsafeFunction "json_object"
1466+-- | Builds a binary JSON object out of a text array. The array must have either
1467+-- exactly one dimension with an even number of members, in which case they are
1468+-- taken as alternating key/value pairs, or two dimensions such that each inner
1469+-- array has exactly two elements, which are taken as a key/value pair.
1471+ :: PGArrayOf "jsonbObject" arr ('NotNull 'PGtext)
1472+ => Expression outer grp commons schemas params from (nullity arr)
1473+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1474+jsonbObject = unsafeFunction "jsonb_object"
1476+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1477+-- keys and one for values, that are zipped pairwise to create a JSON object.
1479+ :: ( PGArrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1480+ , PGArrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
1481+ => Expression outer grp commons schemas params from (nullity keysArray)
1482+ -> Expression outer grp commons schemas params from (nullity valuesArray)
1483+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1484+jsonZipObject ks vs =
1485+ unsafeVariadicFunction "json_object" (ks :* vs :* Nil)
1487+-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
1488+-- keys and one for values, that are zipped pairwise to create a binary JSON
1491+ :: ( PGArrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1492+ , PGArrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
1493+ => Expression outer grp commons schemas params from (nullity keysArray)
1494+ -> Expression outer grp commons schemas params from (nullity valuesArray)
1495+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1496+jsonbZipObject ks vs =
1497+ unsafeVariadicFunction "jsonb_object" (ks :* vs :* Nil)
1499+{-----------------------------------------
1500+Table 9.46: JSON processing functions
1501+-----------------------------------------}
1503+-- | Returns the number of elements in the outermost JSON array.
1505+ :: Expression outer grp commons schemas params from (nullity 'PGjson)
1506+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1507+jsonArrayLength = unsafeFunction "json_array_length"
1509+-- | Returns the number of elements in the outermost binary JSON array.
1511+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1512+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1513+jsonbArrayLength = unsafeFunction "jsonb_array_length"
1515+-- | Returns JSON value pointed to by the given path (equivalent to #>
1519+ => Expression outer grp commons schemas params from (nullity 'PGjson)
1520+ -> NP (Expression outer grp commons schemas params from) elems
1521+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1522+jsonExtractPath x xs =
1523+ unsafeVariadicFunction "json_extract_path" (x :* xs)
1525+-- | Returns JSON value pointed to by the given path (equivalent to #>
1529+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1530+ -> NP (Expression outer grp commons schemas params from) elems
1531+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1532+jsonbExtractPath x xs =
1533+ unsafeVariadicFunction "jsonb_extract_path" (x :* xs)
1535+-- | Returns JSON value pointed to by the given path (equivalent to #>
1536+-- operator), as text.
1537+jsonExtractPathAsText
1539+ => Expression outer grp commons schemas params from (nullity 'PGjson)
1540+ -> NP (Expression outer grp commons schemas params from) elems
1541+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1542+jsonExtractPathAsText x xs =
1543+ unsafeVariadicFunction "json_extract_path_text" (x :* xs)
1545+-- | Returns JSON value pointed to by the given path (equivalent to #>
1546+-- operator), as text.
1547+jsonbExtractPathAsText
1549+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1550+ -> NP (Expression outer grp commons schemas params from) elems
1551+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1552+jsonbExtractPathAsText x xs =
1553+ unsafeVariadicFunction "jsonb_extract_path_text" (x :* xs)
1555+-- | Returns the type of the outermost JSON value as a text string. Possible
1556+-- types are object, array, string, number, boolean, and null.
1558+ :: Expression outer grp commons schemas params from (nullity 'PGjson)
1559+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1560+jsonTypeof = unsafeFunction "json_typeof"
1562+-- | Returns the type of the outermost binary JSON value as a text string.
1563+-- Possible types are object, array, string, number, boolean, and null.
1565+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1566+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1567+jsonbTypeof = unsafeFunction "jsonb_typeof"
1569+-- | Returns its argument with all object fields that have null values omitted.
1570+-- Other null values are untouched.
1572+ :: Expression outer grp commons schemas params from (nullity 'PGjson)
1573+ -> Expression outer grp commons schemas params from (nullity 'PGjson)
1574+jsonStripNulls = unsafeFunction "json_strip_nulls"
1576+-- | Returns its argument with all object fields that have null values omitted.
1577+-- Other null values are untouched.
1579+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1580+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1581+jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
1583+-- | @ jsonbSet target path new_value create_missing @
1585+-- Returns target with the section designated by path replaced by new_value,
1586+-- or with new_value added if create_missing is true ( default is true) and the
1587+-- item designated by path does not exist. As with the path orientated
1588+-- operators, negative integers that appear in path count from the end of JSON
1591+ :: PGTextArray "jsonbSet" arr
1592+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1593+ -> Expression outer grp commons schemas params from (nullity arr)
1594+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1595+ -> Maybe (Expression outer grp commons schemas params from (nullity 'PGbool))
1596+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1597+jsonbSet tgt path val createMissing = case createMissing of
1598+ Just m -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* m :* Nil)
1599+ Nothing -> unsafeVariadicFunction "jsonb_set" (tgt :* path :* val :* Nil)
1601+-- | @ jsonbInsert target path new_value insert_after @
1603+-- Returns target with new_value inserted. If target section designated by
1604+-- path is in a JSONB array, new_value will be inserted before target or after
1605+-- if insert_after is true (default is false). If target section designated by
1606+-- path is in JSONB object, new_value will be inserted only if target does not
1607+-- exist. As with the path orientated operators, negative integers that appear
1608+-- in path count from the end of JSON arrays.
1610+ :: PGTextArray "jsonbInsert" arr
1611+ => Expression outer grp commons schemas params from (nullity 'PGjsonb)
1612+ -> Expression outer grp commons schemas params from (nullity arr)
1613+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1614+ -> Maybe (Expression outer grp commons schemas params from (nullity 'PGbool))
1615+ -> Expression outer grp commons schemas params from (nullity 'PGjsonb)
1616+jsonbInsert tgt path val insertAfter = case insertAfter of
1617+ Just i -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* i :* Nil)
1618+ Nothing -> unsafeVariadicFunction "jsonb_insert" (tgt :* path :* val :* Nil)
1620+-- | Returns its argument as indented JSON text.
1622+ :: Expression outer grp commons schemas params from (nullity 'PGjsonb)
1623+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1624+jsonbPretty = unsafeFunction "jsonb_pretty"
1626+(@@) :: ComparisonOperator (nullity 'PGtsvector) (nullity 'PGtsquery)
1627+(@@) = unsafeBinaryOp "@@"
1629+(.&) :: Operator (nullity 'PGtsquery) (nullity 'PGtsquery) (nullity 'PGtsquery)
1630+(.&) = unsafeBinaryOp "&&"
1632+(.|) :: Operator (nullity 'PGtsquery) (nullity 'PGtsquery) (nullity 'PGtsquery)
1633+(.|) = unsafeBinaryOp "||"
1636+ :: Expression outer grp commons schemas params from (nullity 'PGtsquery)
1637+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1638+(.!) = unsafeUnaryOp "!!"
1640+(<->) :: Operator (nullity 'PGtsquery) (nullity 'PGtsquery) (nullity 'PGtsquery)
1641+(<->) = unsafeBinaryOp "<->"
1644+ :: Expression outer grp commons schemas params from (nullity ('PGvararray ('NotNull 'PGtext)))
1645+ -> Expression outer grp commons schemas params from (nullity 'PGtsvector)
1646+arrayToTSvector = unsafeFunction "array_to_tsvector"
1649+ :: Expression outer grp commons schemas params from (nullity 'PGtsvector)
1650+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1651+tsvectorLength = unsafeFunction "length"
1654+ :: Expression outer grp commons schemas params from (nullity 'PGtsquery)
1655+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
1656+numnode = unsafeFunction "numnode"
1659+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1660+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1661+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1662+plainToTSquery = unsafeFunction2 "plainto_tsquery"
1665+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1666+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1667+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1668+phraseToTSquery = unsafeFunction2 "phraseto_tsquery"
1671+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1672+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1673+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1674+websearchToTSquery = unsafeFunction2 "websearch_to_tsquery"
1677+ :: Expression outer grp commons schemas params from (nullity 'PGtsquery)
1678+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1679+queryTree = unsafeFunction "query_tree"
1682+ :: Expression outer grp commons schemas params from (nullity 'PGtext)
1683+ -> Expression outer grp commons schemas params from (nullity 'PGtext)
1684+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1685+toTSquery = unsafeFunction2 "to_tsquery"
1688+ :: ty `In` '[ 'PGtext, 'PGjson, 'PGjsonb]
1689+ => Expression outer grp commons schemas params from (nullity 'PGtext)
1690+ -> Expression outer grp commons schemas params from (nullity ty)
1691+ -> Expression outer grp commons schemas params from (nullity 'PGtsquery)
1692+toTSvector = unsafeFunction2 "to_tsvector"
1694+{-----------------------------------------
1696+-----------------------------------------}
1699+`Aggregate` functions compute a single result from a set of input values.
1700+`Aggregate` functions can be used as `GroupedBy` `Expression`s as well
1701+as `WindowFunction`s.
1703+class Aggregate expr1 expr2 aggr
1704+ | aggr -> expr1, aggr -> expr2 where
1706+ -- | A special aggregation that does not require an input
1710+ -- expression :: Expression '[] ('Grouped bys) commons schemas params from ('NotNull 'PGint8)
1711+ -- expression = countStar
1712+ -- in printSQL expression
1715+ countStar :: aggr ('NotNull 'PGint8)
1719+ -- expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity ty]] ('NotNull 'PGint8)
1720+ -- expression = count (All #col)
1721+ -- in printSQL expression
1723+ -- count(ALL "col")
1727+ -> aggr ('NotNull 'PGint8)
1731+ -- expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('NotNull 'PGnumeric)
1732+ -- expression = sum_ (Distinct #col)
1733+ -- in printSQL expression
1735+ -- sum(DISTINCT "col")
1738+ => expr1 (nullity ty)
1739+ -> aggr ('NotNull ty)
1741+ -- | input values, including nulls, concatenated into an array
1744+ -> aggr ('Null ('PGvararray ty))
1746+ -- | aggregates values as a JSON array
1749+ -> aggr ('Null 'PGjson)
1751+ -- | aggregates values as a JSON array
1754+ -> aggr ('Null 'PGjsonb)
1757+ the bitwise AND of all non-null input values, or null if none
1760+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] ('Null 'PGint4)
1761+ expression = bitAnd (Distinct #col)
1762+ in printSQL expression
1764+ bit_and(DISTINCT "col")
1767+ :: int `In` PGIntegral
1768+ => expr1 (nullity int)
1769+ -- ^ what to aggregate
1770+ -> aggr ('Null int)
1773+ the bitwise OR of all non-null input values, or null if none
1777+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGint4]] ('Null 'PGint4)
1778+ expression = bitOr (All #col)
1779+ in printSQL expression
1784+ :: int `In` PGIntegral
1785+ => expr1 (nullity int)
1786+ -- ^ what to aggregate
1787+ -> aggr ('Null int)
1790+ true if all input values are true, otherwise false
1794+ winFun :: WindowFunction '[] 'Ungrouped commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] ('Null 'PGbool)
1795+ winFun = boolAnd #col
1801+ :: expr1 (nullity 'PGbool)
1802+ -- ^ what to aggregate
1803+ -> aggr ('Null 'PGbool)
1806+ true if at least one input value is true, otherwise false
1810+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] ('Null 'PGbool)
1811+ expression = boolOr (All #col)
1812+ in printSQL expression
1817+ :: expr1(nullity 'PGbool)
1818+ -- ^ what to aggregate
1819+ -> aggr ('Null 'PGbool)
1822+ equivalent to `boolAnd`
1826+ expression :: Expression '[] ('Grouped bys) commons schemas params '[tab ::: '["col" ::: nullity 'PGbool]] ('Null 'PGbool)
1827+ expression = every (Distinct #col)
1828+ in printSQL expression
1830+ every(DISTINCT "col")
1833+ :: expr1 (nullity 'PGbool)
1834+ -- ^ what to aggregate
1835+ -> aggr ('Null 'PGbool)
1837+ {- |maximum value of expression across all input values-}
1839+ :: expr1 (nullity ty)
1840+ -- ^ what to maximize
1843+ -- | minimum value of expression across all input values
1845+ :: expr1 (nullity ty)
1846+ -- ^ what to minimize
1849+ -- | the average (arithmetic mean) of all input values
1851+ :: expr1 (nullity ty)
1852+ -- ^ what to average
1853+ -> aggr ('Null (PGAvg ty))
1855+ {- | correlation coefficient
1858+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1859+ expression = corr (All (#y :*: #x))
1860+ in printSQL expression
1865+ :: expr2 (nullity 'PGfloat8)
1866+ -> aggr ('Null 'PGfloat8)
1868+ {- | population covariance
1871+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1872+ expression = covarPop (All (#y :*: #x))
1873+ in printSQL expression
1875+ covar_pop(ALL "y", "x")
1878+ :: expr2 (nullity 'PGfloat8)
1879+ -> aggr ('Null 'PGfloat8)
1881+ {- | sample covariance
1884+ winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1885+ winFun = covarSamp (#y :*: #x)
1888+ covar_samp("y", "x")
1891+ :: expr2 (nullity 'PGfloat8)
1892+ -> aggr ('Null 'PGfloat8)
1894+ {- | average of the independent variable (sum(X)/N)
1897+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1898+ expression = regrAvgX (All (#y :*: #x))
1899+ in printSQL expression
1901+ regr_avgx(ALL "y", "x")
1904+ :: expr2 (nullity 'PGfloat8)
1905+ -> aggr ('Null 'PGfloat8)
1907+ {- | average of the dependent variable (sum(Y)/N)
1910+ winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1911+ winFun = regrAvgY (#y :*: #x)
1914+ regr_avgy("y", "x")
1917+ :: expr2 (nullity 'PGfloat8)
1918+ -> aggr ('Null 'PGfloat8)
1920+ {- | number of input rows in which both expressions are nonnull
1923+ winFun :: WindowFunction '[] 'Ungrouped c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGint8)
1924+ winFun = regrCount (#y :*: #x)
1927+ regr_count("y", "x")
1930+ :: expr2 (nullity 'PGfloat8)
1931+ -> aggr ('Null 'PGint8)
1933+ {- | y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs
1936+ expression :: Expression '[] ('Grouped g) c s p '[t ::: '["x" ::: 'NotNull 'PGfloat8, "y" ::: 'NotNull 'PGfloat8]] ('Null 'PGfloat8)
1937+ expression = regrIntercept (All (#y :*: #x))
1938+ in printSQL expression
1940+ regr_intercept(ALL "y", "x")
1943+ :: expr2 (nullity 'PGfloat8)
1944+ -> aggr ('Null 'PGfloat8)
1946+ -- | @regr_r2(Y, X)@, square of the correlation coefficient
1948+ :: expr2 (nullity 'PGfloat8)
1949+ -> aggr ('Null 'PGfloat8)
1951+ -- | @regr_slope(Y, X)@, slope of the least-squares-fit linear equation
1952+ -- determined by the (X, Y) pairs
1954+ :: expr2 (nullity 'PGfloat8)
1955+ -> aggr ('Null 'PGfloat8)
1957+ -- | @regr_sxx(Y, X)@, sum(X^2) - sum(X)^2/N
1958+ -- (“sum of squares” of the independent variable)
1960+ :: expr2 (nullity 'PGfloat8)
1961+ -> aggr ('Null 'PGfloat8)
1963+ -- | @regr_sxy(Y, X)@, sum(X*Y) - sum(X) * sum(Y)/N
1964+ -- (“sum of products” of independent times dependent variable)
1966+ :: expr2 (nullity 'PGfloat8)
1967+ -> aggr ('Null 'PGfloat8)
1969+ -- | @regr_syy(Y, X)@, sum(Y^2) - sum(Y)^2/N
1970+ -- (“sum of squares” of the dependent variable)
1972+ :: expr2 (nullity 'PGfloat8)
1973+ -> aggr ('Null 'PGfloat8)
1975+ -- | historical alias for `stddevSamp`
1977+ :: expr1 (nullity ty)
1978+ -> aggr ('Null (PGAvg ty))
1980+ -- | population standard deviation of the input values
1982+ :: expr1 (nullity ty)
1983+ -> aggr ('Null (PGAvg ty))
1985+ -- | sample standard deviation of the input values
1987+ :: expr1 (nullity ty)
1988+ -> aggr ('Null (PGAvg ty))
1990+ -- | historical alias for `varSamp`
1992+ :: expr1 (nullity ty)
1993+ -> aggr ('Null (PGAvg ty))
1995+ -- | population variance of the input values
1996+ -- (square of the population standard deviation)
1998+ :: expr1 (nullity ty)
1999+ -> aggr ('Null (PGAvg ty))
2001+ -- | sample variance of the input values
2002+ -- (square of the sample standard deviation)
2004+ :: expr1 (nullity ty)
2005+ -> aggr ('Null (PGAvg ty))
2008+`Distinction`s are used for the input of `Aggregate` `Expression`s.
2009+`All` invokes the aggregate once for each input row.
2010+`Distinct` invokes the aggregate once for each distinct value of the expression
2011+(or distinct set of values, for multiple expressions) found in the input
2013+data Distinction expr ty
2015+ | Distinct (expr ty)
2016+ deriving (GHC.Generic,Show,Eq,Ord)
2017+instance NFData (Distinction (Expression outer grp commons schemas params from) ty)
2018+instance RenderSQL (Distinction (Expression outer grp commons schemas params from) ty) where
2020+ All x -> "ALL" <+> renderSQL x
2021+ Distinct x -> "DISTINCT" <+> renderSQL x
2024+ ( Expression outer grp commons schemas params from
2026+ Expression outer grp commons schemas params from) xty ) where
2029+ "ALL" <+> renderSQL x <> ", " <> renderSQL x'
2030+ Distinct (x :*: x') ->
2031+ "DISTINCT" <+> renderSQL x <> ", " <> renderSQL x'
2034+ (Distinction (Expression outer 'Ungrouped commons schemas params from))
2035+ (Distinction (Expression outer 'Ungrouped commons schemas params from :*: Expression outer 'Ungrouped commons schemas params from))
2036+ (Expression outer ('Grouped bys) commons schemas params from) where
2037+ countStar = UnsafeExpression "count(*)"
2038+ count = unsafeAggregate1 "count"
2039+ sum_ = unsafeAggregate1 "sum"
2040+ arrayAgg = unsafeAggregate1 "array_agg"
2041+ jsonAgg = unsafeAggregate1 "json_agg"
2042+ jsonbAgg = unsafeAggregate1 "jsonb_agg"
2043+ bitAnd = unsafeAggregate1 "bit_and"
2044+ bitOr = unsafeAggregate1 "bit_or"
2045+ boolAnd = unsafeAggregate1 "bool_and"
2046+ boolOr = unsafeAggregate1 "bool_or"
2047+ every = unsafeAggregate1 "every"
2048+ max_ = unsafeAggregate1 "max"
2049+ min_ = unsafeAggregate1 "min"
2050+ avg = unsafeAggregate1 "avg"
2051+ corr = unsafeAggregate2 "corr"
2052+ covarPop = unsafeAggregate2 "covar_pop"
2053+ covarSamp = unsafeAggregate2 "covar_samp"
2054+ regrAvgX = unsafeAggregate2 "regr_avgx"
2055+ regrAvgY = unsafeAggregate2 "regr_avgy"
2056+ regrCount = unsafeAggregate2 "regr_count"
2057+ regrIntercept = unsafeAggregate2 "regr_intercept"
2058+ regrR2 = unsafeAggregate2 "regr_r2"
2059+ regrSlope = unsafeAggregate2 "regr_slope"
2060+ regrSxx = unsafeAggregate2 "regr_sxx"
2061+ regrSxy = unsafeAggregate2 "regr_sxy"
2062+ regrSyy = unsafeAggregate2 "regr_syy"
2063+ stddev = unsafeAggregate1 "stddev"
2064+ stddevPop = unsafeAggregate1 "stddev_pop"
2065+ stddevSamp = unsafeAggregate1 "stddev_samp"
2066+ variance = unsafeAggregate1 "variance"
2067+ varPop = unsafeAggregate1 "var_pop"
2068+ varSamp = unsafeAggregate1 "var_samp"
2070+ (Expression outer grp commons schemas params from)
2071+ (Expression outer grp commons schemas params from :*: Expression outer grp commons schemas params from)
2072+ (WindowFunction outer grp commons schemas params from) where
2073+ countStar = UnsafeWindowFunction "count(*)"
2074+ count = unsafeWindowFunction1 "count"
2075+ sum_ = unsafeWindowFunction1 "sum"
2076+ arrayAgg = unsafeWindowFunction1 "array_agg"
2077+ jsonAgg = unsafeWindowFunction1 "json_agg"
2078+ jsonbAgg = unsafeWindowFunction1 "jsonb_agg"
2079+ bitAnd = unsafeWindowFunction1 "bit_and"
2080+ bitOr = unsafeWindowFunction1 "bit_or"
2081+ boolAnd = unsafeWindowFunction1 "bool_and"
2082+ boolOr = unsafeWindowFunction1 "bool_or"
2083+ every = unsafeWindowFunction1 "every"
2084+ max_ = unsafeWindowFunction1 "max"
2085+ min_ = unsafeWindowFunction1 "min"
2086+ avg = unsafeWindowFunction1 "avg"
2087+ corr = unsafeWindowFunction2 "corr"
2088+ covarPop = unsafeWindowFunction2 "covar_pop"
2089+ covarSamp = unsafeWindowFunction2 "covar_samp"
2090+ regrAvgX = unsafeWindowFunction2 "regr_avgx"
2091+ regrAvgY = unsafeWindowFunction2 "regr_avgy"
2092+ regrCount = unsafeWindowFunction2 "regr_count"
2093+ regrIntercept = unsafeWindowFunction2 "regr_intercept"
2094+ regrR2 = unsafeWindowFunction2 "regr_r2"
2095+ regrSlope = unsafeWindowFunction2 "regr_slope"
2096+ regrSxx = unsafeWindowFunction2 "regr_sxx"
2097+ regrSxy = unsafeWindowFunction2 "regr_sxy"
2098+ regrSyy = unsafeWindowFunction2 "regr_syy"
2099+ stddev = unsafeWindowFunction1 "stddev"
2100+ stddevPop = unsafeWindowFunction1 "stddev_pop"
2101+ stddevSamp = unsafeWindowFunction1 "stddev_samp"
2102+ variance = unsafeWindowFunction1 "variance"
2103+ varPop = unsafeWindowFunction1 "var_pop"
2104+ varSamp = unsafeWindowFunction1 "var_samp"
2106+-- | escape hatch to define aggregate functions
2108+ :: ByteString -- ^ aggregate function
2109+ -> Distinction (Expression outer 'Ungrouped commons schemas params from) xty
2110+ -> Expression outer ('Grouped bys) commons schemas params from yty
2111+unsafeAggregate1 fun x = UnsafeExpression $ mconcat
2112+ [fun, "(", renderSQL x, ")"]
2114+-- | escape hatch to define aggregate binary functions
2116+ :: ByteString -- ^ aggregate function
2117+ -> Distinction (Expression outer 'Ungrouped commons schemas params from :*: Expression outer 'Ungrouped commons schemas params from) xty
2118+ -> Expression outer ('Grouped bys) commons schemas params from yty
2119+unsafeAggregate2 fun xx = UnsafeExpression $ mconcat
2120+ [fun, "(", renderSQL xx, ")"]
2122+-- | A type family that calculates `PGAvg` type of a `PGType`.
2123+type family PGAvg ty where
2124+ PGAvg 'PGint2 = 'PGnumeric
2125+ PGAvg 'PGint4 = 'PGnumeric
2126+ PGAvg 'PGint8 = 'PGnumeric
2127+ PGAvg 'PGnumeric = 'PGnumeric
2128+ PGAvg 'PGfloat4 = 'PGfloat8
2129+ PGAvg 'PGfloat8 = 'PGfloat8
2130+ PGAvg 'PGinterval = 'PGinterval
2131+ PGAvg pg = TypeError
2132+ ('Text "Squeal type error: No average for " ':<>: 'ShowType pg)
2134+{-----------------------------------------
2136+-----------------------------------------}
2138+-- | `TypeExpression`s are used in `cast`s and
2139+-- `Squeal.PostgreSQL.Definition.createTable` commands.
2140+newtype TypeExpression (schemas :: SchemasType) (ty :: NullityType)
2141+ = UnsafeTypeExpression { renderTypeExpression :: ByteString }
2142+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
2143+instance RenderSQL (TypeExpression schemas ty) where
2144+ renderSQL = renderTypeExpression
2146+-- | The enum or composite type in a `Typedef` can be expressed by its alias.
2148+ :: (Has sch schemas schema, Has td schema ('Typedef ty))
2149+ => QualifiedAlias sch td
2150+ -> TypeExpression schemas (nullity ty)
2151+typedef = UnsafeTypeExpression . renderSQL
2153+-- | The composite type corresponding to a `Table` definition can be expressed
2156+ :: (Has sch schemas schema, Has tab schema ('Table table))
2157+ => QualifiedAlias sch tab
2158+ -> TypeExpression schemas (nullity ('PGcomposite (TableToRow table)))
2159+typetable = UnsafeTypeExpression . renderSQL
2161+-- | The composite type corresponding to a `View` definition can be expressed
2164+ :: (Has sch schemas schema, Has vw schema ('View view))
2165+ => QualifiedAlias sch vw
2166+ -> TypeExpression schemas (nullity ('PGcomposite view))
2167+typeview = UnsafeTypeExpression . renderSQL
2169+-- | logical Boolean (true/false)
2170+bool :: TypeExpression schemas (nullity 'PGbool)
2171+bool = UnsafeTypeExpression "bool"
2172+-- | signed two-byte integer
2173+int2, smallint :: TypeExpression schemas (nullity 'PGint2)
2174+int2 = UnsafeTypeExpression "int2"
2175+smallint = UnsafeTypeExpression "smallint"
2176+-- | signed four-byte integer
2177+int4, int, integer :: TypeExpression schemas (nullity 'PGint4)
2178+int4 = UnsafeTypeExpression "int4"
2179+int = UnsafeTypeExpression "int"
2180+integer = UnsafeTypeExpression "integer"
2181+-- | signed eight-byte integer
2182+int8, bigint :: TypeExpression schemas (nullity 'PGint8)
2183+int8 = UnsafeTypeExpression "int8"
2184+bigint = UnsafeTypeExpression "bigint"
2185+-- | arbitrary precision numeric type
2186+numeric :: TypeExpression schemas (nullity 'PGnumeric)
2187+numeric = UnsafeTypeExpression "numeric"
2188+-- | single precision floating-point number (4 bytes)
2189+float4, real :: TypeExpression schemas (nullity 'PGfloat4)
2190+float4 = UnsafeTypeExpression "float4"
2191+real = UnsafeTypeExpression "real"
2192+-- | double precision floating-point number (8 bytes)
2193+float8, doublePrecision :: TypeExpression schemas (nullity 'PGfloat8)
2194+float8 = UnsafeTypeExpression "float8"
2195+doublePrecision = UnsafeTypeExpression "double precision"
2196+-- | currency amount
2197+money :: TypeExpression schema (nullity 'PGmoney)
2198+money = UnsafeTypeExpression "money"
2199+-- | variable-length character string
2200+text :: TypeExpression schemas (nullity 'PGtext)
2201+text = UnsafeTypeExpression "text"
2202+-- | fixed-length character string
2204+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
2205+ => TypeExpression schemas (nullity ('PGchar n))
2206+char = UnsafeTypeExpression $ "char(" <> renderNat @n <> ")"
2207+character = UnsafeTypeExpression $ "character(" <> renderNat @n <> ")"
2208+-- | variable-length character string
2209+varchar, characterVarying
2210+ :: forall n schemas nullity. (KnownNat n, 1 <= n)
2211+ => TypeExpression schemas (nullity ('PGvarchar n))
2212+varchar = UnsafeTypeExpression $ "varchar(" <> renderNat @n <> ")"
2213+characterVarying = UnsafeTypeExpression $
2214+ "character varying(" <> renderNat @n <> ")"
2215+-- | binary data ("byte array")
2216+bytea :: TypeExpression schemas (nullity 'PGbytea)
2217+bytea = UnsafeTypeExpression "bytea"
2218+-- | date and time (no time zone)
2219+timestamp :: TypeExpression schemas (nullity 'PGtimestamp)
2220+timestamp = UnsafeTypeExpression "timestamp"
2221+-- | date and time, including time zone
2222+timestampWithTimeZone :: TypeExpression schemas (nullity 'PGtimestamptz)
2223+timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
2224+-- | calendar date (year, month, day)
2225+date :: TypeExpression schemas (nullity 'PGdate)
2226+date = UnsafeTypeExpression "date"
2227+-- | time of day (no time zone)
2228+time :: TypeExpression schemas (nullity 'PGtime)
2229+time = UnsafeTypeExpression "time"
2230+-- | time of day, including time zone
2231+timeWithTimeZone :: TypeExpression schemas (nullity 'PGtimetz)
2232+timeWithTimeZone = UnsafeTypeExpression "time with time zone"
2234+interval :: TypeExpression schemas (nullity 'PGinterval)
2235+interval = UnsafeTypeExpression "interval"
2236+-- | universally unique identifier
2237+uuid :: TypeExpression schemas (nullity 'PGuuid)
2238+uuid = UnsafeTypeExpression "uuid"
2239+-- | IPv4 or IPv6 host address
2240+inet :: TypeExpression schemas (nullity 'PGinet)
2241+inet = UnsafeTypeExpression "inet"
2242+-- | textual JSON data
2243+json :: TypeExpression schemas (nullity 'PGjson)
2244+json = UnsafeTypeExpression "json"
2245+-- | binary JSON data, decomposed
2246+jsonb :: TypeExpression schemas (nullity 'PGjsonb)
2247+jsonb = UnsafeTypeExpression "jsonb"
2248+-- | variable length array
2250+ :: TypeExpression schemas pg
2251+ -> TypeExpression schemas (nullity ('PGvararray pg))
2252+vararray ty = UnsafeTypeExpression $ renderSQL ty <> "[]"
2253+-- | fixed length array
2255+-- >>> renderSQL (fixarray @'[2] json)
2258+ :: forall dims schemas nullity pg. SOP.All KnownNat dims
2259+ => TypeExpression schemas pg
2260+ -> TypeExpression schemas (nullity ('PGfixarray dims pg))
2261+fixarray ty = UnsafeTypeExpression $
2262+ renderSQL ty <> renderDims @dims
2264+ renderDims :: forall ns. SOP.All KnownNat ns => ByteString
2268+ . ByteString.intercalate "]["
2270+ $ hcmap (SOP.Proxy @KnownNat)
2271+ (K . fromString . show . natVal)
2272+ (hpure SOP.Proxy :: NP SOP.Proxy ns)
2273+tsvector :: TypeExpression schemas (nullity 'PGtsvector)
2274+tsvector = UnsafeTypeExpression "tsvector"
2275+tsquery :: TypeExpression schemas (nullity 'PGtsquery)
2276+tsquery = UnsafeTypeExpression "tsquery"
2278+-- | `pgtype` is a demoted version of a `PGType`
2279+class PGTyped schemas (ty :: NullityType) where
2280+ pgtype :: TypeExpression schemas ty
2281+instance PGTyped schemas (nullity 'PGbool) where pgtype = bool
2282+instance PGTyped schemas (nullity 'PGint2) where pgtype = int2
2283+instance PGTyped schemas (nullity 'PGint4) where pgtype = int4
2284+instance PGTyped schemas (nullity 'PGint8) where pgtype = int8
2285+instance PGTyped schemas (nullity 'PGnumeric) where pgtype = numeric
2286+instance PGTyped schemas (nullity 'PGfloat4) where pgtype = float4
2287+instance PGTyped schemas (nullity 'PGfloat8) where pgtype = float8
2288+instance PGTyped schemas (nullity 'PGmoney) where pgtype = money
2289+instance PGTyped schemas (nullity 'PGtext) where pgtype = text
2290+instance (KnownNat n, 1 <= n)
2291+ => PGTyped schemas (nullity ('PGchar n)) where pgtype = char @n
2292+instance (KnownNat n, 1 <= n)
2293+ => PGTyped schemas (nullity ('PGvarchar n)) where pgtype = varchar @n
2294+instance PGTyped schemas (nullity 'PGbytea) where pgtype = bytea
2295+instance PGTyped schemas (nullity 'PGtimestamp) where pgtype = timestamp
2296+instance PGTyped schemas (nullity 'PGtimestamptz) where pgtype = timestampWithTimeZone
2297+instance PGTyped schemas (nullity 'PGdate) where pgtype = date
2298+instance PGTyped schemas (nullity 'PGtime) where pgtype = time
2299+instance PGTyped schemas (nullity 'PGtimetz) where pgtype = timeWithTimeZone
2300+instance PGTyped schemas (nullity 'PGinterval) where pgtype = interval
2301+instance PGTyped schemas (nullity 'PGuuid) where pgtype = uuid
2302+instance PGTyped schemas (nullity 'PGjson) where pgtype = json
2303+instance PGTyped schemas (nullity 'PGjsonb) where pgtype = jsonb
2304+instance PGTyped schemas ty
2305+ => PGTyped schemas (nullity ('PGvararray ty)) where
2306+ pgtype = vararray (pgtype @schemas @ty)
2307+instance (SOP.All KnownNat dims, PGTyped schemas ty)
2308+ => PGTyped schemas (nullity ('PGfixarray dims ty)) where
2309+ pgtype = fixarray @dims (pgtype @schemas @ty)
2310+instance PGTyped schemas (nullity 'PGtsvector) where pgtype = tsvector
2311+instance PGTyped schemas (nullity 'PGtsquery) where pgtype = tsquery
2313+{-----------------------------------------
2315+-----------------------------------------}
2317+-- | `SortExpression`s are used by `orderBy` to optionally sort the results
2318+-- of a `Squeal.PostgreSQL.Query.Query`. `Asc` or `Desc`
2319+-- set the sort direction of a `NotNull` result
2320+-- column to ascending or descending. Ascending order puts smaller values
2321+-- first, where "smaller" is defined in terms of the `.<` operator. Similarly,
2322+-- descending order is determined with the `.>` operator. `AscNullsFirst`,
2323+-- `AscNullsLast`, `DescNullsFirst` and `DescNullsLast` options are used to
2324+-- determine whether nulls appear before or after non-null values in the sort
2325+-- ordering of a `Null` result column.
2326+data SortExpression outer grp commons schemas params from where
2328+ :: Expression outer grp commons schemas params from ('NotNull ty)
2329+ -> SortExpression outer grp commons schemas params from
2331+ :: Expression outer grp commons schemas params from ('NotNull ty)
2332+ -> SortExpression outer grp commons schemas params from
2334+ :: Expression outer grp commons schemas params from ('Null ty)
2335+ -> SortExpression outer grp commons schemas params from
2337+ :: Expression outer grp commons schemas params from ('Null ty)
2338+ -> SortExpression outer grp commons schemas params from
2340+ :: Expression outer grp commons schemas params from ('Null ty)
2341+ -> SortExpression outer grp commons schemas params from
2343+ :: Expression outer grp commons schemas params from ('Null ty)
2344+ -> SortExpression outer grp commons schemas params from
2345+deriving instance Show (SortExpression outer grp commons schemas params from)
2348+The `orderBy` clause causes the result rows of a `Squeal.PostgreSQL.Query.TableExpression`
2349+to be sorted according to the specified `SortExpression`(s).
2350+If two rows are equal according to the leftmost expression,
2351+they are compared according to the next expression and so on.
2352+If they are equal according to all specified expressions,
2353+they are returned in an implementation-dependent order.
2355+You can also control the order in which rows are processed by window functions
2356+using `orderBy` within `Squeal.PostgreSQL.Query.Over`.
2358+class OrderBy expr where
2360+ :: [SortExpression outer grp commons schemas params from]
2361+ -> expr outer grp commons schemas params from
2362+ -> expr outer grp commons schemas params from
2364+-- | Render a `SortExpression`.
2365+instance RenderSQL (SortExpression outer grp commons schemas params from) where
2367+ Asc expression -> renderSQL expression <+> "ASC"
2368+ Desc expression -> renderSQL expression <+> "DESC"
2369+ AscNullsFirst expression -> renderSQL expression
2370+ <+> "ASC NULLS FIRST"
2371+ DescNullsFirst expression -> renderSQL expression
2372+ <+> "DESC NULLS FIRST"
2373+ AscNullsLast expression -> renderSQL expression <+> "ASC NULLS LAST"
2374+ DescNullsLast expression -> renderSQL expression <+> "DESC NULLS LAST"
2376+-- | A `WindowDefinition` is a set of table rows that are somehow related
2377+-- to the current row
2378+data WindowDefinition outer grp commons schemas params from where
2381+ => NP (Expression outer grp commons schemas params from) bys
2382+ -> [SortExpression outer grp commons schemas params from]
2383+ -> WindowDefinition outer grp commons schemas params from
2385+instance OrderBy WindowDefinition where
2386+ orderBy sortsR (WindowDefinition parts sortsL)
2387+ = WindowDefinition parts (sortsL ++ sortsR)
2389+instance RenderSQL (WindowDefinition outer commons schemas from grp params) where
2390+ renderSQL (WindowDefinition part ord) =
2391+ renderPartitionByClause part <> renderOrderByClause ord
2393+ renderPartitionByClause = \case
2395+ parts -> "PARTITION" <+> "BY" <+> renderCommaSeparated renderExpression parts
2396+ renderOrderByClause = \case
2398+ srts -> " ORDER" <+> "BY"
2399+ <+> commaSeparated (renderSQL <$> srts)
2402+The `partitionBy` clause within `Squeal.PostgreSQL.Query.Over` divides the rows into groups,
2403+or partitions, that share the same values of the `partitionBy` `Expression`(s).
2404+For each row, the window function is computed across the rows that fall into
2405+the same partition as the current row.
2409+ => NP (Expression outer grp commons schemas params from) bys
2410+ -> WindowDefinition outer grp commons schemas params from
2411+partitionBy bys = WindowDefinition bys []
2414+A window function performs a calculation across a set of table rows
2415+that are somehow related to the current row. This is comparable to the type
2416+of calculation that can be done with an aggregate function.
2417+However, window functions do not cause rows to become grouped into a single
2418+output row like non-window aggregate calls would.
2419+Instead, the rows retain their separate identities.
2420+Behind the scenes, the window function is able to access more than
2421+just the current row of the query result.
2423+newtype WindowFunction
2424+ (outer :: FromType)
2426+ (commons :: FromType)
2427+ (schemas :: SchemasType)
2428+ (params :: [NullityType])
2430+ (ty :: NullityType)
2431+ = UnsafeWindowFunction { renderWindowFunction :: ByteString }
2432+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
2434+instance RenderSQL (WindowFunction outer grp commons schemas params from ty) where
2435+ renderSQL = renderWindowFunction
2437+unsafeWindowFunction1
2439+ -> Expression outer grp commons schemas params from ty0
2440+ -> WindowFunction outer grp commons schemas params from ty1
2441+unsafeWindowFunction1 fun x
2442+ = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x)
2444+unsafeWindowFunction2
2446+ -> (Expression outer grp commons schemas params from :*: Expression outer grp commons schemas params from) ty0
2447+ -> WindowFunction outer grp commons schemas params from ty1
2448+unsafeWindowFunction2 fun (x :*: x')
2449+ = UnsafeWindowFunction $ fun <> parenthesized (renderSQL x <> ", " <> renderSQL x')
2451+{- | rank of the current row with gaps; same as `rowNumber` of its first peer
2455+rank :: WindowFunction outer grp commons schemas params from ('NotNull 'PGint8)
2456+rank = UnsafeWindowFunction "rank()"
2458+{- | number of the current row within its partition, counting from 1
2459+>>> printSQL rowNumber
2462+rowNumber :: WindowFunction outer grp commons schemas params from ('NotNull 'PGint8)
2463+rowNumber = UnsafeWindowFunction "row_number()"
2465+{- | rank of the current row without gaps; this function counts peer groups
2466+>>> printSQL denseRank
2469+denseRank :: WindowFunction outer grp commons schemas params from ('NotNull 'PGint8)
2470+denseRank = UnsafeWindowFunction "dense_rank()"
2472+{- | relative rank of the current row: (rank - 1) / (total partition rows - 1)
2473+>>> printSQL percentRank
2476+percentRank :: WindowFunction outer grp commons schemas params from ('NotNull 'PGfloat8)
2477+percentRank = UnsafeWindowFunction "percent_rank()"
2479+{- | cumulative distribution: (number of partition rows
2480+preceding or peer with current row) / total partition rows
2481+>>> printSQL cumeDist
2484+cumeDist :: WindowFunction outer grp commons schemas params from ('NotNull 'PGfloat8)
2485+cumeDist = UnsafeWindowFunction "cume_dist()"
2487+{- | integer ranging from 1 to the argument value,
2488+dividing the partition as equally as possible
2491+ :: Expression outer grp commons schemas params from ('NotNull 'PGint4)
2493+ -> WindowFunction outer grp commons schemas params from ('NotNull 'PGint4)
2494+ntile = unsafeWindowFunction1 "ntile"
2496+{- | returns value evaluated at the row that is offset rows before the current
2497+row within the partition; if there is no such row, instead return default
2498+(which must be of the same type as value). Both offset and default are
2499+evaluated with respect to the current row.
2502+ :: Expression outer grp commons schemas params from ty
2504+ -> Expression outer grp commons schemas params from ('NotNull 'PGint4)
2506+ -> Expression outer grp commons schemas params from ty
2508+ -> WindowFunction outer grp commons schemas params from ty
2509+lag value offset def = UnsafeWindowFunction $ "lag"
2511+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
2513+{- | returns value evaluated at the row that is offset rows after the current
2514+row within the partition; if there is no such row, instead return default
2515+(which must be of the same type as value). Both offset and default are
2516+evaluated with respect to the current row.
2519+ :: Expression outer grp commons schemas params from ty
2521+ -> Expression outer grp commons schemas params from ('NotNull 'PGint4)
2523+ -> Expression outer grp commons schemas params from ty
2525+ -> WindowFunction outer grp commons schemas params from ty
2526+lead value offset def = UnsafeWindowFunction $ "lag"
2528+ (commaSeparated ([renderSQL value, renderSQL offset, renderSQL def]))
2530+{- | returns value evaluated at the row that is the
2531+first row of the window frame
2534+ :: Expression outer grp commons schemas params from ty
2536+ -> WindowFunction outer grp commons schemas params from ty
2537+firstValue = unsafeWindowFunction1 "first_value"
2539+{- | returns value evaluated at the row that is the
2540+last row of the window frame
2543+ :: Expression outer grp commons schemas params from ty
2545+ -> WindowFunction outer grp commons schemas params from ty
2546+lastValue = unsafeWindowFunction1 "last_value"
2548+{- | returns value evaluated at the row that is the nth
2549+row of the window frame (counting from 1); null if no such row
2552+ :: Expression outer grp commons schemas params from (nullity ty)
2554+ -> Expression outer grp commons schemas params from ('NotNull 'PGint4)
2556+ -> WindowFunction outer grp commons schemas params from ('Null ty)
2557+nthValue value nth = UnsafeWindowFunction $ "nth_value"
2558+ <> parenthesized (commaSeparated [renderSQL value, renderSQL nth])
2561+Create date from year, month and day fields
2563+>>> printSQL (makeDate 1984 7 3)
2564+make_date(1984, 7, 3)
2567+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2569+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2571+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2573+ -> Expression outer grp commons schemas params from (nullity 'PGdate)
2574+makeDate y m d = UnsafeExpression $ "make_date" <>
2575+ parenthesized (renderCommaSeparated renderSQL (y :* m :* d :* Nil))
2578+Create time from hour, minute and seconds fields
2580+>>> printSQL (makeTime 8 15 23.5)
2581+make_time(8, 15, 23.5)
2584+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2586+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2588+ -> Expression outer grp commons schemas params from (nullity 'PGfloat8)
2590+ -> Expression outer grp commons schemas params from (nullity 'PGtime)
2591+makeTime h m s = UnsafeExpression $ "make_time" <>
2592+ parenthesized (renderCommaSeparated renderSQL (h :* m :* s :* Nil))
2595+Create timestamp from year, month, day, hour, minute and seconds fields
2597+>>> printSQL (makeTimestamp 2013 7 15 8 15 23.5)
2598+make_timestamp(2013, 7, 15, 8, 15, 23.5)
2601+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2603+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2605+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2607+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2609+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2611+ -> Expression outer grp commons schemas params from (nullity 'PGfloat8)
2613+ -> Expression outer grp commons schemas params from (nullity 'PGtimestamp)
2614+makeTimestamp y mon d h m s =
2615+ UnsafeExpression $ "make_timestamp" <> parenthesized
2616+ (renderCommaSeparated renderSQL (y :* mon :* d :* h :* m :* s :* Nil))
2619+Create timestamp with time zone from
2620+year, month, day, hour, minute and seconds fields;
2621+the current time zone is used
2623+>>> printSQL (makeTimestamptz 2013 7 15 8 15 23.5)
2624+make_timestamptz(2013, 7, 15, 8, 15, 23.5)
2627+ :: Expression outer grp commons schemas params from (nullity 'PGint4)
2629+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2631+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2633+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2635+ -> Expression outer grp commons schemas params from (nullity 'PGint4)
2637+ -> Expression outer grp commons schemas params from (nullity 'PGfloat8)
2639+ -> Expression outer grp commons schemas params from (nullity 'PGtimestamptz)
2640+makeTimestamptz y mon d h m s =
2641+ UnsafeExpression $ "make_timestamptz" <> parenthesized
2642+ (renderCommaSeparated renderSQL (y :* mon :* d :* h :* m :* s :* Nil))
2645+Affine space operations on time types.
2647+class TimeOp time diff | time -> diff where
2649+ >>> printSQL (makeDate 1984 7 3 !+ 365)
2650+ (make_date(1984, 7, 3) + 365)
2653+ :: Expression outer grp commons schemas params from (nullity time)
2654+ -> Expression outer grp commons schemas params from (nullity diff)
2655+ -> Expression outer grp commons schemas params from (nullity time)
2656+ (!+) = unsafeBinaryOp "+"
2658+ >>> printSQL (365 +! makeDate 1984 7 3)
2659+ (365 + make_date(1984, 7, 3))
2662+ :: Expression outer grp commons schemas params from (nullity diff)
2663+ -> Expression outer grp commons schemas params from (nullity time)
2664+ -> Expression outer grp commons schemas params from (nullity time)
2665+ (+!) = unsafeBinaryOp "+"
2667+ >>> printSQL (makeDate 1984 7 3 !- 365)
2668+ (make_date(1984, 7, 3) - 365)
2671+ :: Expression outer grp commons schemas params from (nullity time)
2672+ -> Expression outer grp commons schemas params from (nullity diff)
2673+ -> Expression outer grp commons schemas params from (nullity time)
2674+ (!-) = unsafeBinaryOp "-"
2676+ >>> printSQL (makeDate 1984 7 3 !-! currentDate)
2677+ (make_date(1984, 7, 3) - CURRENT_DATE)
2680+ :: Expression outer grp commons schemas params from (nullity time)
2681+ -> Expression outer grp commons schemas params from (nullity time)
2682+ -> Expression outer grp commons schemas params from (nullity diff)
2683+ (!-!) = unsafeBinaryOp "-"
2684+instance TimeOp 'PGtimestamp 'PGinterval
2685+instance TimeOp 'PGtimestamptz 'PGinterval
2686+instance TimeOp 'PGtime 'PGinterval
2687+instance TimeOp 'PGtimetz 'PGinterval
2688+instance TimeOp 'PGinterval 'PGinterval
2689+instance TimeOp 'PGdate 'PGint4