@@ -37,13 +37,6 @@ module Squeal.PostgreSQL.Expression
3737 ( -- * Expression
3838 Expression (UnsafeExpression, renderExpression)
3939 , HasParameter (param)
40− , HasColumn (getColumn)
41− , Column (Column)
42− , renderColumn
43− , GroupedBy (getGroup1, getGroup2)
44− -- ** Default
45− , def
46− , unDef
4740 -- ** Null
4841 , null_
4942 , unNull
@@ -53,7 +46,9 @@ module Squeal.PostgreSQL.Expression
5346 , isn'tNull
5447 , matchNull
5548 , nullIf
56− -- ** Functions
49+ -- ** Arrays
50+ , array
51+ -- ** Functions
5752 , unsafeBinaryOp
5853 , unsafeUnaryOp
5954 , unsafeFunction
@@ -104,8 +99,7 @@ module Squeal.PostgreSQL.Expression
10499 , max_, maxDistinct, min_, minDistinct
105100 -- * Tables
106101 , Table (UnsafeTable, renderTable)
107− , HasTable (getTable)
108− -- * TypeExpression
102+ -- * Types
109103 , TypeExpression (UnsafeTypeExpression, renderTypeExpression)
110104 , PGTyped (pgtype)
111105 , bool
@@ -143,6 +137,8 @@ module Squeal.PostgreSQL.Expression
143137 , inet
144138 , json
145139 , jsonb
140+ , vararray
141+ , fixarray
146142 , notNull
147143 , default_
148144 -- * Re-export
@@ -164,7 +160,7 @@ import Prelude hiding (id, (.))
164160
165161import qualified GHC.Generics as GHC
166162
167−import Squeal.PostgreSQL.Prettyprint
163+import Squeal.PostgreSQL.Render
168164import Squeal.PostgreSQL.Schema
169165
170166{-----------------------------------------
@@ -181,10 +177,10 @@ values from primitive expression using arithmetic, logical,
181177and other operations.
182178-}
183179newtype Expression
184− (tables :: TablesType)
180+ (relations :: RelationsType)
185181 (grouping :: Grouping)
186− (params :: [ColumnType])
187− (ty :: ColumnType)
182+ (params :: [NullityType])
183+ (ty :: NullityType)
188184 = UnsafeExpression { renderExpression :: ByteString }
189185 deriving (GHC.Generic,Show,Eq,Ord,NFData)
190186
@@ -196,123 +192,51 @@ supplied externally to a SQL statement.
196192separately from the SQL command string, in which case `param`s are used to
197193refer to the out-of-line data values.
198194-}
199−class (PGTyped (BaseType ty), KnownNat n)
200− => HasParameter (n :: Nat) params ty | n params -> ty where
201− param :: Expression tables grouping params ty
195+class (PGTyped (PGTypeOf ty), KnownNat n) => HasParameter
196+ (n :: Nat)
197+ (params :: [NullityType])
198+ (ty :: NullityType)
199+ | n params -> ty where
200+ param :: Expression relations grouping params ty
202201 param = UnsafeExpression $ parenthesized $
203202 "$" <> renderNat (Proxy @n) <+> "::"
204− <+> renderTypeExpression (pgtype @(BaseType ty))
205−instance {-# OVERLAPPING #-} PGTyped (BaseType ty1)
203+ <+> renderTypeExpression (pgtype @(PGTypeOf ty))
204+instance {-# OVERLAPPING #-} PGTyped (PGTypeOf ty1)
206205 => HasParameter 1 (ty1:tys) ty1
207206instance {-# OVERLAPPABLE #-} (KnownNat n, HasParameter (n-1) params ty)
208207 => HasParameter n (ty' : params) ty
209208
210−{- | A `HasColumn` constraint indicates an unqualified column reference.
211−`getColumn` can only be unambiguous when the `TableExpression` the column
212−references is unique, in which case the column may be referenced using
213−@-XOverloadedLabels@. Otherwise, combined with a `HasTable` constraint, the
214−qualified column reference operator `!` may be used.
215−-}
216−class KnownSymbol column => HasColumn column columns ty
217− | column columns -> ty where
218− getColumn
219− :: HasUnique table tables columns
220− => Alias column
221− -> Expression tables 'Ungrouped params ty
222− getColumn column = UnsafeExpression $ renderAlias column
223−instance {-# OVERLAPPING #-} KnownSymbol column
224− => HasColumn column ((column ::: optionality ty) ': tys) ('Required ty)
225−instance {-# OVERLAPPABLE #-} (KnownSymbol column, HasColumn column table ty)
226− => HasColumn column (ty' ': table) ty
227−
228−instance (HasColumn column columns ty, HasUnique table tables columns)
229− => IsLabel column (Expression tables 'Ungrouped params ty) where
230− fromLabel = getColumn (Alias @column)
231−
232−instance (HasTable table tables columns, HasColumn column columns ty)
233− => IsTableColumn table column (Expression tables 'Ungrouped params ty) where
234− table ! column = UnsafeExpression $
235− renderAlias table <> "." <> renderAlias column
236−
237−-- | A `Column` is a witness to a `HasColumn` constraint. It's used
238−-- in `Squeel.PostgreSQL.Definition.unique` and other
239−-- `Squeel.PostgreSQL.Definition.TableConstraint`s to witness a
240−-- subcolumns relationship.
241−data Column
242− (columns :: ColumnsType)
243− (columnty :: (Symbol,ColumnType))
244− where
245− Column
246− :: HasColumn column columns ty
247− => Alias column
248− -> Column columns (column ::: ty)
249−deriving instance Show (Column columns columnty)
250−deriving instance Eq (Column columns columnty)
251−deriving instance Ord (Column columns columnty)
252−
253−-- | Render a `Column`.
254−renderColumn :: Column columns columnty -> ByteString
255−renderColumn (Column column) = renderAlias column
256−
257−{- | A `GroupedBy` constraint indicates that a table qualified column is
258−a member of the auxiliary namespace created by @GROUP BY@ clauses and thus,
259−may be called in an output `Expression` without aggregating.
260−-}
261−class (KnownSymbol table, KnownSymbol column)
262− => GroupedBy table column bys where
263− getGroup1
264− :: (HasUnique table tables columns, HasColumn column columns ty)
265− => Alias column
266− -> Expression tables ('Grouped bys) params ty
267− getGroup1 column = UnsafeExpression $ renderAlias column
268− getGroup2
269− :: (HasTable table tables columns, HasColumn column columns ty)
270− => Alias table
271− -> Alias column
272− -> Expression tables ('Grouped bys) params ty
273− getGroup2 table column = UnsafeExpression $
274− renderAlias table <> "." <> renderAlias column
275−instance {-# OVERLAPPING #-} (KnownSymbol table, KnownSymbol column)
276− => GroupedBy table column ('(table,column) ': bys)
277−instance {-# OVERLAPPABLE #-}
278− ( KnownSymbol table
279− , KnownSymbol column
280− , GroupedBy table column bys
281− ) => GroupedBy table column (tabcol ': bys)
209+instance (HasUnique relation relations columns, Has column columns ty)
210+ => IsLabel column (Expression relations 'Ungrouped params ty) where
211+ fromLabel = UnsafeExpression $ renderAlias (Alias @column)
212+
213+instance (Has relation relations columns, Has column columns ty)
214+ => IsQualified relation column (Expression relations 'Ungrouped params ty) where
215+ relation ! column = UnsafeExpression $
216+ renderAlias relation <> "." <> renderAlias column
282217
283218instance
284− ( HasUnique table tables columns
285− , HasColumn column columns ty
286− , GroupedBy table column bys
219+ ( HasUnique relation relations columns
220+ , Has column columns ty
221+ , GroupedBy relation column bys
287222 ) => IsLabel column
288− (Expression tables ('Grouped bys) params ty) where
289− fromLabel = getGroup1 (Alias @column)
223+ (Expression relations ('Grouped bys) params ty) where
224+ fromLabel = UnsafeExpression $ renderAlias (Alias @column)
290225
291226instance
292− ( HasTable table tables columns
293− , HasColumn column columns ty
294− , GroupedBy table column bys
295− ) => IsTableColumn table column
296− (Expression tables ('Grouped bys) params ty) where (!) = getGroup2
297−
298−-- | >>> renderExpression def
299−-- "DEFAULT"
300−def :: Expression '[] 'Ungrouped params ('Optional (nullity ty))
301−def = UnsafeExpression "DEFAULT"
302−
303−-- | >>> renderExpression $ unDef false
304−-- "FALSE"
305−unDef
306− :: Expression '[] 'Ungrouped params ('Required (nullity ty))
307− -- ^ not @DEFAULT@
308− -> Expression '[] 'Ungrouped params ('Optional (nullity ty))
309−unDef = UnsafeExpression . renderExpression
227+ ( Has relation relations columns
228+ , Has column columns ty
229+ , GroupedBy relation column bys
230+ ) => IsQualified relation column
231+ (Expression relations ('Grouped bys) params ty) where
232+ relation ! column = UnsafeExpression $
233+ renderAlias relation <> "." <> renderAlias column
310234
311235-- | analagous to `Nothing`
312236--
313237-- >>> renderExpression $ null_
314238-- "NULL"
315−null_ :: Expression tables grouping params (optionality ('Null ty))
239+null_ :: Expression relations grouping params ('Null ty)
316240null_ = UnsafeExpression "NULL"
317241
318242-- | analagous to `Just`
@@ -320,9 +244,9 @@ null_ = UnsafeExpression "NULL"
320244-- >>> renderExpression $ unNull true
321245-- "TRUE"
322246unNull
323− :: Expression tables grouping params (optionality ('NotNull ty))
247+ :: Expression relations grouping params ('NotNull ty)
324248 -- ^ not @NULL@
325− -> Expression tables grouping params (optionality ('Null ty))
249+ -> Expression relations grouping params ('Null ty)
326250unNull = UnsafeExpression . renderExpression
327251
328252-- | return the leftmost value which is not NULL
@@ -330,40 +254,40 @@ unNull = UnsafeExpression . renderExpression
330254-- >>> renderExpression $ coalesce [null_, unNull true] false
331255-- "COALESCE(NULL, TRUE, FALSE)"
332256coalesce
333− :: [Expression tables grouping params ('Required ('Null ty))]
257+ :: [Expression relations grouping params ('Null ty)]
334258 -- ^ @NULL@s may be present
335− -> Expression tables grouping params ('Required ('NotNull ty))
259+ -> Expression relations grouping params ('NotNull ty)
336260 -- ^ @NULL@ is absent
337− -> Expression tables grouping params ('Required ('NotNull ty))
261+ -> Expression relations grouping params ('NotNull ty)
338262coalesce nullxs notNullx = UnsafeExpression $
339263 "COALESCE" <> parenthesized (commaSeparated
340264 ((renderExpression <$> nullxs) <> [renderExpression notNullx]))
341265
342−-- | analagous to `fromMaybe` using @COALESCE@
266+-- | analagous to `Data.Maybe.fromMaybe` using @COALESCE@
343267--
344268-- >>> renderExpression $ fromNull true null_
345269-- "COALESCE(NULL, TRUE)"
346270fromNull
347− :: Expression tables grouping params ('Required ('NotNull ty))
271+ :: Expression relations grouping params ('NotNull ty)
348272 -- ^ what to convert @NULL@ to
349− -> Expression tables grouping params ('Required ('Null ty))
350− -> Expression tables grouping params ('Required ('NotNull ty))
273+ -> Expression relations grouping params ('Null ty)
274+ -> Expression relations grouping params ('NotNull ty)
351275fromNull notNullx nullx = coalesce [nullx] notNullx
352276
353277-- | >>> renderExpression $ null_ & isNull
354278-- "NULL IS NULL"
355279isNull
356− :: Expression tables grouping params ('Required ('Null ty))
280+ :: Expression relations grouping params ('Null ty)
357281 -- ^ possibly @NULL@
358− -> Condition tables grouping params
282+ -> Condition relations grouping params
359283isNull x = UnsafeExpression $ renderExpression x <+> "IS NULL"
360284
361285-- | >>> renderExpression $ null_ & isn'tNull
362286-- "NULL IS NOT NULL"
363287isn'tNull
364− :: Expression tables grouping params ('Required ('Null ty))
288+ :: Expression relations grouping params ('Null ty)
365289 -- ^ possibly @NULL@
366− -> Condition tables grouping params
290+ -> Condition relations grouping params
367291isn'tNull x = UnsafeExpression $ renderExpression x <+> "IS NOT NULL"
368292
369293-- | analagous to `maybe` using @IS NULL@
@@ -371,13 +295,13 @@ isn'tNull x = UnsafeExpression $ renderExpression x <+> "IS NOT NULL"
371295-- >>> renderExpression $ matchNull true not_ null_
372296-- "CASE WHEN NULL IS NULL THEN TRUE ELSE (NOT NULL) END"
373297matchNull
374− :: Expression tables grouping params ('Required nullty)
298+ :: Expression relations grouping params (nullty)
375299 -- ^ what to convert @NULL@ to
376− -> ( Expression tables grouping params ('Required ('NotNull ty))
377− -> Expression tables grouping params ('Required nullty) )
300+ -> ( Expression relations grouping params ('NotNull ty)
301+ -> Expression relations grouping params (nullty) )
378302 -- ^ function to perform when @NULL@ is absent
379− -> Expression tables grouping params ('Required ('Null ty))
380− -> Expression tables grouping params ('Required nullty)
303+ -> Expression relations grouping params ('Null ty)
304+ -> Expression relations grouping params (nullty)
381305matchNull y f x = ifThenElse (isNull x) y
382306 (f (UnsafeExpression (renderExpression x)))
383307
@@ -388,33 +312,47 @@ matchNull y f x = ifThenElse (isNull x) y
388312-- >>> renderExpression @_ @_ @'[_] $ fromNull false (nullIf false (param @1))
389313-- "COALESCE(NULL IF (FALSE, ($1 :: bool)), FALSE)"
390314nullIf
391− :: Expression tables grouping params ('Required ('NotNull ty))
315+ :: Expression relations grouping params ('NotNull ty)
392316 -- ^ @NULL@ is absent
393− -> Expression tables grouping params ('Required ('NotNull ty))
317+ -> Expression relations grouping params ('NotNull ty)
394318 -- ^ @NULL@ is absent
395− -> Expression tables grouping params ('Required ('Null ty))
319+ -> Expression relations grouping params ('Null ty)
396320nullIf x y = UnsafeExpression $ "NULL IF" <+> parenthesized
397321 (renderExpression x <> ", " <> renderExpression y)
398322
323+-- | >>> renderExpression $ array [null_, unNull false, unNull true]
324+-- "ARRAY[NULL, FALSE, TRUE]"
325+array
326+ :: [Expression relations grouping params ('Null ty)]
327+ -- ^ array elements
328+ -> Expression relations grouping params (nullity ('PGvararray ty))
329+array xs = UnsafeExpression $
330+ "ARRAY[" <> commaSeparated (renderExpression <$> xs) <> "]"
331+
332+instance Monoid
333+ (Expression relations grouping params (nullity ('PGvararray ty))) where
334+ mempty = array []
335+ mappend = unsafeBinaryOp "||"
336+
399337-- | >>> renderExpression @_ @_ @'[_] $ greatest currentTimestamp [param @1]
400338-- "GREATEST(CURRENT_TIMESTAMP, ($1 :: timestamp with time zone))"
401339greatest
402− :: Expression tables grouping params ('Required nullty)
340+ :: Expression relations grouping params (nullty)
403341 -- ^ needs at least 1 argument
404− -> [Expression tables grouping params ('Required nullty)]
342+ -> [Expression relations grouping params (nullty)]
405343 -- ^ or more
406− -> Expression tables grouping params ('Required nullty)
344+ -> Expression relations grouping params (nullty)
407345greatest x xs = UnsafeExpression $ "GREATEST("
408346 <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
409347
410348-- | >>> renderExpression $ least currentTimestamp [null_]
411349-- "LEAST(CURRENT_TIMESTAMP, NULL)"
412350least
413− :: Expression tables grouping params ('Required nullty)
351+ :: Expression relations grouping params (nullty)
414352 -- ^ needs at least 1 argument
415− -> [Expression tables grouping params ('Required nullty)]
353+ -> [Expression relations grouping params (nullty)]
416354 -- ^ or more
417− -> Expression tables grouping params ('Required nullty)
355+ -> Expression relations grouping params (nullty)
418356least x xs = UnsafeExpression $ "LEAST("
419357 <> commaSeparated (renderExpression <$> (x:xs)) <> ")"
420358
@@ -423,9 +361,9 @@ least x xs = UnsafeExpression $ "LEAST("
423361unsafeBinaryOp
424362 :: ByteString
425363 -- ^ operator
426− -> Expression tables grouping params ('Required ty0)
427− -> Expression tables grouping params ('Required ty1)
428− -> Expression tables grouping params ('Required ty2)
364+ -> Expression relations grouping params (ty0)
365+ -> Expression relations grouping params (ty1)
366+ -> Expression relations grouping params (ty2)
429367unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
430368 renderExpression x <+> op <+> renderExpression y
431369
@@ -434,8 +372,8 @@ unsafeBinaryOp op x y = UnsafeExpression $ parenthesized $
434372unsafeUnaryOp
435373 :: ByteString
436374 -- ^ operator
437− -> Expression tables grouping params ('Required ty0)
438− -> Expression tables grouping params ('Required ty1)
375+ -> Expression relations grouping params (ty0)
376+ -> Expression relations grouping params (ty1)
439377unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
440378 op <+> renderExpression x
441379
@@ -444,13 +382,13 @@ unsafeUnaryOp op x = UnsafeExpression $ parenthesized $
444382unsafeFunction
445383 :: ByteString
446384 -- ^ function
447− -> Expression tables grouping params ('Required xty)
448− -> Expression tables grouping params ('Required yty)
385+ -> Expression relations grouping params (xty)
386+ -> Expression relations grouping params (yty)
449387unsafeFunction fun x = UnsafeExpression $
450388 fun <> parenthesized (renderExpression x)
451389
452390instance PGNum ty
453− => Num (Expression tables grouping params ('Required (nullity ty))) where
391+ => Num (Expression relations grouping params (nullity ty)) where
454392 (+) = unsafeBinaryOp "+"
455393 (-) = unsafeBinaryOp "-"
456394 (*) = unsafeBinaryOp "*"
@@ -462,12 +400,12 @@ instance PGNum ty
462400 . show
463401
464402instance (PGNum ty, PGFloating ty) => Fractional
465− (Expression tables grouping params ('Required (nullity ty))) where
403+ (Expression relations grouping params (nullity ty)) where
466404 (/) = unsafeBinaryOp "/"
467405 fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
468406
469407instance (PGNum ty, PGFloating ty) => Floating
470− (Expression tables grouping params ('Required (nullity ty))) where
408+ (Expression relations grouping params (nullity ty)) where
471409 pi = UnsafeExpression "pi()"
472410 exp = unsafeFunction "exp"
473411 log = unsafeFunction "ln"
@@ -488,15 +426,20 @@ instance (PGNum ty, PGFloating ty) => Floating
488426 acosh x = log (x + sqrt (x*x - 1))
489427 atanh x = log ((1 + x) / (1 - x)) / 2
490428
491−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGfloat4)) $ atan2_ pi 2
429+-- | >>> :{
430+-- let
431+-- expression :: Expression relations grouping params (nullity 'PGfloat4)
432+-- expression = atan2_ pi 2
433+-- in renderExpression expression
434+-- :}
492435-- "atan2(pi(), 2)"
493436atan2_
494437 :: PGFloating float
495− => Expression tables grouping params ('Required (nullity float))
438+ => Expression relations grouping params (nullity float)
496439 -- ^ numerator
497− -> Expression tables grouping params ('Required (nullity float))
440+ -> Expression relations grouping params (nullity float)
498441 -- ^ denominator
499− -> Expression tables grouping params ('Required (nullity float))
442+ -> Expression relations grouping params (nullity float)
500443atan2_ y x = UnsafeExpression $
501444 "atan2(" <> renderExpression y <> ", " <> renderExpression x <> ")"
502445
@@ -507,115 +450,147 @@ atan2_ y x = UnsafeExpression $
507450-- | >>> renderExpression $ true & cast int4
508451-- "(TRUE :: int4)"
509452cast
510− :: TypeExpression ('Required ('Null ty1))
453+ :: TypeExpression ('NoDef :=> 'Null ty1)
511454 -- ^ type to cast as
512− -> Expression tables grouping params ('Required (nullity ty0))
455+ -> Expression relations grouping params (nullity ty0)
513456 -- ^ value to convert
514− -> Expression tables grouping params ('Required (nullity ty1))
457+ -> Expression relations grouping params (nullity ty1)
515458cast ty x = UnsafeExpression $ parenthesized $
516459 renderExpression x <+> "::" <+> renderTypeExpression ty
517460
518461-- | integer division, truncates the result
519462--
520−-- >>> renderExpression @_ @_ @_ @(_(_ 'PGint2)) $ 5 `quot_` 2
463+-- >>> :{
464+-- let
465+-- expression :: Expression relations grouping params (nullity 'PGint2)
466+-- expression = 5 `quot_` 2
467+-- in renderExpression expression
468+-- :}
521469-- "(5 / 2)"
522470quot_
523471 :: PGIntegral int
524− => Expression tables grouping params ('Required (nullity int))
472+ => Expression relations grouping params (nullity int)
525473 -- ^ numerator
526− -> Expression tables grouping params ('Required (nullity int))
474+ -> Expression relations grouping params (nullity int)
527475 -- ^ denominator
528− -> Expression tables grouping params ('Required (nullity int))
476+ -> Expression relations grouping params (nullity int)
529477quot_ = unsafeBinaryOp "/"
530478
531479-- | remainder upon integer division
532480--
533−-- >>> renderExpression @_ @_ @_ @(_ (_ 'PGint2)) $ 5 `rem_` 2
481+-- >>> :{
482+-- let
483+-- expression :: Expression relations grouping params (nullity 'PGint2)
484+-- expression = 5 `rem_` 2
485+-- in renderExpression expression
486+-- :}
534487-- "(5 % 2)"
535488rem_
536489 :: PGIntegral int
537− => Expression tables grouping params ('Required (nullity int))
490+ => Expression relations grouping params (nullity int)
538491 -- ^ numerator
539− -> Expression tables grouping params ('Required (nullity int))
492+ -> Expression relations grouping params (nullity int)
540493 -- ^ denominator
541− -> Expression tables grouping params ('Required (nullity int))
494+ -> Expression relations grouping params (nullity int)
542495rem_ = unsafeBinaryOp "%"
543496
544−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGfloat4)) $ trunc pi
497+-- | >>> :{
498+-- let
499+-- expression :: Expression relations grouping params (nullity 'PGfloat4)
500+-- expression = trunc pi
501+-- in renderExpression expression
502+-- :}
545503-- "trunc(pi())"
546504trunc
547505 :: PGFloating frac
548− => Expression tables grouping params ('Required (nullity frac))
506+ => Expression relations grouping params (nullity frac)
549507 -- ^ fractional number
550− -> Expression tables grouping params ('Required (nullity frac))
508+ -> Expression relations grouping params (nullity frac)
551509trunc = unsafeFunction "trunc"
552510
553−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGfloat4)) $ round_ pi
511+-- | >>> :{
512+-- let
513+-- expression :: Expression relations grouping params (nullity 'PGfloat4)
514+-- expression = round_ pi
515+-- in renderExpression expression
516+-- :}
554517-- "round(pi())"
555518round_
556519 :: PGFloating frac
557− => Expression tables grouping params ('Required (nullity frac))
520+ => Expression relations grouping params (nullity frac)
558521 -- ^ fractional number
559− -> Expression tables grouping params ('Required (nullity frac))
522+ -> Expression relations grouping params (nullity frac)
560523round_ = unsafeFunction "round"
561524
562−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGfloat4)) $ ceiling_ pi
525+-- | >>> :{
526+-- let
527+-- expression :: Expression relations grouping params (nullity 'PGfloat4)
528+-- expression = ceiling_ pi
529+-- in renderExpression expression
530+-- :}
563531-- "ceiling(pi())"
564532ceiling_
565533 :: PGFloating frac
566− => Expression tables grouping params ('Required (nullity frac))
534+ => Expression relations grouping params (nullity frac)
567535 -- ^ fractional number
568− -> Expression tables grouping params ('Required (nullity frac))
536+ -> Expression relations grouping params (nullity frac)
569537ceiling_ = unsafeFunction "ceiling"
570538
571539-- | A `Condition` is a boolean valued `Expression`. While SQL allows
572−-- conditions to have @NULL@, squeal instead chooses to disallow @NULL@,
540+-- conditions to have @NULL@, Squeal instead chooses to disallow @NULL@,
573541-- forcing one to handle the case of @NULL@ explicitly to produce
574542-- a `Condition`.
575−type Condition tables grouping params =
576− Expression tables grouping params ('Required ('NotNull 'PGbool))
543+type Condition relations grouping params =
544+ Expression relations grouping params ('NotNull 'PGbool)
577545
578546-- | >>> renderExpression true
579547-- "TRUE"
580−true :: Condition tables grouping params
548+true :: Condition relations grouping params
581549true = UnsafeExpression "TRUE"
582550
583551-- | >>> renderExpression false
584552-- "FALSE"
585−false :: Condition tables grouping params
553+false :: Condition relations grouping params
586554false = UnsafeExpression "FALSE"
587555
588556-- | >>> renderExpression $ not_ true
589557-- "(NOT TRUE)"
590558not_
591− :: Condition tables grouping params
592− -> Condition tables grouping params
559+ :: Condition relations grouping params
560+ -> Condition relations grouping params
593561not_ = unsafeUnaryOp "NOT"
594562
595563-- | >>> renderExpression $ true .&& false
596564-- "(TRUE AND FALSE)"
597565(.&&)
598− :: Condition tables grouping params
599− -> Condition tables grouping params
600− -> Condition tables grouping params
566+ :: Condition relations grouping params
567+ -> Condition relations grouping params
568+ -> Condition relations grouping params
601569(.&&) = unsafeBinaryOp "AND"
602570
603571-- | >>> renderExpression $ true .|| false
604572-- "(TRUE OR FALSE)"
605573(.||)
606− :: Condition tables grouping params
607− -> Condition tables grouping params
608− -> Condition tables grouping params
574+ :: Condition relations grouping params
575+ -> Condition relations grouping params
576+ -> Condition relations grouping params
609577(.||) = unsafeBinaryOp "OR"
610578
611−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGint2)) $ caseWhenThenElse [(true, 1), (false, 2)] 3
579+-- | >>> :{
580+-- let
581+-- expression :: Expression relations grouping params (nullity 'PGint2)
582+-- expression = caseWhenThenElse [(true, 1), (false, 2)] 3
583+-- in renderExpression expression
584+-- :}
612585-- "CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 ELSE 3 END"
613586caseWhenThenElse
614− :: [ ( Condition tables grouping params
615− , Expression tables grouping params ('Required ty)
587+ :: [ ( Condition relations grouping params
588+ , Expression relations grouping params (ty)
616589 ) ]
617− -> Expression tables grouping params ('Required ty)
618− -> Expression tables grouping params ('Required ty)
590+ -- ^ whens and thens
591+ -> Expression relations grouping params (ty)
592+ -- ^ else
593+ -> Expression relations grouping params (ty)
619594caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
620595 [ "CASE"
621596 , mconcat
@@ -629,13 +604,18 @@ caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
629604 , " END"
630605 ]
631606
632−-- | >>> renderExpression @_ @_ @_ @(_ (_ 'PGint2)) $ ifThenElse true 1 0
607+-- | >>> :{
608+-- let
609+-- expression :: Expression relations grouping params (nullity 'PGint2)
610+-- expression = ifThenElse true 1 0
611+-- in renderExpression expression
612+-- :}
633613-- "CASE WHEN TRUE THEN 1 ELSE 0 END"
634614ifThenElse
635− :: Condition tables grouping params
636− -> Expression tables grouping params ('Required ty)
637− -> Expression tables grouping params ('Required ty)
638− -> Expression tables grouping params ('Required ty)
615+ :: Condition relations grouping params
616+ -> Expression relations grouping params (ty) -- ^ then
617+ -> Expression relations grouping params (ty) -- ^ else
618+ -> Expression relations grouping params (ty)
639619ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
640620
641621-- | Comparison operations like `.==`, `./=`, `.>`, `.>=`, `.<` and `.<=`
@@ -644,85 +624,85 @@ ifThenElse if_ then_ else_ = caseWhenThenElse [(if_,then_)] else_
644624-- >>> renderExpression $ unNull true .== null_
645625-- "(TRUE = NULL)"
646626(.==)
647− :: Expression tables grouping params ('Required (nullity ty)) -- ^ lhs
648− -> Expression tables grouping params ('Required (nullity ty)) -- ^ rhs
649− -> Expression tables grouping params ('Required (nullity 'PGbool))
627+ :: Expression relations grouping params (nullity ty) -- ^ lhs
628+ -> Expression relations grouping params (nullity ty) -- ^ rhs
629+ -> Expression relations grouping params (nullity 'PGbool)
650630(.==) = unsafeBinaryOp "="
651631infix 4 .==
652632
653633-- | >>> renderExpression $ unNull true ./= null_
654634-- "(TRUE <> NULL)"
655635(./=)
656− :: Expression tables grouping params ('Required (nullity ty)) -- ^ lhs
657− -> Expression tables grouping params ('Required (nullity ty)) -- ^ rhs
658− -> Expression tables grouping params ('Required (nullity 'PGbool))
636+ :: Expression relations grouping params (nullity ty) -- ^ lhs
637+ -> Expression relations grouping params (nullity ty) -- ^ rhs
638+ -> Expression relations grouping params (nullity 'PGbool)
659639(./=) = unsafeBinaryOp "<>"
660640infix 4 ./=
661641
662642-- | >>> renderExpression $ unNull true .>= null_
663643-- "(TRUE >= NULL)"
664644(.>=)
665− :: Expression tables grouping params ('Required (nullity ty)) -- ^ lhs
666− -> Expression tables grouping params ('Required (nullity ty)) -- ^ rhs
667− -> Expression tables grouping params ('Required (nullity 'PGbool))
645+ :: Expression relations grouping params (nullity ty) -- ^ lhs
646+ -> Expression relations grouping params (nullity ty) -- ^ rhs
647+ -> Expression relations grouping params (nullity 'PGbool)
668648(.>=) = unsafeBinaryOp ">="
669649infix 4 .>=
670650
671651-- | >>> renderExpression $ unNull true .< null_
672652-- "(TRUE < NULL)"
673653(.<)
674− :: Expression tables grouping params ('Required (nullity ty)) -- ^ lhs
675− -> Expression tables grouping params ('Required (nullity ty)) -- ^ rhs
676− -> Expression tables grouping params ('Required (nullity 'PGbool))
654+ :: Expression relations grouping params (nullity ty) -- ^ lhs
655+ -> Expression relations grouping params (nullity ty) -- ^ rhs
656+ -> Expression relations grouping params (nullity 'PGbool)
677657(.<) = unsafeBinaryOp "<"
678658infix 4 .<
679659
680660-- | >>> renderExpression $ unNull true .<= null_
681661-- "(TRUE <= NULL)"
682662(.<=)
683− :: Expression tables grouping params ('Required (nullity ty)) -- ^ lhs
684− -> Expression tables grouping params ('Required (nullity ty)) -- ^ rhs
685− -> Expression tables grouping params ('Required (nullity 'PGbool))
663+ :: Expression relations grouping params (nullity ty) -- ^ lhs
664+ -> Expression relations grouping params (nullity ty) -- ^ rhs
665+ -> Expression relations grouping params (nullity 'PGbool)
686666(.<=) = unsafeBinaryOp "<="
687667infix 4 .<=
688668
689669-- | >>> renderExpression $ unNull true .> null_
690670-- "(TRUE > NULL)"
691671(.>)
692− :: Expression tables grouping params ('Required (nullity ty)) -- ^ lhs
693− -> Expression tables grouping params ('Required (nullity ty)) -- ^ rhs
694− -> Expression tables grouping params ('Required (nullity 'PGbool))
672+ :: Expression relations grouping params (nullity ty) -- ^ lhs
673+ -> Expression relations grouping params (nullity ty) -- ^ rhs
674+ -> Expression relations grouping params (nullity 'PGbool)
695675(.>) = unsafeBinaryOp ">"
696676infix 4 .>
697677
698−-- | >>> renderExpression $ currentDate
678+-- | >>> renderExpression currentDate
699679-- "CURRENT_DATE"
700680currentDate
701− :: Expression tables grouping params ('Required (nullity 'PGdate))
681+ :: Expression relations grouping params (nullity 'PGdate)
702682currentDate = UnsafeExpression "CURRENT_DATE"
703683
704−-- | >>> renderExpression $ currentTime
684+-- | >>> renderExpression currentTime
705685-- "CURRENT_TIME"
706686currentTime
707− :: Expression tables grouping params ('Required (nullity 'PGtimetz))
687+ :: Expression relations grouping params (nullity 'PGtimetz)
708688currentTime = UnsafeExpression "CURRENT_TIME"
709689
710−-- | >>> renderExpression $ currentTimestamp
690+-- | >>> renderExpression currentTimestamp
711691-- "CURRENT_TIMESTAMP"
712692currentTimestamp
713− :: Expression tables grouping params ('Required (nullity 'PGtimestamptz))
693+ :: Expression relations grouping params (nullity 'PGtimestamptz)
714694currentTimestamp = UnsafeExpression "CURRENT_TIMESTAMP"
715695
716−-- | >>> renderExpression $ localTime
696+-- | >>> renderExpression localTime
717697-- "LOCALTIME"
718698localTime
719− :: Expression tables grouping params ('Required (nullity 'PGtime))
699+ :: Expression relations grouping params (nullity 'PGtime)
720700localTime = UnsafeExpression "LOCALTIME"
721701
722−-- | >>> renderExpression $ localTimestamp
702+-- | >>> renderExpression localTimestamp
723703-- "LOCALTIMESTAMP"
724704localTimestamp
725− :: Expression tables grouping params ('Required (nullity 'PGtimestamp))
705+ :: Expression relations grouping params (nullity 'PGtimestamp)
726706localTimestamp = UnsafeExpression "LOCALTIMESTAMP"
727707
728708{-----------------------------------------
@@ -730,7 +710,7 @@ text
730710-----------------------------------------}
731711
732712instance IsString
733− (Expression tables grouping params ('Required (nullity 'PGtext))) where
713+ (Expression relations grouping params (nullity 'PGtext)) where
734714 fromString str = UnsafeExpression $
735715 "E\'" <> fromString (escape =<< str) <> "\'"
736716 where
@@ -746,32 +726,32 @@ instance IsString
746726 c -> [c]
747727
748728instance Monoid
749− (Expression tables grouping params ('Required (nullity 'PGtext))) where
729+ (Expression relations grouping params (nullity 'PGtext)) where
750730 mempty = fromString ""
751731 mappend = unsafeBinaryOp "||"
752732
753733-- | >>> renderExpression $ lower "ARRRGGG"
754734-- "lower(E'ARRRGGG')"
755735lower
756− :: Expression tables grouping params ('Required (nullity 'PGtext))
736+ :: Expression relations grouping params (nullity 'PGtext)
757737 -- ^ string to lower case
758− -> Expression tables grouping params ('Required (nullity 'PGtext))
738+ -> Expression relations grouping params (nullity 'PGtext)
759739lower = unsafeFunction "lower"
760740
761741-- | >>> renderExpression $ upper "eeee"
762742-- "upper(E'eeee')"
763743upper
764− :: Expression tables grouping params ('Required (nullity 'PGtext))
744+ :: Expression relations grouping params (nullity 'PGtext)
765745 -- ^ string to upper case
766− -> Expression tables grouping params ('Required (nullity 'PGtext))
746+ -> Expression relations grouping params (nullity 'PGtext)
767747upper = unsafeFunction "upper"
768748
769749-- | >>> renderExpression $ charLength "four"
770750-- "char_length(E'four')"
771751charLength
772− :: Expression tables grouping params ('Required (nullity 'PGtext))
752+ :: Expression relations grouping params (nullity 'PGtext)
773753 -- ^ string to measure
774− -> Expression tables grouping params ('Required (nullity 'PGint4))
754+ -> Expression relations grouping params (nullity 'PGint4)
775755charLength = unsafeFunction "char_length"
776756
777757-- | The `like` expression returns true if the @string@ matches
@@ -784,11 +764,11 @@ charLength = unsafeFunction "char_length"
784764-- >>> renderExpression $ "abc" `like` "a%"
785765-- "(E'abc' LIKE E'a%')"
786766like
787− :: Expression tables grouping params ('Required (nullity 'PGtext))
767+ :: Expression relations grouping params (nullity 'PGtext)
788768 -- ^ string
789− -> Expression tables grouping params ('Required (nullity 'PGtext))
769+ -> Expression relations grouping params (nullity 'PGtext)
790770 -- ^ pattern
791− -> Expression tables grouping params ('Required (nullity 'PGbool))
771+ -> Expression relations grouping params (nullity 'PGbool)
792772like = unsafeBinaryOp "LIKE"
793773
794774{-----------------------------------------
@@ -798,44 +778,54 @@ aggregation
798778-- | escape hatch to define aggregate functions
799779unsafeAggregate
800780 :: ByteString -- ^ aggregate function
801− -> Expression tables 'Ungrouped params ('Required xty)
802− -> Expression tables ('Grouped bys) params ('Required yty)
781+ -> Expression relations 'Ungrouped params (xty)
782+ -> Expression relations ('Grouped bys) params (yty)
803783unsafeAggregate fun x = UnsafeExpression $ mconcat
804784 [fun, "(", renderExpression x, ")"]
805785
806786-- | escape hatch to define aggregate functions over distinct values
807787unsafeAggregateDistinct
808788 :: ByteString -- ^ aggregate function
809− -> Expression tables 'Ungrouped params ('Required xty)
810− -> Expression tables ('Grouped bys) params ('Required yty)
789+ -> Expression relations 'Ungrouped params (xty)
790+ -> Expression relations ('Grouped bys) params (yty)
811791unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
812792 [fun, "(DISTINCT ", renderExpression x, ")"]
813793
814−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGnumeric)]] $ sum_ #col
794+-- | >>> :{
795+-- let
796+-- expression :: Expression '[tab ::: '["col" ::: 'Null 'PGnumeric]] ('Grouped bys) params ('Null 'PGnumeric)
797+-- expression = sum_ #col
798+-- in renderExpression expression
799+-- :}
815800-- "sum(col)"
816801sum_
817802 :: PGNum ty
818− => Expression tables 'Ungrouped params ('Required (nullity ty))
803+ => Expression relations 'Ungrouped params (nullity ty)
819804 -- ^ what to sum
820− -> Expression tables ('Grouped bys) params ('Required (nullity ty))
805+ -> Expression relations ('Grouped bys) params (nullity ty)
821806sum_ = unsafeAggregate "sum"
822807
823−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGnumeric)]] $ sumDistinct #col
808+-- | >>> :{
809+-- let
810+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGnumeric]] ('Grouped bys) params (nullity 'PGnumeric)
811+-- expression = sumDistinct #col
812+-- in renderExpression expression
813+-- :}
824814-- "sum(DISTINCT col)"
825815sumDistinct
826816 :: PGNum ty
827− => Expression tables 'Ungrouped params ('Required (nullity ty))
817+ => Expression relations 'Ungrouped params (nullity ty)
828818 -- ^ what to sum
829− -> Expression tables ('Grouped bys) params ('Required (nullity ty))
819+ -> Expression relations ('Grouped bys) params (nullity ty)
830820sumDistinct = unsafeAggregateDistinct "sum"
831821
832822-- | A constraint for `PGType`s that you can take averages of and the resulting
833823-- `PGType`.
834824class PGAvg ty avg | ty -> avg where
835825 avg, avgDistinct
836− :: Expression tables 'Ungrouped params ('Required (nullity ty))
826+ :: Expression relations 'Ungrouped params (nullity ty)
837827 -- ^ what to average
838− -> Expression tables ('Grouped bys) params ('Required (nullity avg))
828+ -> Expression relations ('Grouped bys) params (nullity avg)
839829 avg = unsafeAggregate "avg"
840830 avgDistinct = unsafeAggregateDistinct "avg"
841831instance PGAvg 'PGint2 'PGnumeric
@@ -846,72 +836,112 @@ instance PGAvg 'PGfloat4 'PGfloat8
846836instance PGAvg 'PGfloat8 'PGfloat8
847837instance PGAvg 'PGinterval 'PGinterval
848838
849−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGint4)]] $ bitAnd #col
839+-- | >>> :{
840+-- let
841+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
842+-- expression = bitAnd #col
843+-- in renderExpression expression
844+-- :}
850845-- "bit_and(col)"
851846bitAnd
852847 :: PGIntegral int
853− => Expression tables 'Ungrouped params ('Required (nullity int))
848+ => Expression relations 'Ungrouped params (nullity int)
854849 -- ^ what to aggregate
855− -> Expression tables ('Grouped bys) params ('Required (nullity int))
850+ -> Expression relations ('Grouped bys) params (nullity int)
856851bitAnd = unsafeAggregate "bit_and"
857852
858−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGint4)]] $ bitOr #col
853+-- | >>> :{
854+-- let
855+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
856+-- expression = bitOr #col
857+-- in renderExpression expression
858+-- :}
859859-- "bit_or(col)"
860860bitOr
861861 :: PGIntegral int
862− => Expression tables 'Ungrouped params ('Required (nullity int))
862+ => Expression relations 'Ungrouped params (nullity int)
863863 -- ^ what to aggregate
864− -> Expression tables ('Grouped bys) params ('Required (nullity int))
864+ -> Expression relations ('Grouped bys) params (nullity int)
865865bitOr = unsafeAggregate "bit_or"
866866
867−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGint4)]] $ bitAndDistinct #col
867+-- | >>> :{
868+-- let
869+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
870+-- expression = bitAndDistinct #col
871+-- in renderExpression expression
872+-- :}
868873-- "bit_and(DISTINCT col)"
869874bitAndDistinct
870875 :: PGIntegral int
871− => Expression tables 'Ungrouped params ('Required (nullity int))
876+ => Expression relations 'Ungrouped params (nullity int)
872877 -- ^ what to aggregate
873− -> Expression tables ('Grouped bys) params ('Required (nullity int))
878+ -> Expression relations ('Grouped bys) params (nullity int)
874879bitAndDistinct = unsafeAggregateDistinct "bit_and"
875880
876−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGint4)]] $ bitOrDistinct #col
881+-- | >>> :{
882+-- let
883+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGint4]] (Grouped bys) params (nullity 'PGint4)
884+-- expression = bitOrDistinct #col
885+-- in renderExpression expression
886+-- :}
877887-- "bit_or(DISTINCT col)"
878888bitOrDistinct
879889 :: PGIntegral int
880− => Expression tables 'Ungrouped params ('Required (nullity int))
890+ => Expression relations 'Ungrouped params (nullity int)
881891 -- ^ what to aggregate
882− -> Expression tables ('Grouped bys) params ('Required (nullity int))
892+ -> Expression relations ('Grouped bys) params (nullity int)
883893bitOrDistinct = unsafeAggregateDistinct "bit_or"
884894
885−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ boolAnd #col
895+-- | >>> :{
896+-- let
897+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
898+-- expression = boolAnd #col
899+-- in renderExpression expression
900+-- :}
886901-- "bool_and(col)"
887902boolAnd
888− :: Expression tables 'Ungrouped params ('Required (nullity 'PGbool))
903+ :: Expression relations 'Ungrouped params (nullity 'PGbool)
889904 -- ^ what to aggregate
890− -> Expression tables ('Grouped bys) params ('Required (nullity 'PGbool))
905+ -> Expression relations ('Grouped bys) params (nullity 'PGbool)
891906boolAnd = unsafeAggregate "bool_and"
892907
893−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ boolOr #col
908+-- | >>> :{
909+-- let
910+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
911+-- expression = boolOr #col
912+-- in renderExpression expression
913+-- :}
894914-- "bool_or(col)"
895915boolOr
896− :: Expression tables 'Ungrouped params ('Required (nullity 'PGbool))
916+ :: Expression relations 'Ungrouped params (nullity 'PGbool)
897917 -- ^ what to aggregate
898− -> Expression tables ('Grouped bys) params ('Required (nullity 'PGbool))
918+ -> Expression relations ('Grouped bys) params (nullity 'PGbool)
899919boolOr = unsafeAggregate "bool_or"
900920
901−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ boolAndDistinct #col
921+-- | >>> :{
922+-- let
923+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
924+-- expression = boolAndDistinct #col
925+-- in renderExpression expression
926+-- :}
902927-- "bool_and(DISTINCT col)"
903928boolAndDistinct
904− :: Expression tables 'Ungrouped params ('Required (nullity 'PGbool))
929+ :: Expression relations 'Ungrouped params (nullity 'PGbool)
905930 -- ^ what to aggregate
906− -> Expression tables ('Grouped bys) params ('Required (nullity 'PGbool))
931+ -> Expression relations ('Grouped bys) params (nullity 'PGbool)
907932boolAndDistinct = unsafeAggregateDistinct "bool_and"
908933
909−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ boolOrDistinct #col
934+-- | >>> :{
935+-- let
936+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
937+-- expression = boolOrDistinct #col
938+-- in renderExpression expression
939+-- :}
910940-- "bool_or(DISTINCT col)"
911941boolOrDistinct
912− :: Expression tables 'Ungrouped params ('Required (nullity 'PGbool))
942+ :: Expression relations 'Ungrouped params (nullity 'PGbool)
913943 -- ^ what to aggregate
914− -> Expression tables ('Grouped bys) params ('Required (nullity 'PGbool))
944+ -> Expression relations ('Grouped bys) params (nullity 'PGbool)
915945boolOrDistinct = unsafeAggregateDistinct "bool_or"
916946
917947-- | A special aggregation that does not require an input
@@ -919,50 +949,70 @@ boolOrDistinct = unsafeAggregateDistinct "bool_or"
919949-- >>> renderExpression countStar
920950-- "count(*)"
921951countStar
922− :: Expression tables ('Grouped bys) params ('Required ('NotNull 'PGint8))
952+ :: Expression relations ('Grouped bys) params ('NotNull 'PGint8)
923953countStar = UnsafeExpression $ "count(*)"
924954
925−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Optional _]] $ count #col
955+-- | >>> :{
956+-- let
957+-- expression :: Expression '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
958+-- expression = count #col
959+-- in renderExpression expression
960+-- :}
926961-- "count(col)"
927962count
928− :: Expression tables 'Ungrouped params ('Required ty)
963+ :: Expression relations 'Ungrouped params ty
929964 -- ^ what to count
930− -> Expression tables ('Grouped bys) params ('Required ('NotNull 'PGint8))
965+ -> Expression relations ('Grouped bys) params ('NotNull 'PGint8)
931966count = unsafeAggregate "count"
932967
933−-- | >>> renderExpression @'[_ ::: '["col" ::: 'Required _]] $ countDistinct #col
968+-- | >>> :{
969+-- let
970+-- expression :: Expression '[tab ::: '["col" ::: nullity ty]] (Grouped bys) params ('NotNull 'PGint8)
971+-- expression = countDistinct #col
972+-- in renderExpression expression
973+-- :}
934974-- "count(DISTINCT col)"
935975countDistinct
936− :: Expression tables 'Ungrouped params ('Required ty)
976+ :: Expression relations 'Ungrouped params ty
937977 -- ^ what to count
938− -> Expression tables ('Grouped bys) params ('Required ('NotNull 'PGint8))
978+ -> Expression relations ('Grouped bys) params ('NotNull 'PGint8)
939979countDistinct = unsafeAggregateDistinct "count"
940980
941981-- | synonym for `boolAnd`
942982--
943−-- >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ every #col
983+-- >>> :{
984+-- let
985+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
986+-- expression = every #col
987+-- in renderExpression expression
988+-- :}
944989-- "every(col)"
945990every
946− :: Expression tables 'Ungrouped params ('Required (nullity 'PGbool))
991+ :: Expression relations 'Ungrouped params (nullity 'PGbool)
947992 -- ^ what to aggregate
948− -> Expression tables ('Grouped bys) params ('Required (nullity 'PGbool))
993+ -> Expression relations ('Grouped bys) params (nullity 'PGbool)
949994every = unsafeAggregate "every"
950995
951996-- | synonym for `boolAndDistinct`
952997--
953−-- >>> renderExpression @'[_ ::: '["col" ::: 'Required (_ 'PGbool)]] $ everyDistinct #col
998+-- >>> :{
999+-- let
1000+-- expression :: Expression '[tab ::: '["col" ::: nullity 'PGbool]] (Grouped bys) params (nullity 'PGbool)
1001+-- expression = everyDistinct #col
1002+-- in renderExpression expression
1003+-- :}
9541004-- "every(DISTINCT col)"
9551005everyDistinct
956− :: Expression tables 'Ungrouped params ('Required (nullity 'PGbool))
1006+ :: Expression relations 'Ungrouped params (nullity 'PGbool)
9571007 -- ^ what to aggregate
958− -> Expression tables ('Grouped bys) params ('Required (nullity 'PGbool))
1008+ -> Expression relations ('Grouped bys) params (nullity 'PGbool)
9591009everyDistinct = unsafeAggregateDistinct "every"
9601010
9611011-- | minimum and maximum aggregation
9621012max_, min_, maxDistinct, minDistinct
963− :: Expression tables 'Ungrouped params ('Required (nullity ty))
1013+ :: Expression relations 'Ungrouped params (nullity ty)
9641014 -- ^ what to aggregate
965− -> Expression tables ('Grouped bys) params ('Required (nullity ty))
1015+ -> Expression relations ('Grouped bys) params (nullity ty)
9661016max_ = unsafeAggregate "max"
9671017min_ = unsafeAggregate "min"
9681018maxDistinct = unsafeAggregateDistinct "max"
@@ -972,28 +1022,18 @@ minDistinct = unsafeAggregateDistinct "min"
9721022tables
9731023-----------------------------------------}
9741024
975−-- | A `Table` from a schema without its alias with an `IsLabel` instance
1025+-- | A `Table` from a table expression is a way
9761026-- to call a table reference by its alias.
9771027newtype Table
9781028 (schema :: TablesType)
979− (columns :: ColumnsType)
1029+ (columns :: RelationType)
9801030 = UnsafeTable { renderTable :: ByteString }
9811031 deriving (GHC.Generic,Show,Eq,Ord,NFData)
982−
983−-- | A `HasTable` constraint indicates a table reference.
984−class KnownSymbol table => HasTable table tables columns
985− | table tables -> columns where
986− getTable :: Alias table -> Table tables columns
987− getTable table = UnsafeTable $ renderAlias table
988−instance {-# OVERLAPPING #-} KnownSymbol table
989− => HasTable table ((table ::: columns) ': tables) columns
990−instance {-# OVERLAPPABLE #-}
991− (KnownSymbol table, HasTable table schema columns)
992− => HasTable table (table' ': schema) columns
993−
994−instance HasTable table schema columns
995− => IsLabel table (Table schema columns) where
996− fromLabel = getTable (Alias @table)
1032+instance
1033+ ( Has alias schema table
1034+ , relation ~ ColumnsToRelation (TableToColumns table)
1035+ ) => IsLabel alias (Table schema relation) where
1036+ fromLabel = UnsafeTable $ renderAlias (Alias @alias)
9971037
9981038{-----------------------------------------
9991039type expressions
@@ -1005,117 +1045,136 @@ newtype TypeExpression (ty :: ColumnType)
10051045 deriving (GHC.Generic,Show,Eq,Ord,NFData)
10061046
10071047-- | logical Boolean (true/false)
1008−bool :: TypeExpression ('Required ('Null 'PGbool))
1048+bool :: TypeExpression ('NoDef :=> 'Null 'PGbool)
10091049bool = UnsafeTypeExpression "bool"
10101050-- | signed two-byte integer
1011−int2, smallint :: TypeExpression ('Required ('Null 'PGint2))
1051+int2, smallint :: TypeExpression ('NoDef :=> 'Null 'PGint2)
10121052int2 = UnsafeTypeExpression "int2"
10131053smallint = UnsafeTypeExpression "smallint"
10141054-- | signed four-byte integer
1015−int4, int, integer :: TypeExpression ('Required ('Null 'PGint4))
1055+int4, int, integer :: TypeExpression ('NoDef :=> 'Null 'PGint4)
10161056int4 = UnsafeTypeExpression "int4"
10171057int = UnsafeTypeExpression "int"
10181058integer = UnsafeTypeExpression "integer"
10191059-- | signed eight-byte integer
1020−int8, bigint :: TypeExpression ('Required ('Null 'PGint8))
1060+int8, bigint :: TypeExpression ('NoDef :=> 'Null 'PGint8)
10211061int8 = UnsafeTypeExpression "int8"
10221062bigint = UnsafeTypeExpression "bigint"
10231063-- | arbitrary precision numeric type
1024−numeric :: TypeExpression ('Required ('Null 'PGnumeric))
1064+numeric :: TypeExpression ('NoDef :=> 'Null 'PGnumeric)
10251065numeric = UnsafeTypeExpression "numeric"
10261066-- | single precision floating-point number (4 bytes)
1027−float4, real :: TypeExpression ('Required ('Null 'PGfloat4))
1067+float4, real :: TypeExpression ('NoDef :=> 'Null 'PGfloat4)
10281068float4 = UnsafeTypeExpression "float4"
10291069real = UnsafeTypeExpression "real"
10301070-- | double precision floating-point number (8 bytes)
1031−float8, doublePrecision :: TypeExpression ('Required ('Null 'PGfloat8))
1071+float8, doublePrecision :: TypeExpression ('NoDef :=> 'Null 'PGfloat8)
10321072float8 = UnsafeTypeExpression "float8"
10331073doublePrecision = UnsafeTypeExpression "double precision"
10341074-- | not a true type, but merely a notational convenience for creating
10351075-- unique identifier columns with type `'PGint2`
1036−serial2, smallserial :: TypeExpression ('Optional ('NotNull 'PGint2))
1076+serial2, smallserial
1077+ :: TypeExpression ('Def :=> 'NotNull 'PGint2)
10371078serial2 = UnsafeTypeExpression "serial2"
10381079smallserial = UnsafeTypeExpression "smallserial"
10391080-- | not a true type, but merely a notational convenience for creating
10401081-- unique identifier columns with type `'PGint4`
1041−serial4, serial :: TypeExpression ('Optional ('NotNull 'PGint4))
1082+serial4, serial
1083+ :: TypeExpression ('Def :=> 'NotNull 'PGint4)
10421084serial4 = UnsafeTypeExpression "serial4"
10431085serial = UnsafeTypeExpression "serial"
10441086-- | not a true type, but merely a notational convenience for creating
10451087-- unique identifier columns with type `'PGint8`
1046−serial8, bigserial :: TypeExpression ('Optional ('NotNull 'PGint8))
1088+serial8, bigserial
1089+ :: TypeExpression ('Def :=> 'NotNull 'PGint8)
10471090serial8 = UnsafeTypeExpression "serial8"
10481091bigserial = UnsafeTypeExpression "bigserial"
10491092-- | variable-length character string
1050−text :: TypeExpression ('Required ('Null 'PGtext))
1093+text :: TypeExpression ('NoDef :=> 'Null 'PGtext)
10511094text = UnsafeTypeExpression "text"
10521095-- | fixed-length character string
10531096char, character
10541097 :: (KnownNat n, 1 <= n)
10551098 => proxy n
1056− -> TypeExpression ('Required ('Null ('PGchar n)))
1099+ -> TypeExpression ('NoDef :=> 'Null ('PGchar n))
10571100char p = UnsafeTypeExpression $ "char(" <> renderNat p <> ")"
10581101character p = UnsafeTypeExpression $ "character(" <> renderNat p <> ")"
10591102-- | variable-length character string
10601103varchar, characterVarying
10611104 :: (KnownNat n, 1 <= n)
10621105 => proxy n
1063− -> TypeExpression ('Required ('Null ('PGvarchar n)))
1106+ -> TypeExpression ('NoDef :=> 'Null ('PGvarchar n))
10641107varchar p = UnsafeTypeExpression $ "varchar(" <> renderNat p <> ")"
10651108characterVarying p = UnsafeTypeExpression $
10661109 "character varying(" <> renderNat p <> ")"
10671110-- | binary data ("byte array")
1068−bytea :: TypeExpression ('Required ('Null 'PGbytea))
1111+bytea :: TypeExpression ('NoDef :=> 'Null 'PGbytea)
10691112bytea = UnsafeTypeExpression "bytea"
10701113-- | date and time (no time zone)
1071−timestamp :: TypeExpression ('Required ('Null 'PGtimestamp))
1114+timestamp :: TypeExpression ('NoDef :=> 'Null 'PGtimestamp)
10721115timestamp = UnsafeTypeExpression "timestamp"
10731116-- | date and time, including time zone
1074−timestampWithTimeZone :: TypeExpression ('Required ('Null 'PGtimestamptz))
1117+timestampWithTimeZone :: TypeExpression ('NoDef :=> 'Null 'PGtimestamptz)
10751118timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
10761119-- | calendar date (year, month, day)
1077−date :: TypeExpression ('Required ('Null 'PGdate))
1120+date :: TypeExpression ('NoDef :=> 'Null 'PGdate)
10781121date = UnsafeTypeExpression "date"
10791122-- | time of day (no time zone)
1080−time :: TypeExpression ('Required ('Null 'PGtime))
1123+time :: TypeExpression ('NoDef :=> 'Null 'PGtime)
10811124time = UnsafeTypeExpression "time"
10821125-- | time of day, including time zone
1083−timeWithTimeZone :: TypeExpression ('Required ('Null 'PGtimetz))
1126+timeWithTimeZone :: TypeExpression ('NoDef :=> 'Null 'PGtimetz)
10841127timeWithTimeZone = UnsafeTypeExpression "time with time zone"
10851128-- | time span
1086−interval :: TypeExpression ('Required ('Null 'PGinterval))
1129+interval :: TypeExpression ('NoDef :=> 'Null 'PGinterval)
10871130interval = UnsafeTypeExpression "interval"
10881131-- | universally unique identifier
1089−uuid :: TypeExpression ('Required ('Null 'PGuuid))
1132+uuid :: TypeExpression ('NoDef :=> 'Null 'PGuuid)
10901133uuid = UnsafeTypeExpression "uuid"
10911134-- | IPv4 or IPv6 host address
1092−inet :: TypeExpression ('Required ('Null 'PGinet))
1135+inet :: TypeExpression ('NoDef :=> 'Null 'PGinet)
10931136inet = UnsafeTypeExpression "inet"
10941137-- | textual JSON data
1095−json :: TypeExpression ('Required ('Null 'PGjson))
1138+json :: TypeExpression ('NoDef :=> 'Null 'PGjson)
10961139json = UnsafeTypeExpression "json"
10971140-- | binary JSON data, decomposed
1098−jsonb :: TypeExpression ('Required ('Null 'PGjsonb))
1141+jsonb :: TypeExpression ('NoDef :=> 'Null 'PGjsonb)
10991142jsonb = UnsafeTypeExpression "jsonb"
1143+-- | variable length array
1144+vararray
1145+ :: TypeExpression ('NoDef :=> 'Null pg)
1146+ -> TypeExpression ('NoDef :=> 'Null ('PGvararray pg))
1147+vararray ty = UnsafeTypeExpression $ renderTypeExpression ty <> "[]"
1148+-- | fixed length array
1149+--
1150+-- >>> renderTypeExpression (fixarray (Proxy @2) json)
1151+-- "json[2]"
1152+fixarray
1153+ :: KnownNat n
1154+ => proxy n
1155+ -> TypeExpression ('NoDef :=> 'Null pg)
1156+ -> TypeExpression ('NoDef :=> 'Null ('PGfixarray n pg))
1157+fixarray p ty = UnsafeTypeExpression $
1158+ renderTypeExpression ty <> "[" <> renderNat p <> "]"
11001159
11011160-- | used in `createTable` commands as a column constraint to ensure
11021161-- @NULL@ is not present
11031162notNull
1104− :: TypeExpression (optionality ('Null ty))
1105− -> TypeExpression (optionality ('NotNull ty))
1163+ :: TypeExpression (def :=> 'Null ty)
1164+ -> TypeExpression (def :=> 'NotNull ty)
11061165notNull ty = UnsafeTypeExpression $ renderTypeExpression ty <+> "NOT NULL"
11071166
11081167-- | used in `createTable` commands as a column constraint to give a default
11091168default_
1110− :: Expression '[] 'Ungrouped '[] ('Required ty)
1111− -> TypeExpression ('Required ty)
1112− -> TypeExpression ('Optional ty)
1169+ :: Expression '[] 'Ungrouped '[] ty
1170+ -> TypeExpression ('NoDef :=> ty)
1171+ -> TypeExpression ('Def :=> ty)
11131172default_ x ty = UnsafeTypeExpression $
11141173 renderTypeExpression ty <+> "DEFAULT" <+> renderExpression x
11151174
11161175-- | `pgtype` is a demoted version of a `PGType`
11171176class PGTyped (ty :: PGType) where
1118− pgtype :: TypeExpression ('Required ('Null ty))
1177+ pgtype :: TypeExpression ('NoDef :=> 'Null ty)
11191178instance PGTyped 'PGbool where pgtype = bool
11201179instance PGTyped 'PGint2 where pgtype = int2
11211180instance PGTyped 'PGint4 where pgtype = int4
@@ -1138,3 +1197,7 @@ instance PGTyped 'PGinterval where pgtype = interval
11381197instance PGTyped 'PGuuid where pgtype = uuid
11391198instance PGTyped 'PGjson where pgtype = json
11401199instance PGTyped 'PGjsonb where pgtype = jsonb
1200+instance PGTyped ty => PGTyped ('PGvararray ty) where
1201+ pgtype = vararray (pgtype @ty)
1202+instance (KnownNat n, PGTyped ty) => PGTyped ('PGfixarray n ty) where
1203+ pgtype = fixarray (Proxy @n) (pgtype @ty)