on dev help sign in
Merge branch '0.3' of https://github.com/morphismtech/squeal into 0.3
commitd01439b44fcb0a1470f9d72f48e1aa694cb4fc85 authorEitan Chatav <eitan.chatav@gmail.com> dateMon 25 Jun 2018, 12:49 (8 years ago) parentcad427a6f83d1a
1 file changed+198−5
RELEASE NOTES.md+198−5
RELEASE NOTES.md+198−5
@@ -1,11 +1,204 @@
11## RELEASE NOTES
22
3−### Version 0.3.0.0 - June 23, 2018
3+### Version 0.3 - June 23, 2018
44
5−**Changes**
6−- **Views** - Create, drop and query views
7−- **Enums, Composites** - Create, drop and marshal enumerated and composite types
8−- **Bugfixes**
5+Version 0.3 of Squeal adds views as well as composite and enumerated types to Squeal.
6+To support these features, a new kind `SchemumType` was added.
7+
8+```Haskell
9+data SchemumType
10+ = Table TableType
11+ | View RelationType
12+ | Typedef PGType
13+```
14+
15+As a consequence, you will have to update your schema definitions like so:
16+
17+```Haskell
18+-- Squeal 0.2
19+type Schema =
20+ '[ "users" :::
21+ '[ "pk_users" ::: 'PrimaryKey '["id"] ] :=>
22+ '[ "id" ::: 'Def :=> 'NotNull 'PGint4
23+ , "name" ::: 'NoDef :=> 'NotNull 'PGtext
24+ ]
25+ ]
26+
27+-- Squeal 0.3
28+type Schema =
29+ '[ "users" ::: 'Table (
30+ '[ "pk_users" ::: 'PrimaryKey '["id"] ] :=>
31+ '[ "id" ::: 'Def :=> 'NotNull 'PGint4
32+ , "name" ::: 'NoDef :=> 'NotNull 'PGtext
33+ ])
34+ ]
35+```
36+
37+**Views**
38+
39+You can now create, drop, and query views.
40+
41+```Haskell
42+>>> :{
43+type ABC =
44+ ('[] :: TableConstraints) :=>
45+ '[ "a" ::: 'NoDef :=> 'Null 'PGint4
46+ , "b" ::: 'NoDef :=> 'Null 'PGint4
47+ , "c" ::: 'NoDef :=> 'Null 'PGint4
48+ ]
49+type BC =
50+ '[ "b" ::: 'Null 'PGint4
51+ , "c" ::: 'Null 'PGint4
52+ ]
53+:}
54+
55+>>> :{
56+let
57+ definition :: Definition '["abc" ::: 'Table ABC ] '["abc" ::: 'Table ABC, "bc" ::: 'View BC]
58+ definition = createView #bc (select (#b :* #c :* Nil) (from (table #abc)))
59+in printSQL definition
60+:}
61+CREATE VIEW "bc" AS SELECT "b" AS "b", "c" AS "c" FROM "abc" AS "abc";
62+
63+>>> :{
64+let
65+ definition :: Definition '["abc" ::: 'Table ABC, "bc" ::: 'View BC] '["abc" ::: 'Table ABC]
66+ definition = dropView #bc
67+in printSQL definition
68+:}
69+DROP VIEW "bc";
70+
71+>>> :{
72+let
73+ query :: Query '["abc" ::: 'Table ABC, "bc" ::: 'View BC] '[] BC
74+ query = selectStar (from (view #bc))
75+in printSQL query
76+:}
77+SELECT * FROM "bc" AS "bc"
78+```
79+
80+**Enumerated Types**
81+
82+PostgreSQL has a powerful type system. It even allows for user defined types.
83+For instance, you can define enumerated types which are data types that comprise
84+a static, ordered set of values. They are equivalent to Haskell algebraic data
85+types whose constructors are nullary. An example of an enum type might be the days of the week,
86+or a set of status values for a piece of data.
87+
88+Enumerated types are created using the `createTypeEnum` command, for example:
89+
90+```Haskell
91+>>> :{
92+let
93+ definition :: Definition '[] '["mood" ::: 'Typedef ('PGenum '["sad", "ok", "happy"])]
94+ definition = createTypeEnum #mood (label @"sad" :* label @"ok" :* label @"happy" :* Nil)
95+:}
96+>>> printSQL definition
97+CREATE TYPE "mood" AS ENUM ('sad', 'ok', 'happy');
98+```
99+
100+Enumerated types can also be generated from a Haskell algbraic data type with nullary constructors, for example:
101+
102+```Haskell
103+>>> data Schwarma = Beef | Lamb | Chicken deriving GHC.Generic
104+>>> instance SOP.Generic Schwarma
105+>>> instance SOP.HasDatatypeInfo Schwarma
106+
107+>>> :kind! EnumFrom Schwarma
108+EnumFrom Schwarma :: PGType
109+= 'PGenum '["Beef", "Lamb", "Chicken"]
110+
111+>>> :{
112+let
113+ definition :: Definition '[] '["schwarma" ::: 'Typedef (EnumFrom Schwarma)]
114+ definition = createTypeEnumFrom @Schwarma #schwarma
115+:}
116+>>> printSQL definition
117+CREATE TYPE "schwarma" AS ENUM ('Beef', 'Lamb', 'Chicken');
118+```
119+
120+You can express values of an enum type using `label`, which is an overloaded method
121+of the `IsPGlabel` typeclass.
122+
123+```Haskell
124+>>> :{
125+let
126+ expression :: Expression sch rels grp params ('NotNull (EnumFrom Schwarma))
127+ expression = label @"Chicken"
128+in printSQL expression
129+:}
130+'Chicken'
131+```
132+
133+**Composite Types**
134+
135+In addition to enum types, you can define composite types.
136+A composite type represents the structure of a row or record;
137+it is essentially just a list of field names and their data types.
138+
139+
140+`createTypeComposite` creates a composite type. The composite type is
141+specified by a list of attribute names and data types.
142+
143+```Haskell
144+>>> :{
145+let
146+ definition :: Definition '[] '["complex" ::: 'Typedef ('PGcomposite '["real" ::: 'PGfloat8, "imaginary" ::: 'PGfloat8])]
147+ definition = createTypeComposite #complex (float8 `As` #real :* float8 `As` #imaginary :* Nil)
148+:}
149+>>> printSQL definition
150+CREATE TYPE "complex" AS ("real" float8, "imaginary" float8);
151+```
152+
153+Composite types are almost equivalent to Haskell record types.
154+However, because of the potential presence of @NULL@
155+all the record fields must be `Maybe`s of basic types.
156+Composite types can be generated from a Haskell record type, for example:
157+
158+```Haskell
159+>>> data Complex = Complex {real :: Maybe Double, imaginary :: Maybe Double} deriving GHC.Generic
160+>>> instance SOP.Generic Complex
161+>>> instance SOP.HasDatatypeInfo Complex
162+
163+>>> :kind! CompositeFrom Complex
164+CompositeFrom Complex :: PGType
165+= 'PGcomposite '['("real", 'PGfloat8), '("imaginary", 'PGfloat8)]
166+
167+>>> :{
168+let
169+ definition :: Definition '[] '["complex" ::: 'Typedef (CompositeFrom Complex)]
170+ definition = createTypeCompositeFrom @Complex #complex
171+in printSQL definition
172+:}
173+CREATE TYPE "complex" AS ("real" float8, "imaginary" float8);
174+```
175+
176+A row constructor is an expression that builds a row value
177+(also called a composite value) using values for its member fields.
178+
179+```Haskell
180+>>> :{
181+let
182+ i :: Expression '[] '[] 'Ungrouped '[] ('NotNull (CompositeFrom Complex))
183+ i = row (0 `As` #real :* 1 `As` #imaginary :* Nil)
184+:}
185+>>> printSQL i
186+ROW(0, 1)
187+```
188+
189+You can also use `(&)` to apply a field label to a composite value.
190+
191+```Haskell
192+>>> :{
193+let
194+ expr :: Expression '[] '[] 'Ungrouped '[] ('Null 'PGfloat8)
195+ expr = i & #imaginary
196+in printSQL expr
197+:}
198+(ROW(0, 1)).imaginary
199+```
200+
201+Both composite and enum types can be automatically encoded from and decoded to their equivalent Haskell types.
9202
10203### Version 0.2.1 - April 7, 2018
11204