@@ -3,7 +3,8 @@
3### Version 0.4
3### Version 0.4
5Version 0.4 of strengthens Squeal's type system, adds
5Version 0.4 of strengthens Squeal's type system, adds
6−support for multidimensional arrays, improves `with` statements,
6+support for multidimensional arrays, improves support
7+for container type, improves `with` statements,
7improves runtime exceptions, accomodates SQL's three-valued logic,
8improves runtime exceptions, accomodates SQL's three-valued logic,
8adds subquery expressions, and adds table and view type expressions.
9adds subquery expressions, and adds table and view type expressions.
@@ -146,6 +147,120 @@ void . withConnection "host=localhost port=5432 dbname=exampledb" $ do
152+Squeal aims to provide a correspondence between Haskell types and Postgres types.
153+In particular, Haskell ADTs with nullary constructors can correspond to
154+Postgres enum types and Haskell record types can correspond to Postgres
155+composite types. However, it's not always obvious that that's how a user
156+will choose to store values of those types. So Squeal 0.4 introduces newtypes
157+whose purpose is to specify how a user wants to store values of a type.
160+newtype Json hask = Json {getJson :: hask}
161+newtype Jsonb hask = Jsonb {getJsonb :: hask}
162+newtype Composite record = Composite {getComposite :: record}
163+newtype Enumerated enum = Enumerated {getEnumerated :: enum}
166+Let's see an example:
169+>>> data Schwarma = Beef | Lamb | Chicken deriving (Eq, Show, GHC.Generic)
170+>>> instance SOP.Generic Schwarma
171+>>> instance SOP.HasDatatypeInfo Schwarma
173+>>> data Person = Person {name :: Text, age :: Int32} deriving (Eq, Show, GHC.Generic)
174+>>> instance SOP.Generic Person
175+>>> instance SOP.HasDatatypeInfo Person
176+>>> instance Aeson.FromJSON Person
177+>>> instance Aeson.ToJSON Person
180+We can create the equivalent Postgres types directly from their Haskell types.
185+ '[ "schwarma" ::: 'Typedef (PG (Enumerated Schwarma))
186+ , "person" ::: 'Typedef (PG (Composite Person))
192+ setup :: Definition '[] Schema
194+ createTypeEnumFrom @Schwarma #schwarma >>>
195+ createTypeCompositeFrom @Person #person
199+Let's demonstrate how to associate our Haskell types `Schwarma` and `Person`
200+with enumerated, composite or json types in Postgres. First create a Haskell
201+`Row` type using the `Enumerated`, `Composite` and `Json` newtypes as fields.
206+ { schwarma :: Enumerated Schwarma
207+ , person1 :: Composite Person
208+ , person2 :: Json Person
209+ } deriving (Eq, GHC.Generic)
212+>>> instance Generic Row
213+>>> instance HasDatatypeInfo Row
217+ (Enumerated Chicken)
218+ (Composite (Person "Faisal" 24))
219+ (Json (Person "Ahmad" 48))
223+Once again, define a round trip query.
228+ roundTrip :: Query Schema (TuplePG Row) (RowPG Row)
229+ roundTrip = values_ $
230+ parameter @1 (typedef #schwarma) `as` #schwarma :*
231+ parameter @2 (typedef #person) `as` #person1 :*
232+ parameter @3 json `as` #person2
236+Finally, we can drop our type definitions.
241+ teardown :: Definition Schema '[]
242+ teardown = dropType #schwarma >>> dropType #person
252+ result <- runQueryParams roundTrip input
253+ Just output <- firstRow result
254+ liftBase . print $ input == output
256+ void . withConnection "host=localhost port=5432 dbname=exampledb" $
259+ & pqThen (define teardown)
151Squeal 0.3 supported WITH statements but there's a couple problems with them.
266Squeal 0.3 supported WITH statements but there's a couple problems with them.