@@ -36,28 +36,32 @@ type Schema =
36 '[ "users" ::: 'Table (
36 '[ "users" ::: 'Table (
37 '[ "pk_users" ::: 'PrimaryKey '["id"] ] :=>
37 '[ "pk_users" ::: 'PrimaryKey '["id"] ] :=>
38 '[ "id" ::: 'Def :=> 'NotNull 'PGint4
38 '[ "id" ::: 'Def :=> 'NotNull 'PGint4
39− , "name" ::: 'NoDef :=> 'NotNull 'PGtext
39+ , "name" ::: 'NoDef :=> 'NotNull 'PGtext
41 , "emails" ::: 'Table (
41 , "emails" ::: 'Table (
42 '[ "pk_emails" ::: 'PrimaryKey '["id"]
42 '[ "pk_emails" ::: 'PrimaryKey '["id"]
43− , "fk_user_id" ::: 'ForeignKey '["user_id"] "users" '["id"]
43+ , "fk_user_id" ::: 'ForeignKey '["user_id"] "users" '["id"]
45 '[ "id" ::: 'Def :=> 'NotNull 'PGint4
45 '[ "id" ::: 'Def :=> 'NotNull 'PGint4
46− , "user_id" ::: 'NoDef :=> 'NotNull 'PGint4
46+ , "user_id" ::: 'NoDef :=> 'NotNull 'PGint4
47− , "email" ::: 'NoDef :=> 'Null 'PGtext
47+ , "email" ::: 'NoDef :=> 'Null 'PGtext
52−Notice the use of type operators. `:::` is used
52+Notice the use of type operators.
53−to pair an alias `Symbol` with either a `TableType` or a `ColumnType`.
54+`:::` is used to pair an alias `GHC.TypeLits.Symbol` with a `SchemumType`,
54−`:=>` is used to pair a `TableConstraint`s with a `ColumnsType`,
55+a `TableConstraint` or a `ColumnType`. It is intended to connote Haskell's @::@
58+`:=>` is used to pair `TableConstraints` with a `ColumnsType`,
55yielding a `TableType`, or to pair a `ColumnConstraint` with a `NullityType`,
59yielding a `TableType`, or to pair a `ColumnConstraint` with a `NullityType`,
56−yielding a `ColumnType`.
60+yielding a `ColumnType`. It is intended to connote Haskell's @=>@ operator
58Next, we'll write `Definition`s to set up and tear down the schema. In
62Next, we'll write `Definition`s to set up and tear down the schema. In
59−Squeal, a `Definition` is a `createTable`, `alterTable` or `dropTable`
63+Squeal, a `Definition` like `createTable`, `alterTable` or `dropTable`
60−command and has two type parameters, corresponding to the schema
64+has two type parameters, corresponding to the schema
61before being run and the schema after. We can compose definitions using `>>>`.
65before being run and the schema after. We can compose definitions using `>>>`.
62Here and in the rest of our commands we make use of overloaded
66Here and in the rest of our commands we make use of overloaded
63labels to refer to named tables and columns in our schema.
67labels to refer to named tables and columns in our schema.
@@ -101,12 +105,11 @@ DROP TABLE "emails";
101DROP TABLE "users";
105DROP TABLE "users";
103Next, we'll write `Manipulation`s to insert data into our two tables.
107Next, we'll write `Manipulation`s to insert data into our two tables.
104−A `Manipulation` is an `insertRow` (or other inserts), `update`
108+A `Manipulation` like `insertRow`, `update` or `deleteFrom`
105−or `deleteFrom` command and
106has three type parameters, the schema it refers to, a list of parameters
109has three type parameters, the schema it refers to, a list of parameters
107it can take as input, and a list of columns it produces as output. When
110it can take as input, and a list of columns it produces as output. When
108we insert into the users table, we will need a parameter for the @name@
111we insert into the users table, we will need a parameter for the @name@
109−field but not for the @id@ field. Since it's optional, we can use a default
112+field but not for the @id@ field. Since it's serial, we can use a default
110value. However, since the emails table refers to the users table, we will
113value. However, since the emails table refers to the users table, we will
111need to retrieve the user id that the insert generates and insert it into
114need to retrieve the user id that the insert generates and insert it into
112the emails table. Take a careful look at the type and definition of both
115the emails table. Take a careful look at the type and definition of both
@@ -144,7 +147,7 @@ need to use an inner join to get the right result. A `Query` is like a
145 getUsers :: Query Schema '[]
148 getUsers :: Query Schema '[]
146 '[ "userName" ::: 'NotNull 'PGtext
149 '[ "userName" ::: 'NotNull 'PGtext
147− , "userEmail" ::: 'Null 'PGtext ]
150+ , "userEmail" ::: 'Null 'PGtext ]
148 getUsers = select
151 getUsers = select
149 (#u ! #name `As` #userName :* #e ! #email `As` #userEmail :* Nil)
152 (#u ! #name `As` #userName :* #e ! #email `As` #userEmail :* Nil)
150 ( from (table (#users `As` #u)
153 ( from (table (#users `As` #u)
@@ -195,13 +198,11 @@ let
195 usersResult <- runQuery getUsers
198 usersResult <- runQuery getUsers
196 usersRows <- getRows usersResult
199 usersRows <- getRows usersResult
197 liftBase $ print (usersRows :: [User])
200 liftBase $ print (usersRows :: [User])
201−void . withConnection "host=localhost port=5432 dbname=exampledb" $
202+ void . withConnection "host=localhost port=5432 dbname=exampledb" $
202− define setup
203+ define setup
203− & pqThen session
204+ & pqThen session
204− & pqThen (define teardown)
205+ & pqThen (define teardown)
206[User {userName = "Alice", userEmail = Just "alice@gmail.com"},User {userName = "Bob", userEmail = Nothing},User {userName = "Carole", userEmail = Just "carole@hotmail.com"}]
207[User {userName = "Alice", userEmail = Just "alice@gmail.com"},User {userName = "Bob", userEmail = Nothing},User {userName = "Carole", userEmail = Just "carole@hotmail.com"}]