on dev help sign in
documentation
bf8b907Eitan Chatav
squeal-postgresql/src/Squeal/PostgreSQL.hs+18−17
@@ -4,7 +4,8 @@
4-- Maintainer: eitan@morphism.tech
4-- Maintainer: eitan@morphism.tech
5-- Stability: experimental
5-- Stability: experimental
6--
6--
7−-- Squeal is a deep embedding of PostgreSQL in Haskell. Let's see an example!
7+-- Squeal is a deep embedding of [PostgreSQL](https://www.postgresql.org) in Haskell.
8+-- Let's see an example!
8--
9--
9-- First, we need some language extensions because Squeal uses modern GHC
10-- First, we need some language extensions because Squeal uses modern GHC
10-- features.
11-- features.
@@ -26,32 +27,32 @@
26-- >>> import qualified GHC.Generics as GHC
27-- >>> import qualified GHC.Generics as GHC
27--
28--
28-- The first step is to define the schema of our database. This is where
29-- The first step is to define the schema of our database. This is where
29−-- we use @DataKinds@ and @TypeOperators@. The schema consists of a type-level
30+-- we use @DataKinds@ and @TypeOperators@.
30−-- list of tables, a `:::` pairing of a type level string or
31−-- @Symbol@ and a list a columns, itself a `:::` pairing of a
32−-- @Symbol@ and a `ColumnType`. The `ColumnType` describes the
33−-- PostgreSQL type of the column as well as whether or not it may contain
34−-- @NULL@ and whether or not inserts and updates can use a @DEFAULT@. For our
35−-- schema, we'll define two tables, a users table and an emails table.
36--
31--
37-- >>> :{
32-- >>> :{
38-- type Schema =
33-- type Schema =
39-- '[ "users" :::
34-- '[ "users" :::
40-- '[ "pk_users" ::: 'PrimaryKey '["id"] ] :=>
35-- '[ "pk_users" ::: 'PrimaryKey '["id"] ] :=>
41−-- '[ "id" ::: 'Def :=> 'NotNull 'PGint4
36+-- '[ "id" ::: 'Def :=> 'NotNull 'PGint4
42-- , "name" ::: 'NoDef :=> 'NotNull 'PGtext
37-- , "name" ::: 'NoDef :=> 'NotNull 'PGtext
43-- ]
38-- ]
44-- , "emails" :::
39-- , "emails" :::
45−-- '[ "pk_emails" ::: 'PrimaryKey '["id"]
40+-- '[ "pk_emails" ::: 'PrimaryKey '["id"]
46-- , "fk_user_id" ::: 'ForeignKey '["user_id"] "users" '["id"]
41-- , "fk_user_id" ::: 'ForeignKey '["user_id"] "users" '["id"]
47-- ] :=>
42-- ] :=>
48−-- '[ "id" ::: 'Def :=> 'NotNull 'PGint4
43+-- '[ "id" ::: 'Def :=> 'NotNull 'PGint4
49-- , "user_id" ::: 'NoDef :=> 'NotNull 'PGint4
44-- , "user_id" ::: 'NoDef :=> 'NotNull 'PGint4
50−-- , "email" ::: 'NoDef :=> 'Null 'PGtext
45+-- , "email" ::: 'NoDef :=> 'Null 'PGtext
51-- ]
46-- ]
52-- ]
47-- ]
53-- :}
48-- :}
54--
49--
50+-- Notice the use of type operators. `:::` is used
51+-- to pair an alias `Symbol` with either a `TableType` or a `ColumnType`.
52+-- `:=>` is used to pair a `TableConstraint`s with a `ColumnsType`,
53+-- yielding a `TableType`, or to pair a `ColumnConstraint` with a `NullityType`,
54+-- yielding a `ColumnType`.
55+--
55-- Next, we'll write `Definition`s to set up and tear down the schema. In
56-- Next, we'll write `Definition`s to set up and tear down the schema. In
56-- Squeal, a `Definition` is a `createTable`, `alterTable` or `dropTable`
57-- Squeal, a `Definition` is a `createTable`, `alterTable` or `dropTable`
57-- command and has two type parameters, corresponding to the schema
58-- command and has two type parameters, corresponding to the schema
@@ -96,7 +97,8 @@
96-- "DROP TABLE emails; DROP TABLE users;"
97-- "DROP TABLE emails; DROP TABLE users;"
97--
98--
98-- Next, we'll write `Manipulation`s to insert data into our two tables.
99-- Next, we'll write `Manipulation`s to insert data into our two tables.
100+-- A `Manipulation` is an `insertRow` (or other inserts), `update`
99−-- A `Manipulation` is a `insertInto`, `update` or `deleteFrom` command and
101+-- or `deleteFrom` command and
100-- has three type parameters, the schema it refers to, a list of parameters
102-- has three type parameters, the schema it refers to, a list of parameters
101-- it can take as input, and a list of columns it produces as output. When
103-- it can take as input, and a list of columns it produces as output. When
102-- we insert into the users table, we will need a parameter for the @name@
104-- we insert into the users table, we will need a parameter for the @name@
@@ -108,8 +110,7 @@
108--
110--
109-- >>> :{
111-- >>> :{
110-- let
112-- let
111−-- insertUser :: Manipulation Schema '[ 'NotNull 'PGtext ]
113+-- insertUser :: Manipulation Schema '[ 'NotNull 'PGtext ] '[ "fromOnly" ::: 'NotNull 'PGint4 ]
112−-- '[ "fromOnly" ::: 'NotNull 'PGint4 ]
113-- insertUser = insertRow #users
114-- insertUser = insertRow #users
114-- (Default `As` #id :* Set (param @1) `As` #name :* Nil)
115-- (Default `As` #id :* Set (param @1) `As` #name :* Nil)
115-- OnConflictDoNothing (Returning (#id `As` #fromOnly :* Nil))
116-- OnConflictDoNothing (Returning (#id `As` #fromOnly :* Nil))
@@ -138,8 +139,8 @@
138-- >>> :{
139-- >>> :{
139-- let
140-- let
140-- getUsers :: Query Schema '[]
141-- getUsers :: Query Schema '[]
141−-- '[ "userName" ::: 'NotNull 'PGtext
142+-- '[ "userName" ::: 'NotNull 'PGtext
142−-- , "userEmail" ::: 'Null 'PGtext ]
143+-- , "userEmail" ::: 'Null 'PGtext ]
143-- getUsers = select
144-- getUsers = select
144-- (#u ! #name `As` #userName :* #e ! #email `As` #userEmail :* Nil)
145-- (#u ! #name `As` #userName :* #e ! #email `As` #userEmail :* Nil)
145-- ( from (table (#users `As` #u)
146-- ( from (table (#users `As` #u)
squeal-postgresql/src/Squeal/PostgreSQL/Migration.hs+1
@@ -156,6 +156,7 @@ instance Category (AlignedList p) where
156 Done -> list
156 Done -> list
157 step :>> steps -> step :>> (steps >>> list)
157 step :>> steps -> step :>> (steps >>> list)
158
158
159+-- | A `single` step.
159single :: p x0 x1 -> AlignedList p x0 x1
160single :: p x0 x1 -> AlignedList p x0 x1
160single step = step :>> Done
161single step = step :>> Done
161
162