on dev help sign in
13 files changed+280−288
since splitsnapshots
unifiedsplit
README.md+6−6 squeal-postgresql/exe/Example.hs+2−2 squeal-postgresql/squeal-postgresql.cabal−1 squeal-postgresql/src/Squeal/PostgreSQL.hs−1 squeal-postgresql/src/Squeal/PostgreSQL/Binary.hs+124−124 squeal-postgresql/src/Squeal/PostgreSQL/Definition.hs+1 squeal-postgresql/src/Squeal/PostgreSQL/Definition/Table.hs+1−1 squeal-postgresql/src/Squeal/PostgreSQL/Definition/Table/Column.hs−105 squeal-postgresql/src/Squeal/PostgreSQL/Expression/Type.hs+95−4 squeal-postgresql/src/Squeal/PostgreSQL/Migration.hs−1 squeal-postgresql/src/Squeal/PostgreSQL/PQ.hs+16−16 squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+33−25 squeal-postgresql/test/Property.hs+2−2
README.md+6−6
@@ -121,7 +121,7 @@ type Schemas = Public Schema
121121
122122Notice the use of type operators.
123123
124−`:::` is used to pair an alias `GHC.TypeLits.Symbol` with a `SchemumType`,
124+`:::` is used to pair an alias `Symbol` with a `SchemumType`,
125125a `TableConstraint` or a `ColumnType`. It is intended to connote Haskell's `::`
126126operator.
127127
@@ -180,8 +180,8 @@ DROP TABLE "emails";
180180DROP TABLE "users";
181181```
182182
183−We'll need a Haskell type for @User@s. We give the type `Generics.SOP.Generic` and
184−`Generics.SOP.HasDatatypeInfo` instances so that we can encode and decode @User@s.
183+We'll need a Haskell type for `User`s. We give the type `SOP.Generic` and
184+`SOP.HasDatatypeInfo` instances so that we can encode and decode `User`s.
185185
186186```Haskell
187187>>> data User = User { userName :: Text, userEmail :: Maybe Text } deriving (Show, GHC.Generic)
@@ -189,12 +189,12 @@ We'll need a Haskell type for @User@s. We give the type `Generics.SOP.Generic` a
189189>>> instance SOP.HasDatatypeInfo User
190190```
191191
192−Next, we'll write `Manipulation_`s to insert @User@s into our two tables.
192+Next, we'll write `Manipulation_`s to insert `User`s into our two tables.
193193A `Manipulation_` like `insertInto`, `update` or `deleteFrom`
194194has three type parameters, the schemas it refers to, input parameters
195195and an output row. When
196−we insert into the users table, we will need a parameter for the @name@
197−field but not for the @id@ field. Since it's serial, we can use a default
196+we insert into the users table, we will need a parameter for the `name`
197+field but not for the `id` field. Since it's serial, we can use a default
198198value. However, since the emails table refers to the users table, we will
199199need to retrieve the user id that the insert generates and insert it into
200200the emails table. We can do this in a single `Manipulation_` by using a
squeal-postgresql/exe/Example.hs+2−2
@@ -53,8 +53,8 @@ setup =
5353 >>>
5454 createTable #emails
5555 ( serial `as` #id :*
56− (int & notNullable) `as` #user_id :*
57− (text & nullable) `as` #email )
56+ hask @Int32 `as` #user_id :*
57+ hask @(Maybe Text) `as` #email )
5858 ( primaryKey #id `as` #pk_emails :*
5959 foreignKey #user_id #users #id
6060 OnDeleteCascade OnUpdateCascade `as` #fk_user_id )
squeal-postgresql/squeal-postgresql.cabal−1
@@ -28,7 +28,6 @@ library
2828 Squeal.PostgreSQL.Definition.Function
2929 Squeal.PostgreSQL.Definition.Index
3030 Squeal.PostgreSQL.Definition.Table
31− Squeal.PostgreSQL.Definition.Table.Column
3231 Squeal.PostgreSQL.Definition.Table.Constraint
3332 Squeal.PostgreSQL.Definition.Type
3433 Squeal.PostgreSQL.Definition.Schema
squeal-postgresql/src/Squeal/PostgreSQL.hs−1
@@ -199,7 +199,6 @@ import Squeal.PostgreSQL.Definition.Function as X
199199import Squeal.PostgreSQL.Definition.Index as X
200200import Squeal.PostgreSQL.Definition.Schema as X
201201import Squeal.PostgreSQL.Definition.Table as X
202−import Squeal.PostgreSQL.Definition.Table.Column as X
203202import Squeal.PostgreSQL.Definition.Table.Constraint as X
204203import Squeal.PostgreSQL.Definition.Type as X
205204import Squeal.PostgreSQL.Definition.View as X
squeal-postgresql/src/Squeal/PostgreSQL/Binary.hs+124−124
@@ -216,9 +216,9 @@ module Squeal.PostgreSQL.Binary
216216 -- * Only
217217 , Only (..)
218218 -- * Oid
219− , HasOid (..)
220− , HasOidParam (..)
221− , HasAliasedOid (..)
219+ , OidOf (..)
220+ , OidOfParam (..)
221+ , OidOfField (..)
222222 ) where
223223
224224import BinaryParser
@@ -312,24 +312,24 @@ instance Aeson.ToJSON x => ToParam (Json x) 'PGjson where
312312instance Aeson.ToJSON x => ToParam (Jsonb x) 'PGjsonb where
313313 toParam = K . Encoding.jsonb_bytes
314314 . Lazy.ByteString.toStrict . Aeson.encode . getJsonb
315−instance (ToNullityParam x ty, ty ~ nullity pg, HasOid pg)
315+instance (ToNullityParam x ty, ty ~ nullity pg, OidOf pg)
316316 => ToParam (VarArray [x]) ('PGvararray ty) where
317317 toParam = K
318318 . Encoding.array_foldable
319319 (getOid (oidOf @pg)) (unK . toNullityParam @x @ty)
320320 . getVarArray
321−instance (ToParam x pg, HasOid pg)
321+instance (ToParam x pg, OidOf pg)
322322 => ToParam (VarArray (Vector x)) ('PGvararray ('NotNull pg)) where
323323 toParam = K
324324 . Encoding.array_vector (getOid (oidOf @pg)) (unK . toParam @x @pg)
325325 . getVarArray
326−instance (ToParam x pg, HasOid pg)
326+instance (ToParam x pg, OidOf pg)
327327 => ToParam (VarArray (Vector (Maybe x))) ('PGvararray ('Null pg)) where
328328 toParam = K
329329 . Encoding.nullableArray_vector
330330 (getOid (oidOf @pg)) (unK . toParam @x @pg)
331331 . getVarArray
332−instance (ToFixArray x dims ty, ty ~ nullity pg, HasOid pg)
332+instance (ToFixArray x dims ty, ty ~ nullity pg, OidOf pg)
333333 => ToParam (FixArray x) ('PGfixarray dims ty) where
334334 toParam = K . Encoding.array (getOid (oidOf @pg))
335335 . unK . unK . toFixArray @x @dims @ty . getFixArray
@@ -356,7 +356,7 @@ instance
356356 ( SListI fields
357357 , IsRecord x xs
358358 , AllZip ToField xs fields
359− , All HasAliasedOid fields
359+ , All OidOfField fields
360360 ) => ToParam (Composite x) ('PGcomposite fields) where
361361 toParam =
362362 let
@@ -364,7 +364,7 @@ instance
364364 encoders = htrans (Proxy @ToField) toField
365365
366366 composite
367− :: All HasAliasedOid row
367+ :: All OidOfField row
368368 => NP (K (Maybe Encoding.Encoding)) row
369369 -> K Encoding.Encoding ('PGcomposite row)
370370 composite fields = K $
@@ -381,18 +381,18 @@ instance
381381 int32BE (fromIntegral (lengthSList (Proxy @xs))) <>
382382 let
383383 each
384− :: HasAliasedOid field
384+ :: OidOfField field
385385 => K (Maybe Encoding.Encoding) field
386386 -> Encoding.Encoding
387387 each (K field :: K (Maybe Encoding.Encoding) field) =
388− word32BE (getOid (aliasedOid @field))
388+ word32BE (getOid (oidOfField @field))
389389 <> case field of
390390 Nothing -> int64BE (-1)
391391 Just value ->
392392 int32BE (fromIntegral (builderLength value))
393393 <> value
394394 in
395− hcfoldMap (Proxy @HasAliasedOid) each fields
395+ hcfoldMap (Proxy @OidOfField) each fields
396396
397397 in
398398 composite . encoders . toRecord . getComposite
@@ -402,118 +402,118 @@ instance
402402-- >>> :set -XTypeApplications
403403-- >>> oidOf @'PGbool
404404-- Oid 16
405−class HasOid (ty :: PGType) where oidOf :: LibPQ.Oid
406−instance HasOid 'PGbool where oidOf = LibPQ.Oid 16
407−instance HasOid ('PGfixarray ns (null 'PGbool)) where oidOf = LibPQ.Oid 1000
408−instance HasOid ('PGvararray (null 'PGbool)) where oidOf = LibPQ.Oid 1000
409−instance HasOid 'PGint2 where oidOf = LibPQ.Oid 21
410−instance HasOid ('PGfixarray ns (null 'PGint2)) where oidOf = LibPQ.Oid 1005
411−instance HasOid ('PGvararray (null 'PGint2)) where oidOf = LibPQ.Oid 1005
412−instance HasOid 'PGint4 where oidOf = LibPQ.Oid 23
413−instance HasOid ('PGfixarray ns (null 'PGint4)) where oidOf = LibPQ.Oid 1007
414−instance HasOid ('PGvararray (null 'PGint4)) where oidOf = LibPQ.Oid 1007
415−instance HasOid 'PGint8 where oidOf = LibPQ.Oid 20
416−instance HasOid ('PGfixarray ns (null 'PGint8)) where oidOf = LibPQ.Oid 1016
417−instance HasOid ('PGvararray (null 'PGint8)) where oidOf = LibPQ.Oid 1016
418−instance HasOid 'PGnumeric where oidOf = LibPQ.Oid 1700
419−instance HasOid ('PGfixarray ns (null 'PGnumeric)) where oidOf = LibPQ.Oid 1231
420−instance HasOid ('PGvararray (null 'PGnumeric)) where oidOf = LibPQ.Oid 1231
421−instance HasOid 'PGfloat4 where oidOf = LibPQ.Oid 700
422−instance HasOid ('PGfixarray ns (null 'PGfloat4)) where oidOf = LibPQ.Oid 1021
423−instance HasOid ('PGvararray (null 'PGfloat4)) where oidOf = LibPQ.Oid 1021
424−instance HasOid 'PGfloat8 where oidOf = LibPQ.Oid 701
425−instance HasOid ('PGfixarray ns (null 'PGfloat8)) where oidOf = LibPQ.Oid 1022
426−instance HasOid ('PGvararray (null 'PGfloat8)) where oidOf = LibPQ.Oid 1022
427−instance HasOid 'PGmoney where oidOf = LibPQ.Oid 790
428−instance HasOid ('PGfixarray ns (null 'PGmoney)) where oidOf = LibPQ.Oid 791
429−instance HasOid ('PGvararray (null 'PGmoney)) where oidOf = LibPQ.Oid 791
430−instance HasOid ('PGchar n) where oidOf = LibPQ.Oid 18
431−instance HasOid ('PGfixarray ns (null ('PGchar n))) where oidOf = LibPQ.Oid 1002
432−instance HasOid ('PGvararray (null ('PGchar n))) where oidOf = LibPQ.Oid 1002
433−instance HasOid ('PGvarchar n) where oidOf = LibPQ.Oid 1043
434−instance HasOid ('PGfixarray ns (null ('PGvarchar n))) where oidOf = LibPQ.Oid 1015
435−instance HasOid ('PGvararray (null ('PGvarchar n))) where oidOf = LibPQ.Oid 1015
436−instance HasOid 'PGtext where oidOf = LibPQ.Oid 25
437−instance HasOid ('PGfixarray ns (null 'PGtext)) where oidOf = LibPQ.Oid 1009
438−instance HasOid ('PGvararray (null 'PGtext)) where oidOf = LibPQ.Oid 1009
439−instance HasOid 'PGbytea where oidOf = LibPQ.Oid 17
440−instance HasOid ('PGfixarray ns (null 'PGbytea)) where oidOf = LibPQ.Oid 1001
441−instance HasOid ('PGvararray (null 'PGbytea)) where oidOf = LibPQ.Oid 1001
442−instance HasOid 'PGtimestamp where oidOf = LibPQ.Oid 1114
443−instance HasOid ('PGfixarray ns (null 'PGtimestamp)) where oidOf = LibPQ.Oid 1115
444−instance HasOid ('PGvararray (null 'PGtimestamp)) where oidOf = LibPQ.Oid 1115
445−instance HasOid 'PGtimestamptz where oidOf = LibPQ.Oid 1184
446−instance HasOid ('PGfixarray ns (null 'PGtimestamptz)) where oidOf = LibPQ.Oid 1185
447−instance HasOid ('PGvararray (null 'PGtimestamptz)) where oidOf = LibPQ.Oid 1185
448−instance HasOid 'PGdate where oidOf = LibPQ.Oid 1082
449−instance HasOid ('PGfixarray ns (null 'PGdate)) where oidOf = LibPQ.Oid 1182
450−instance HasOid ('PGvararray (null 'PGdate)) where oidOf = LibPQ.Oid 1182
451−instance HasOid 'PGtime where oidOf = LibPQ.Oid 1083
452−instance HasOid ('PGfixarray ns (null 'PGtime)) where oidOf = LibPQ.Oid 1183
453−instance HasOid ('PGvararray (null 'PGtime)) where oidOf = LibPQ.Oid 1183
454−instance HasOid 'PGtimetz where oidOf = LibPQ.Oid 1266
455−instance HasOid ('PGfixarray ns (null 'PGtimetz)) where oidOf = LibPQ.Oid 1270
456−instance HasOid ('PGvararray (null 'PGtimetz)) where oidOf = LibPQ.Oid 1270
457−instance HasOid 'PGinterval where oidOf = LibPQ.Oid 1186
458−instance HasOid ('PGfixarray ns (null 'PGinterval)) where oidOf = LibPQ.Oid 1187
459−instance HasOid ('PGvararray (null 'PGinterval)) where oidOf = LibPQ.Oid 1187
460−instance HasOid 'PGuuid where oidOf = LibPQ.Oid 2950
461−instance HasOid ('PGfixarray ns (null 'PGuuid)) where oidOf = LibPQ.Oid 2951
462−instance HasOid ('PGvararray (null 'PGuuid)) where oidOf = LibPQ.Oid 2951
463−instance HasOid 'PGinet where oidOf = LibPQ.Oid 869
464−instance HasOid ('PGfixarray ns (null 'PGinet)) where oidOf = LibPQ.Oid 1041
465−instance HasOid ('PGvararray (null 'PGinet)) where oidOf = LibPQ.Oid 1041
466−instance HasOid 'PGjson where oidOf = LibPQ.Oid 114
467−instance HasOid ('PGfixarray ns (null 'PGjson)) where oidOf = LibPQ.Oid 199
468−instance HasOid ('PGvararray (null 'PGjson)) where oidOf = LibPQ.Oid 199
469−instance HasOid 'PGjsonb where oidOf = LibPQ.Oid 3802
470−instance HasOid ('PGfixarray ns (null 'PGjsonb)) where oidOf = LibPQ.Oid 3807
471−instance HasOid ('PGvararray (null 'PGjsonb)) where oidOf = LibPQ.Oid 3807
472−instance HasOid 'PGtsvector where oidOf = LibPQ.Oid 3614
473−instance HasOid ('PGfixarray ns (null 'PGtsvector)) where oidOf = LibPQ.Oid 3643
474−instance HasOid ('PGvararray (null 'PGtsvector)) where oidOf = LibPQ.Oid 3643
475−instance HasOid 'PGtsquery where oidOf = LibPQ.Oid 3615
476−instance HasOid ('PGfixarray ns (null 'PGtsquery)) where oidOf = LibPQ.Oid 3645
477−instance HasOid ('PGvararray (null 'PGtsquery)) where oidOf = LibPQ.Oid 3645
478−instance HasOid 'PGoid where oidOf = LibPQ.Oid 26
479−instance HasOid ('PGfixarray ns (null 'PGoid)) where oidOf = LibPQ.Oid 1028
480−instance HasOid ('PGvararray (null 'PGoid)) where oidOf = LibPQ.Oid 1028
481−instance HasOid ('PGrange 'PGint4) where oidOf = LibPQ.Oid 3904
482−instance HasOid ('PGfixarray ns (null ('PGrange 'PGint4))) where oidOf = LibPQ.Oid 3905
483−instance HasOid ('PGvararray (null ('PGrange 'PGint4))) where oidOf = LibPQ.Oid 3905
484−instance HasOid ('PGrange 'PGint8) where oidOf = LibPQ.Oid 3926
485−instance HasOid ('PGfixarray ns (null ('PGrange 'PGint8))) where oidOf = LibPQ.Oid 3927
486−instance HasOid ('PGvararray (null ('PGrange 'PGint8))) where oidOf = LibPQ.Oid 3927
487−instance HasOid ('PGrange 'PGnumeric) where oidOf = LibPQ.Oid 3906
488−instance HasOid ('PGfixarray ns (null ('PGrange 'PGnumeric))) where oidOf = LibPQ.Oid 3907
489−instance HasOid ('PGvararray (null ('PGrange 'PGnumeric))) where oidOf = LibPQ.Oid 3907
490−instance HasOid ('PGrange 'PGtimestamp) where oidOf = LibPQ.Oid 3908
491−instance HasOid ('PGfixarray ns (null ('PGrange 'PGtimestamp))) where oidOf = LibPQ.Oid 3909
492−instance HasOid ('PGvararray (null ('PGrange 'PGtimestamp))) where oidOf = LibPQ.Oid 3909
493−instance HasOid ('PGrange 'PGtimestamptz) where oidOf = LibPQ.Oid 3910
494−instance HasOid ('PGfixarray ns (null ('PGrange 'PGtimestamptz))) where oidOf = LibPQ.Oid 3911
495−instance HasOid ('PGvararray (null ('PGrange 'PGtimestamptz))) where oidOf = LibPQ.Oid 3911
496−instance HasOid ('PGrange 'PGdate) where oidOf = LibPQ.Oid 3912
497−instance HasOid ('PGfixarray ns (null ('PGrange 'PGdate))) where oidOf = LibPQ.Oid 3913
498−instance HasOid ('PGvararray (null ('PGrange 'PGdate))) where oidOf = LibPQ.Oid 3913
499−instance {-# OVERLAPPABLE #-} HasOid ('PGrange ty) where oidOf = LibPQ.invalidOid
500−instance {-# OVERLAPPABLE #-} HasOid ('PGfixarray ns (null ('PGrange ty))) where oidOf = LibPQ.invalidOid
501−instance {-# OVERLAPPABLE #-} HasOid ('PGvararray (null ('PGrange ty))) where oidOf = LibPQ.invalidOid
502−instance {-# OVERLAPPABLE #-} HasOid ('PGcomposite row) where oidOf = LibPQ.invalidOid
503−instance {-# OVERLAPPABLE #-} HasOid ('PGfixarray ns (null ('PGcomposite row))) where oidOf = LibPQ.invalidOid
504−instance {-# OVERLAPPABLE #-} HasOid ('PGvararray (null ('PGcomposite row))) where oidOf = LibPQ.invalidOid
505−instance {-# OVERLAPPABLE #-} HasOid ('PGenum labels) where oidOf = LibPQ.invalidOid
506−instance {-# OVERLAPPABLE #-} HasOid ('PGfixarray ns (null ('PGenum labels))) where oidOf = LibPQ.invalidOid
507−instance {-# OVERLAPPABLE #-} HasOid ('PGvararray (null ('PGenum labels))) where oidOf = LibPQ.invalidOid
508−
509−class HasOidParam (ty :: NullityType) where oidOfParam :: Oid
510−instance HasOid ty => HasOidParam (null ty) where oidOfParam = oidOf @ty
511−
512−-- | Lifts a `HasOid` constraint to a field.
513−class HasAliasedOid (field :: (Symbol, NullityType)) where
514− aliasedOid :: Oid
515−instance HasOid ty => HasAliasedOid (alias ::: nullity ty) where
516− aliasedOid = oidOf @ty
405+class OidOf (ty :: PGType) where oidOf :: LibPQ.Oid
406+instance OidOf 'PGbool where oidOf = LibPQ.Oid 16
407+instance OidOf ('PGfixarray ns (null 'PGbool)) where oidOf = LibPQ.Oid 1000
408+instance OidOf ('PGvararray (null 'PGbool)) where oidOf = LibPQ.Oid 1000
409+instance OidOf 'PGint2 where oidOf = LibPQ.Oid 21
410+instance OidOf ('PGfixarray ns (null 'PGint2)) where oidOf = LibPQ.Oid 1005
411+instance OidOf ('PGvararray (null 'PGint2)) where oidOf = LibPQ.Oid 1005
412+instance OidOf 'PGint4 where oidOf = LibPQ.Oid 23
413+instance OidOf ('PGfixarray ns (null 'PGint4)) where oidOf = LibPQ.Oid 1007
414+instance OidOf ('PGvararray (null 'PGint4)) where oidOf = LibPQ.Oid 1007
415+instance OidOf 'PGint8 where oidOf = LibPQ.Oid 20
416+instance OidOf ('PGfixarray ns (null 'PGint8)) where oidOf = LibPQ.Oid 1016
417+instance OidOf ('PGvararray (null 'PGint8)) where oidOf = LibPQ.Oid 1016
418+instance OidOf 'PGnumeric where oidOf = LibPQ.Oid 1700
419+instance OidOf ('PGfixarray ns (null 'PGnumeric)) where oidOf = LibPQ.Oid 1231
420+instance OidOf ('PGvararray (null 'PGnumeric)) where oidOf = LibPQ.Oid 1231
421+instance OidOf 'PGfloat4 where oidOf = LibPQ.Oid 700
422+instance OidOf ('PGfixarray ns (null 'PGfloat4)) where oidOf = LibPQ.Oid 1021
423+instance OidOf ('PGvararray (null 'PGfloat4)) where oidOf = LibPQ.Oid 1021
424+instance OidOf 'PGfloat8 where oidOf = LibPQ.Oid 701
425+instance OidOf ('PGfixarray ns (null 'PGfloat8)) where oidOf = LibPQ.Oid 1022
426+instance OidOf ('PGvararray (null 'PGfloat8)) where oidOf = LibPQ.Oid 1022
427+instance OidOf 'PGmoney where oidOf = LibPQ.Oid 790
428+instance OidOf ('PGfixarray ns (null 'PGmoney)) where oidOf = LibPQ.Oid 791
429+instance OidOf ('PGvararray (null 'PGmoney)) where oidOf = LibPQ.Oid 791
430+instance OidOf ('PGchar n) where oidOf = LibPQ.Oid 18
431+instance OidOf ('PGfixarray ns (null ('PGchar n))) where oidOf = LibPQ.Oid 1002
432+instance OidOf ('PGvararray (null ('PGchar n))) where oidOf = LibPQ.Oid 1002
433+instance OidOf ('PGvarchar n) where oidOf = LibPQ.Oid 1043
434+instance OidOf ('PGfixarray ns (null ('PGvarchar n))) where oidOf = LibPQ.Oid 1015
435+instance OidOf ('PGvararray (null ('PGvarchar n))) where oidOf = LibPQ.Oid 1015
436+instance OidOf 'PGtext where oidOf = LibPQ.Oid 25
437+instance OidOf ('PGfixarray ns (null 'PGtext)) where oidOf = LibPQ.Oid 1009
438+instance OidOf ('PGvararray (null 'PGtext)) where oidOf = LibPQ.Oid 1009
439+instance OidOf 'PGbytea where oidOf = LibPQ.Oid 17
440+instance OidOf ('PGfixarray ns (null 'PGbytea)) where oidOf = LibPQ.Oid 1001
441+instance OidOf ('PGvararray (null 'PGbytea)) where oidOf = LibPQ.Oid 1001
442+instance OidOf 'PGtimestamp where oidOf = LibPQ.Oid 1114
443+instance OidOf ('PGfixarray ns (null 'PGtimestamp)) where oidOf = LibPQ.Oid 1115
444+instance OidOf ('PGvararray (null 'PGtimestamp)) where oidOf = LibPQ.Oid 1115
445+instance OidOf 'PGtimestamptz where oidOf = LibPQ.Oid 1184
446+instance OidOf ('PGfixarray ns (null 'PGtimestamptz)) where oidOf = LibPQ.Oid 1185
447+instance OidOf ('PGvararray (null 'PGtimestamptz)) where oidOf = LibPQ.Oid 1185
448+instance OidOf 'PGdate where oidOf = LibPQ.Oid 1082
449+instance OidOf ('PGfixarray ns (null 'PGdate)) where oidOf = LibPQ.Oid 1182
450+instance OidOf ('PGvararray (null 'PGdate)) where oidOf = LibPQ.Oid 1182
451+instance OidOf 'PGtime where oidOf = LibPQ.Oid 1083
452+instance OidOf ('PGfixarray ns (null 'PGtime)) where oidOf = LibPQ.Oid 1183
453+instance OidOf ('PGvararray (null 'PGtime)) where oidOf = LibPQ.Oid 1183
454+instance OidOf 'PGtimetz where oidOf = LibPQ.Oid 1266
455+instance OidOf ('PGfixarray ns (null 'PGtimetz)) where oidOf = LibPQ.Oid 1270
456+instance OidOf ('PGvararray (null 'PGtimetz)) where oidOf = LibPQ.Oid 1270
457+instance OidOf 'PGinterval where oidOf = LibPQ.Oid 1186
458+instance OidOf ('PGfixarray ns (null 'PGinterval)) where oidOf = LibPQ.Oid 1187
459+instance OidOf ('PGvararray (null 'PGinterval)) where oidOf = LibPQ.Oid 1187
460+instance OidOf 'PGuuid where oidOf = LibPQ.Oid 2950
461+instance OidOf ('PGfixarray ns (null 'PGuuid)) where oidOf = LibPQ.Oid 2951
462+instance OidOf ('PGvararray (null 'PGuuid)) where oidOf = LibPQ.Oid 2951
463+instance OidOf 'PGinet where oidOf = LibPQ.Oid 869
464+instance OidOf ('PGfixarray ns (null 'PGinet)) where oidOf = LibPQ.Oid 1041
465+instance OidOf ('PGvararray (null 'PGinet)) where oidOf = LibPQ.Oid 1041
466+instance OidOf 'PGjson where oidOf = LibPQ.Oid 114
467+instance OidOf ('PGfixarray ns (null 'PGjson)) where oidOf = LibPQ.Oid 199
468+instance OidOf ('PGvararray (null 'PGjson)) where oidOf = LibPQ.Oid 199
469+instance OidOf 'PGjsonb where oidOf = LibPQ.Oid 3802
470+instance OidOf ('PGfixarray ns (null 'PGjsonb)) where oidOf = LibPQ.Oid 3807
471+instance OidOf ('PGvararray (null 'PGjsonb)) where oidOf = LibPQ.Oid 3807
472+instance OidOf 'PGtsvector where oidOf = LibPQ.Oid 3614
473+instance OidOf ('PGfixarray ns (null 'PGtsvector)) where oidOf = LibPQ.Oid 3643
474+instance OidOf ('PGvararray (null 'PGtsvector)) where oidOf = LibPQ.Oid 3643
475+instance OidOf 'PGtsquery where oidOf = LibPQ.Oid 3615
476+instance OidOf ('PGfixarray ns (null 'PGtsquery)) where oidOf = LibPQ.Oid 3645
477+instance OidOf ('PGvararray (null 'PGtsquery)) where oidOf = LibPQ.Oid 3645
478+instance OidOf 'PGoid where oidOf = LibPQ.Oid 26
479+instance OidOf ('PGfixarray ns (null 'PGoid)) where oidOf = LibPQ.Oid 1028
480+instance OidOf ('PGvararray (null 'PGoid)) where oidOf = LibPQ.Oid 1028
481+instance OidOf ('PGrange 'PGint4) where oidOf = LibPQ.Oid 3904
482+instance OidOf ('PGfixarray ns (null ('PGrange 'PGint4))) where oidOf = LibPQ.Oid 3905
483+instance OidOf ('PGvararray (null ('PGrange 'PGint4))) where oidOf = LibPQ.Oid 3905
484+instance OidOf ('PGrange 'PGint8) where oidOf = LibPQ.Oid 3926
485+instance OidOf ('PGfixarray ns (null ('PGrange 'PGint8))) where oidOf = LibPQ.Oid 3927
486+instance OidOf ('PGvararray (null ('PGrange 'PGint8))) where oidOf = LibPQ.Oid 3927
487+instance OidOf ('PGrange 'PGnumeric) where oidOf = LibPQ.Oid 3906
488+instance OidOf ('PGfixarray ns (null ('PGrange 'PGnumeric))) where oidOf = LibPQ.Oid 3907
489+instance OidOf ('PGvararray (null ('PGrange 'PGnumeric))) where oidOf = LibPQ.Oid 3907
490+instance OidOf ('PGrange 'PGtimestamp) where oidOf = LibPQ.Oid 3908
491+instance OidOf ('PGfixarray ns (null ('PGrange 'PGtimestamp))) where oidOf = LibPQ.Oid 3909
492+instance OidOf ('PGvararray (null ('PGrange 'PGtimestamp))) where oidOf = LibPQ.Oid 3909
493+instance OidOf ('PGrange 'PGtimestamptz) where oidOf = LibPQ.Oid 3910
494+instance OidOf ('PGfixarray ns (null ('PGrange 'PGtimestamptz))) where oidOf = LibPQ.Oid 3911
495+instance OidOf ('PGvararray (null ('PGrange 'PGtimestamptz))) where oidOf = LibPQ.Oid 3911
496+instance OidOf ('PGrange 'PGdate) where oidOf = LibPQ.Oid 3912
497+instance OidOf ('PGfixarray ns (null ('PGrange 'PGdate))) where oidOf = LibPQ.Oid 3913
498+instance OidOf ('PGvararray (null ('PGrange 'PGdate))) where oidOf = LibPQ.Oid 3913
499+instance {-# OVERLAPPABLE #-} OidOf ('PGrange ty) where oidOf = LibPQ.invalidOid
500+instance {-# OVERLAPPABLE #-} OidOf ('PGfixarray ns (null ('PGrange ty))) where oidOf = LibPQ.invalidOid
501+instance {-# OVERLAPPABLE #-} OidOf ('PGvararray (null ('PGrange ty))) where oidOf = LibPQ.invalidOid
502+instance {-# OVERLAPPABLE #-} OidOf ('PGcomposite row) where oidOf = LibPQ.invalidOid
503+instance {-# OVERLAPPABLE #-} OidOf ('PGfixarray ns (null ('PGcomposite row))) where oidOf = LibPQ.invalidOid
504+instance {-# OVERLAPPABLE #-} OidOf ('PGvararray (null ('PGcomposite row))) where oidOf = LibPQ.invalidOid
505+instance {-# OVERLAPPABLE #-} OidOf ('PGenum labels) where oidOf = LibPQ.invalidOid
506+instance {-# OVERLAPPABLE #-} OidOf ('PGfixarray ns (null ('PGenum labels))) where oidOf = LibPQ.invalidOid
507+instance {-# OVERLAPPABLE #-} OidOf ('PGvararray (null ('PGenum labels))) where oidOf = LibPQ.invalidOid
508+
509+class OidOfParam (ty :: NullityType) where oidOfParam :: Oid
510+instance OidOf ty => OidOfParam (null ty) where oidOfParam = oidOf @ty
511+
512+-- | Lifts a `OidOf` constraint to a field.
513+class OidOfField (field :: (Symbol, NullityType)) where
514+ oidOfField :: Oid
515+instance OidOf ty => OidOfField (alias ::: nullity ty) where
516+ oidOfField = oidOf @ty
517517
518518-- | A `ToNullityParam` constraint gives an encoding of a Haskell `Type` into
519519-- into the binary format of a PostgreSQL `NullityType`.
squeal-postgresql/src/Squeal/PostgreSQL/Definition.hs+1
@@ -27,6 +27,7 @@ Squeal data definition language.
2727 , TypeInType
2828 , TypeOperators
2929 , UndecidableSuperClasses
30+ , UndecidableInstances
3031#-}
3132
3233module Squeal.PostgreSQL.Definition
squeal-postgresql/src/Squeal/PostgreSQL/Definition/Table.hs+1−1
@@ -62,9 +62,9 @@ import qualified GHC.Generics as GHC
6262
6363import Squeal.PostgreSQL.Alias
6464import Squeal.PostgreSQL.Definition
65−import Squeal.PostgreSQL.Definition.Table.Column
6665import Squeal.PostgreSQL.Definition.Table.Constraint
6766import Squeal.PostgreSQL.Expression
67+import Squeal.PostgreSQL.Expression.Type
6868import Squeal.PostgreSQL.List
6969import Squeal.PostgreSQL.Render
7070import Squeal.PostgreSQL.Schema
squeal-postgresql/src/Squeal/PostgreSQL/Definition/Table/Column.hsdeleted−105
@@ -1,105 +0,0 @@
1−{-|
2−Module: Squeal.PostgreSQL.Definition.Table.Column
3−Description: Column type expressions
4−Copyright: (c) Eitan Chatav, 2017
5−Maintainer: eitan@morphism.tech
6−Stability: experimental
7−
8−Column type expressions.
9−-}
10−
11−{-# LANGUAGE
12− AllowAmbiguousTypes
13− , ConstraintKinds
14− , DeriveAnyClass
15− , DeriveGeneric
16− , DerivingStrategies
17− , FlexibleContexts
18− , FlexibleInstances
19− , GADTs
20− , LambdaCase
21− , MultiParamTypeClasses
22− , OverloadedLabels
23− , OverloadedStrings
24− , RankNTypes
25− , ScopedTypeVariables
26− , TypeApplications
27− , TypeInType
28− , TypeOperators
29− , UndecidableSuperClasses
30−#-}
31−
32−module Squeal.PostgreSQL.Definition.Table.Column
33− ( ColumnTypeExpression (..)
34− , nullable
35− , notNullable
36− , default_
37− , serial2
38− , smallserial
39− , serial4
40− , serial
41− , serial8
42− , bigserial
43− ) where
44−
45−import Control.DeepSeq
46−import Data.ByteString
47−
48−import qualified GHC.Generics as GHC
49−
50−import Squeal.PostgreSQL.Alias
51−import Squeal.PostgreSQL.Expression
52−import Squeal.PostgreSQL.Expression.Type
53−import Squeal.PostgreSQL.Render
54−import Squeal.PostgreSQL.Schema
55−
56−-- $setup
57−-- >>> import Squeal.PostgreSQL
58−
59−-- | `ColumnTypeExpression`s are used in `createTable` commands.
60−newtype ColumnTypeExpression (schemas :: SchemasType) (ty :: ColumnType)
61− = UnsafeColumnTypeExpression { renderColumnTypeExpression :: ByteString }
62− deriving (GHC.Generic,Show,Eq,Ord,NFData)
63−instance RenderSQL (ColumnTypeExpression schemas ty) where
64− renderSQL = renderColumnTypeExpression
65−
66−-- | used in `createTable` commands as a column constraint to note that
67−-- @NULL@ may be present in a column
68−nullable
69− :: TypeExpression schemas (nullity ty)
70− -> ColumnTypeExpression schemas ('NoDef :=> 'Null ty)
71−nullable ty = UnsafeColumnTypeExpression $ renderSQL ty <+> "NULL"
72−
73−-- | used in `createTable` commands as a column constraint to ensure
74−-- @NULL@ is not present in a column
75−notNullable
76− :: TypeExpression schemas (nullity ty)
77− -> ColumnTypeExpression schemas ('NoDef :=> 'NotNull ty)
78−notNullable ty = UnsafeColumnTypeExpression $ renderSQL ty <+> "NOT NULL"
79−
80−-- | used in `createTable` commands as a column constraint to give a default
81−default_
82− :: Expression '[] '[] 'Ungrouped schemas '[] '[] ty
83− -> ColumnTypeExpression schemas ('NoDef :=> ty)
84− -> ColumnTypeExpression schemas ('Def :=> ty)
85−default_ x ty = UnsafeColumnTypeExpression $
86− renderSQL ty <+> "DEFAULT" <+> renderExpression x
87−
88−-- | not a true type, but merely a notational convenience for creating
89−-- unique identifier columns with type `PGint2`
90−serial2, smallserial
91− :: ColumnTypeExpression schemas ('Def :=> 'NotNull 'PGint2)
92−serial2 = UnsafeColumnTypeExpression "serial2"
93−smallserial = UnsafeColumnTypeExpression "smallserial"
94−-- | not a true type, but merely a notational convenience for creating
95−-- unique identifier columns with type `PGint4`
96−serial4, serial
97− :: ColumnTypeExpression schemas ('Def :=> 'NotNull 'PGint4)
98−serial4 = UnsafeColumnTypeExpression "serial4"
99−serial = UnsafeColumnTypeExpression "serial"
100−-- | not a true type, but merely a notational convenience for creating
101−-- unique identifier columns with type `PGint8`
102−serial8, bigserial
103− :: ColumnTypeExpression schemas ('Def :=> 'NotNull 'PGint8)
104−serial8 = UnsafeColumnTypeExpression "serial8"
105−bigserial = UnsafeColumnTypeExpression "bigserial"
squeal-postgresql/src/Squeal/PostgreSQL/Expression/Type.hs+95−4
@@ -23,15 +23,16 @@ Type expressions.
2323 , ScopedTypeVariables
2424 , TypeApplications
2525 , TypeOperators
26+ , UndecidableInstances
2627#-}
2728
2829module Squeal.PostgreSQL.Expression.Type
29− ( TypeExpression (..)
30− , cast
30+ ( -- * type casting
31+ cast
3132 , astype
3233 , inferredtype
33− , PGTyped (..)
34− , FieldTyped (..)
34+ -- * type expressions
35+ , TypeExpression (..)
3536 , typedef
3637 , typetable
3738 , typeview
@@ -78,6 +79,22 @@ module Squeal.PostgreSQL.Expression.Type
7879 , tsrange
7980 , tstzrange
8081 , daterange
82+ -- * column type definitions
83+ , ColumnTypeExpression (..)
84+ , nullable
85+ , notNullable
86+ , default_
87+ , serial2
88+ , smallserial
89+ , serial4
90+ , serial
91+ , serial8
92+ , bigserial
93+ , hask
94+ -- * type inference
95+ , PGTyped (..)
96+ , PGNullityTyped (..)
97+ , FieldTyped (..)
8198 ) where
8299
83100import Control.DeepSeq
@@ -91,6 +108,7 @@ import qualified Generics.SOP as SOP
91108
92109import Squeal.PostgreSQL.Alias
93110import Squeal.PostgreSQL.Expression
111+import Squeal.PostgreSQL.PG
94112import Squeal.PostgreSQL.Render
95113import Squeal.PostgreSQL.Schema
96114
@@ -132,6 +150,7 @@ astype = cast
132150inferredtype
133151 :: PGTyped schemas ty
134152 => Expression outer common grp schemas params from ty
153+ -- ^ value
135154 -> Expression outer common grp schemas params from ty
136155inferredtype = astype pgtype
137156
@@ -151,6 +170,7 @@ instance RenderSQL (TypeExpression schemas ty) where
151170typedef
152171 :: (Has sch schemas schema, Has td schema ('Typedef ty))
153172 => QualifiedAlias sch td
173+ -- ^ type alias
154174 -> TypeExpression schemas (null ty)
155175typedef = UnsafeTypeExpression . renderSQL
156176
@@ -159,6 +179,7 @@ typedef = UnsafeTypeExpression . renderSQL
159179typetable
160180 :: (Has sch schemas schema, Has tab schema ('Table table))
161181 => QualifiedAlias sch tab
182+ -- ^ table alias
162183 -> TypeExpression schemas (null ('PGcomposite (TableToRow table)))
163184typetable = UnsafeTypeExpression . renderSQL
164185
@@ -167,6 +188,7 @@ typetable = UnsafeTypeExpression . renderSQL
167188typeview
168189 :: (Has sch schemas schema, Has vw schema ('View view))
169190 => QualifiedAlias sch vw
191+ -- ^ view alias
170192 -> TypeExpression schemas (null ('PGcomposite view))
171193typeview = UnsafeTypeExpression . renderSQL
172194
@@ -353,3 +375,72 @@ class FieldTyped schemas ty where
353375instance (KnownSymbol alias, PGTyped schemas ty)
354376 => FieldTyped schemas (alias ::: ty) where
355377 fieldtype = pgtype `As` Alias
378+
379+-- | `ColumnTypeExpression`s are used in `createTable` commands.
380+newtype ColumnTypeExpression (schemas :: SchemasType) (ty :: ColumnType)
381+ = UnsafeColumnTypeExpression { renderColumnTypeExpression :: ByteString }
382+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
383+instance RenderSQL (ColumnTypeExpression schemas ty) where
384+ renderSQL = renderColumnTypeExpression
385+
386+-- | used in `createTable` commands as a column constraint to note that
387+-- @NULL@ may be present in a column
388+nullable
389+ :: TypeExpression schemas (nullity ty)
390+ -> ColumnTypeExpression schemas ('NoDef :=> 'Null ty)
391+nullable ty = UnsafeColumnTypeExpression $ renderSQL ty <+> "NULL"
392+
393+-- | used in `createTable` commands as a column constraint to ensure
394+-- @NULL@ is not present in a column
395+notNullable
396+ :: TypeExpression schemas (nullity ty)
397+ -> ColumnTypeExpression schemas ('NoDef :=> 'NotNull ty)
398+notNullable ty = UnsafeColumnTypeExpression $ renderSQL ty <+> "NOT NULL"
399+
400+-- | used in `createTable` commands as a column constraint to give a default
401+default_
402+ :: Expression '[] '[] 'Ungrouped schemas '[] '[] ty
403+ -> ColumnTypeExpression schemas ('NoDef :=> ty)
404+ -> ColumnTypeExpression schemas ('Def :=> ty)
405+default_ x ty = UnsafeColumnTypeExpression $
406+ renderSQL ty <+> "DEFAULT" <+> renderExpression x
407+
408+-- | not a true type, but merely a notational convenience for creating
409+-- unique identifier columns with type `PGint2`
410+serial2, smallserial
411+ :: ColumnTypeExpression schemas ('Def :=> 'NotNull 'PGint2)
412+serial2 = UnsafeColumnTypeExpression "serial2"
413+smallserial = UnsafeColumnTypeExpression "smallserial"
414+-- | not a true type, but merely a notational convenience for creating
415+-- unique identifier columns with type `PGint4`
416+serial4, serial
417+ :: ColumnTypeExpression schemas ('Def :=> 'NotNull 'PGint4)
418+serial4 = UnsafeColumnTypeExpression "serial4"
419+serial = UnsafeColumnTypeExpression "serial"
420+-- | not a true type, but merely a notational convenience for creating
421+-- unique identifier columns with type `PGint8`
422+serial8, bigserial
423+ :: ColumnTypeExpression schemas ('Def :=> 'NotNull 'PGint8)
424+serial8 = UnsafeColumnTypeExpression "serial8"
425+bigserial = UnsafeColumnTypeExpression "bigserial"
426+
427+-- | Like @PGTyped@ but also accounts for nullity.
428+class PGNullityTyped schemas (nullty :: NullityType) where
429+ pgNullityType :: ColumnTypeExpression schemas ('NoDef :=> nullty)
430+
431+instance PGTyped schemas ('Null ty) => PGNullityTyped schemas ('Null ty) where
432+ pgNullityType = nullable (pgtype @_ @('Null ty))
433+
434+instance PGTyped schemas ('NotNull ty) => PGNullityTyped schemas ('NotNull ty) where
435+ pgNullityType = notNullable (pgtype @_ @('NotNull ty))
436+
437+-- | Allow you to specify pg column types in relation to haskell types.
438+-- >>> printSQL $ hask @(Maybe String)
439+-- text NULL
440+--
441+-- >>> printSQL $ hask @Double
442+-- float8 NOT NULL
443+hask
444+ :: forall hask schemas. PGNullityTyped schemas (NullPG hask)
445+ => ColumnTypeExpression schemas ('NoDef :=> NullPG hask)
446+hask = pgNullityType
squeal-postgresql/src/Squeal/PostgreSQL/Migration.hs−1
@@ -168,7 +168,6 @@ import Squeal.PostgreSQL.Alias
168168import Squeal.PostgreSQL.Binary
169169import Squeal.PostgreSQL.Definition
170170import Squeal.PostgreSQL.Definition.Table
171−import Squeal.PostgreSQL.Definition.Table.Column
172171import Squeal.PostgreSQL.Definition.Table.Constraint
173172import Squeal.PostgreSQL.Expression.Comparison
174173import Squeal.PostgreSQL.Expression.Parameter
squeal-postgresql/src/Squeal/PostgreSQL/PQ.hs+16−16
@@ -317,13 +317,13 @@ a default instance.
317317-}
318318class Monad pq => MonadPQ schemas pq | pq -> schemas where
319319 manipulateParams
320− :: (ToParams x params, All HasOidParam params)
320+ :: (ToParams x params, All OidOfParam params)
321321 => Manipulation '[] schemas params ys
322322 -- ^ `insertInto`, `update` or `deleteFrom`
323323 -> x -> pq (K LibPQ.Result ys)
324324 default manipulateParams
325325 :: (MonadTrans t, MonadPQ schemas pq1, pq ~ t pq1)
326− => (ToParams x params, All HasOidParam params)
326+ => (ToParams x params, All OidOfParam params)
327327 => Manipulation '[] schemas params ys
328328 -- ^ `insertInto`, `update` or `deleteFrom`
329329 -> x -> pq (K LibPQ.Result ys)
@@ -331,7 +331,7 @@ class Monad pq => MonadPQ schemas pq | pq -> schemas where
331331 manipulateParams manipulation params
332332
333333 manipulateParams_
334− :: (ToParams x params, All HasOidParam params)
334+ :: (ToParams x params, All OidOfParam params)
335335 => Manipulation '[] schemas params '[]
336336 -- ^ `insertInto`, `update` or `deleteFrom`
337337 -> x -> pq ()
@@ -344,7 +344,7 @@ class Monad pq => MonadPQ schemas pq | pq -> schemas where
344344 manipulate_ = void . manipulate
345345
346346 runQueryParams
347− :: (ToParams x params, All HasOidParam params)
347+ :: (ToParams x params, All OidOfParam params)
348348 => Query '[] '[] schemas params ys
349349 -- ^ `select` and friends
350350 -> x -> pq (K LibPQ.Result ys)
@@ -357,19 +357,19 @@ class Monad pq => MonadPQ schemas pq | pq -> schemas where
357357 runQuery q = runQueryParams q ()
358358
359359 traversePrepared
360− :: (ToParams x params, Traversable list, All HasOidParam params)
360+ :: (ToParams x params, Traversable list, All OidOfParam params)
361361 => Manipulation '[] schemas params ys
362362 -- ^ `insertInto`, `update`, or `deleteFrom`, and friends
363363 -> list x -> pq (list (K LibPQ.Result ys))
364364 default traversePrepared
365365 :: (MonadTrans t, MonadPQ schemas pq1, pq ~ t pq1)
366− => (ToParams x params, Traversable list, All HasOidParam params)
366+ => (ToParams x params, Traversable list, All OidOfParam params)
367367 => Manipulation '[] schemas params ys -> list x -> pq (list (K LibPQ.Result ys))
368368 traversePrepared manipulation params = lift $
369369 traversePrepared manipulation params
370370
371371 forPrepared
372− :: (ToParams x params, Traversable list, All HasOidParam params)
372+ :: (ToParams x params, Traversable list, All OidOfParam params)
373373 => list x
374374 -> Manipulation '[] schemas params ys
375375 -- ^ `insertInto`, `update` or `deleteFrom`
@@ -377,13 +377,13 @@ class Monad pq => MonadPQ schemas pq | pq -> schemas where
377377 forPrepared = flip traversePrepared
378378
379379 traversePrepared_
380− :: (ToParams x params, Foldable list, All HasOidParam params)
380+ :: (ToParams x params, Foldable list, All OidOfParam params)
381381 => Manipulation '[] schemas params '[]
382382 -- ^ `insertInto`, `update` or `deleteFrom`
383383 -> list x -> pq ()
384384 default traversePrepared_
385385 :: (MonadTrans t, MonadPQ schemas pq1, pq ~ t pq1)
386− => (ToParams x params, Foldable list, All HasOidParam params)
386+ => (ToParams x params, Foldable list, All OidOfParam params)
387387 => Manipulation '[] schemas params '[]
388388 -- ^ `insertInto`, `update` or `deleteFrom`
389389 -> list x -> pq ()
@@ -391,7 +391,7 @@ class Monad pq => MonadPQ schemas pq | pq -> schemas where
391391 traversePrepared_ manipulation params
392392
393393 forPrepared_
394− :: (ToParams x params, Foldable list, All HasOidParam params)
394+ :: (ToParams x params, Foldable list, All OidOfParam params)
395395 => list x
396396 -> Manipulation '[] schemas params '[]
397397 -- ^ `insertInto`, `update` or `deleteFrom`
@@ -412,7 +412,7 @@ instance (MonadIO io, schemas0 ~ schemas, schemas1 ~ schemas)
412412 PQ $ \ (K conn) -> do
413413 let
414414 paramSet
415− :: forall param. HasOidParam param
415+ :: forall param. OidOfParam param
416416 => K (Maybe Encoding.Encoding) param
417417 -> K (Maybe (LibPQ.Oid, ByteString, LibPQ.Format)) param
418418 paramSet (K maybeEncoding) = K $
@@ -420,7 +420,7 @@ instance (MonadIO io, schemas0 ~ schemas, schemas1 ~ schemas)
420420 (oidOfParam @param, encodingBytes encoding, LibPQ.Binary)
421421 params'
422422 = hcollapse
423− . hcmap (Proxy @HasOidParam) paramSet
423+ . hcmap (Proxy @OidOfParam) paramSet
424424 $ toParams @x @ps params
425425 q' = q <> ";"
426426 resultMaybe <- liftIO $ LibPQ.execParams conn q' params' LibPQ.Binary
@@ -436,10 +436,10 @@ instance (MonadIO io, schemas0 ~ schemas, schemas1 ~ schemas)
436436 PQ $ \ (K conn) -> liftIO $ do
437437 let
438438 temp = "temporary_statement"
439− paramOid :: forall p. HasOidParam p => K LibPQ.Oid p
439+ paramOid :: forall p. OidOfParam p => K LibPQ.Oid p
440440 paramOid = K (oidOfParam @p)
441441 paramOids :: NP (K LibPQ.Oid) xs
442− paramOids = hcpure (Proxy @HasOidParam) paramOid
442+ paramOids = hcpure (Proxy @OidOfParam) paramOid
443443 paramOids' :: [LibPQ.Oid]
444444 paramOids' = hcollapse paramOids
445445 prepResultMaybe <- LibPQ.prepare conn temp q (Just paramOids')
@@ -470,10 +470,10 @@ instance (MonadIO io, schemas0 ~ schemas, schemas1 ~ schemas)
470470 PQ $ \ (K conn) -> liftIO $ do
471471 let
472472 temp = "temporary_statement"
473− paramOid :: forall p. HasOidParam p => K LibPQ.Oid p
473+ paramOid :: forall p. OidOfParam p => K LibPQ.Oid p
474474 paramOid = K (oidOfParam @p)
475475 paramOids :: NP (K LibPQ.Oid) xs
476− paramOids = hcpure (Proxy @HasOidParam) paramOid
476+ paramOids = hcpure (Proxy @OidOfParam) paramOid
477477 paramOids' :: [LibPQ.Oid]
478478 paramOids' = hcollapse paramOids
479479 prepResultMaybe <- LibPQ.prepare conn temp q (Just paramOids')
squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+33−25
@@ -554,9 +554,9 @@ select_ = select . List
554554-- be subject to the elimination of duplicate rows using `selectDistinct`.
555555selectDistinct
556556 :: (SListI columns, columns ~ (col ': cols))
557− => Selection outer commons 'Ungrouped schemas params from columns
557+ => Selection outer commons grp schemas params from columns
558558 -- ^ selection
559− -> TableExpression outer commons 'Ungrouped schemas params from
559+ -> TableExpression outer commons grp schemas params from
560560 -- ^ intermediate virtual table
561561 -> Query outer commons schemas params columns
562562selectDistinct selection tabexpr = UnsafeQuery $
@@ -568,9 +568,9 @@ selectDistinct selection tabexpr = UnsafeQuery $
568568-- of a general `Selection`.
569569selectDistinct_
570570 :: (SListI columns, columns ~ (col ': cols))
571− => NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns
571+ => NP (Aliased (Expression outer commons grp schemas params from)) columns
572572 -- ^ select list
573− -> TableExpression outer commons 'Ungrouped schemas params from
573+ -> TableExpression outer commons grp schemas params from
574574 -- ^ intermediate virtual table
575575 -> Query outer commons schemas params columns
576576selectDistinct_ = selectDistinct . List
@@ -580,14 +580,21 @@ selectDistinct_ = selectDistinct . List
580580the given expressions evaluate to equal. The DISTINCT ON expressions are
581581interpreted using the same rules as for ORDER BY. ORDER BY is used to
582582ensure that the desired row appears first.
583+
584+The DISTINCT ON expression(s) must match the leftmost ORDER BY expression(s).
585+The ORDER BY clause will normally contain additional expression(s) that
586+determine the desired precedence of rows within each DISTINCT ON group.
587+
588+In order to guarantee they match and reduce redundancy, this function
589+will prepend the The DISTINCT ON expressions to the ORDER BY clause.
583590-}
584591selectDistinctOn
585592 :: (SListI columns, columns ~ (col ': cols))
586− => [SortExpression outer commons 'Ungrouped schemas params from]
587− -- ^ distinct on and return the first row in ordering
588− -> Selection outer commons 'Ungrouped schemas params from columns
593+ => [SortExpression outer commons grp schemas params from]
594+ -- ^ DISTINCT ON expression(s) and prepended to ORDER BY clause
595+ -> Selection outer commons grp schemas params from columns
589596 -- ^ selection
590− -> TableExpression outer commons 'Ungrouped schemas params from
597+ -> TableExpression outer commons grp schemas params from
591598 -- ^ intermediate virtual table
592599 -> Query outer commons schemas params columns
593600selectDistinctOn distincts selection tab = UnsafeQuery $
@@ -608,11 +615,11 @@ selectDistinctOn distincts selection tab = UnsafeQuery $
608615-- of a general `Selection`.
609616selectDistinctOn_
610617 :: (SListI columns, columns ~ (col ': cols))
611− => [SortExpression outer commons 'Ungrouped schemas params from]
618+ => [SortExpression outer commons grp schemas params from]
612619 -- ^ distinct on and return the first row in ordering
613− -> NP (Aliased (Expression outer commons 'Ungrouped schemas params from)) columns
620+ -> NP (Aliased (Expression outer commons grp schemas params from)) columns
614621 -- ^ selection
615− -> TableExpression outer commons 'Ungrouped schemas params from
622+ -> TableExpression outer commons grp schemas params from
616623 -- ^ intermediate virtual table
617624 -> Query outer commons schemas params columns
618625selectDistinctOn_ distincts = selectDistinctOn distincts . List
@@ -750,7 +757,7 @@ instance RenderSQL (TableExpression outer commons grp schemas params from) where
750757from
751758 :: FromClause outer commons schemas params from -- ^ table reference
752759 -> TableExpression outer commons 'Ungrouped schemas params from
753−from tab = TableExpression tab [] NoGroups NoHaving [] [] []
760+from tab = TableExpression tab [] noGroups NoHaving [] [] []
754761
755762-- | A `where_` is an endomorphism of `TableExpression`s which adds a
756763-- search condition to the `whereClause`.
@@ -771,7 +778,7 @@ groupBy
771778groupBy bys rels = TableExpression
772779 { fromClause = fromClause rels
773780 , whereClause = whereClause rels
774− , groupByClause = Group bys
781+ , groupByClause = group bys
775782 , havingClause = Having []
776783 , orderByClause = []
777784 , limitClause = limitClause rels
@@ -985,19 +992,20 @@ instance (Has rel rels cols, Has col cols ty, bys ~ '[ '(rel, col)])
985992-- done on @NoGroups@ while all output `Expression`s must be aggregated
986993-- in @Group Nil@. In general, all output `Expression`s in the
987994-- complement of @bys@ must be aggregated in @Group bys@.
988−data GroupByClause grp from where
989− NoGroups :: GroupByClause 'Ungrouped from
990− Group
991− :: SListI bys
992− => NP (By from) bys
993− -> GroupByClause ('Grouped bys) from
994−
995−-- | Renders a `GroupByClause`.
995+newtype GroupByClause grp from = UnsafeGroupByClause
996+ { renderGroupByClause :: ByteString }
997+ deriving (GHC.Generic,Show,Eq,Ord,NFData)
996998instance RenderSQL (GroupByClause grp from) where
997− renderSQL = \case
998− NoGroups -> ""
999− Group Nil -> ""
1000− Group bys -> " GROUP BY" <+> renderCommaSeparated renderSQL bys
999+ renderSQL = renderGroupByClause
1000+noGroups :: GroupByClause 'Ungrouped from
1001+noGroups = UnsafeGroupByClause ""
1002+group
1003+ :: SListI bys
1004+ => NP (By from) bys
1005+ -> GroupByClause ('Grouped bys) from
1006+group bys = UnsafeGroupByClause $ case bys of
1007+ Nil -> ""
1008+ bys' -> " GROUP BY" <+> renderCommaSeparated renderSQL bys'
10011009
10021010-- | A `HavingClause` is used to eliminate groups that are not of interest.
10031011-- An `Ungrouped` `TableExpression` may only use `NoHaving` while a `Grouped`
squeal-postgresql/test/Property.hs+2−2
@@ -92,14 +92,14 @@ roundtrips = Group "roundtrips"
9292 -- genTimeWithZone = (,) <$> genTimeOfDay <*> genTimeZone
9393
9494roundtrip
95− :: (HasOid ty, ToParam x ty, FromValue ty x, Show x, Eq x)
95+ :: (OidOf ty, ToParam x ty, FromValue ty x, Show x, Eq x)
9696 => TypeExpression schemas ('NotNull ty)
9797 -> Gen x
9898 -> (PropertyName, Property)
9999roundtrip = roundtripOn id
100100
101101roundtripOn
102− :: (HasOid ty, ToParam x ty, FromValue ty x, Show x, Eq x)
102+ :: (OidOf ty, ToParam x ty, FromValue ty x, Show x, Eq x)
103103 => (x -> x)
104104 -> TypeExpression schemas ('NotNull ty)
105105 -> Gen x