on dev help sign in
readme work
commit34a98dcc8c29a19036e75c3757f59629a09a5167 authorEitan Chatav <eitan@Eitans-MacBook-Pro.local> dateWed 29 May 2019, 09:05 (7 years ago) parent65dca81
2 files changed+345−2
RELEASE NOTES.md+343 squeal-postgresql/src/Squeal/PostgreSQL/Migration.hs+2−2
RELEASE NOTES.md+343
@@ -1,5 +1,348 @@
11## RELEASE NOTES
22
3+### Version 0.5
4+
5+Version 0.5 makes a number of large changes and additions to Squeal.
6+
7+**Multi-schema support**
8+
9+Previous versions of Squeal only supported definitions in the "public"
10+schema. Squeal 0.5 adds support for multiple schemas with the new kind
11+
12+```Haskell
13+type SchemasType = [(Symbol,SchemaType)]
14+```
15+
16+In order to upgrade your queries, manipulations and definitions from
17+Squeal 0.4, you will have to apply the `Public` type family, which indicates
18+that your only schema is the "public" schema.
19+
20+```Haskell
21+-- Squeal 0.4
22+setup :: Definition '[] Schema
23+
24+-- Squeal 0.5
25+setup :: Definition (Public '[]) (Public Schema)
26+```
27+
28+You can create non-public schemas using `createSchema` and inversely
29+remove them using `dropSchema`. There is also an idempotent
30+`createSchemaIfNotExists`.
31+
32+In order to handle aliases which may refer to non-public schemas, Squeal 0.5
33+introduces `QualifiedAlias`es. A `QualifiedAlias` can be referred to using
34+the `(!)` operator from the `IsQualified` typeclass; but if you want to refer
35+to an alias from the "public" schema, you can continue to use a single
36+overloaded label, no need to write `#public ! #tab`, just write `#tab`.
37+
38+**Top-level statements**
39+
40+As a consequence of multi-schema support, common table expressions that
41+a `Query` or `Manipulation` may refer to had to be broken into a new parameter.
42+Additionally, `Query` gained another new parameter for its outer scope which
43+will be discussed in the next section.
44+
45+To simplify type signatures that you have to write for top-level queries
46+and manipulations, Squeal 0.5 introduces the `Query_` and `Manipulation_`
47+type families.
48+
49+```
50+type family Query_
51+ (schemas :: SchemasType)
52+ (parameters :: Type)
53+ (row :: Type) where
54+ Query_ schemas params row =
55+ Query '[] '[] schemas (TuplePG params) (RowPG row)
56+```
57+
58+As you see, a top-level `Query_` has no outer scope and no common
59+table expressions in scope, they are empty `'[]`. Moreover,
60+its parameters and row parameters are now `Type`s, which are
61+converted to corresponding Postgres types using the `TuplePG`
62+and `RowPG` type families. This means you can write the type signatures
63+for your top-level statements using the Haskell types that you
64+intend to input and retrieve when running the statements. Similar
65+to `Query_`, there is a `Manipulation_` type, the only difference
66+being that a general `Manipulation` doesn't have an outer scope,
67+only a scope for common table expressions.
68+
69+**Subquery expressions**
70+
71+Previous versions of Squeal offered subquery expression support
72+but there were issues. The common use case of using the `IN` operator
73+from SQL was overly complex. There was a proliferation of subquery
74+functions to handle different comparison operators, each with two versions
75+for comparing `ALL` or `ANY` of the query rows. And, most confoundedly,
76+there was no way to support the `EXISTS` subquery because the "outer scope"
77+for a query was not available.
78+
79+Squeal adds an outer scope to the `Query` type.
80+
81+```Haskell
82+newtype Query
83+ (outer :: FromType)
84+ (commons :: FromType)
85+ (schemas :: SchemasType)
86+ (params :: [NullityType])
87+ (row :: RowType)
88+ = UnsafeQuery { renderQuery :: ByteString }
89+```
90+
91+This enables a well-typed `exists` function.
92+
93+```Haskell
94+exists
95+ :: Query (Join outer from) commons schemas params row
96+ -> Condition outer commons grp schemas params from
97+```
98+
99+The `in_` and `notIn` functions were simplified to handle the most
100+common use case of comparing to a list of values.
101+
102+```Haskell
103+in_
104+ :: Expression outer commons grp schemas params from ty -- ^ expression
105+ -> [Expression outer commons grp schemas params from ty]
106+ -> Condition outer commons grp schemas params from
107+```
108+
109+Finally, general subquery comparisons were abstracted to work with
110+any comparison operators, using the `Operator` type which will be discussed in
111+the next section.
112+
113+```Haskell
114+subAll
115+ :: Expression outer commons grp schemas params from ty1
116+ -> Operator ty1 ty2 ('Null 'PGbool)
117+ -> Query (Join outer from) commons schemas params '[col ::: ty2]
118+ -> Condition outer commons grp schemas params from
119+
120+subAny
121+ :: Expression outer commons grp schemas params from ty1
122+ -> Operator ty1 ty2 ('Null 'PGbool)
123+ -> Query (Join outer from) commons schemas params '[col ::: ty2]
124+ -> Condition outer commons grp schemas params from
125+```
126+
127+**Expression RankNTypes**
128+
129+Squeal 0.5 introduces RankNType type synonyms for common expression patterns.
130+The simplest example is the `Expr` type, a type for "closed" expressions
131+that cannot reference any aliases or parameters.
132+
133+```Haskell
134+type Expr x
135+ = forall outer commons grp schemas params from
136+ . Expression outer commons grp schemas params from x
137+```
138+
139+There is also a function type `(:-->)`, which is a subtype of the usual Haskell function
140+type `(->)`.
141+
142+```Haskell
143+type (:-->) x y
144+ = forall outer commons grp schemas params from
145+ . Expression outer commons grp schemas params from x
146+ -> Expression outer commons grp schemas params from y
147+```
148+
149+We saw in the subquery section that there is an `Operator` type.
150+
151+```Haskell
152+type Operator x1 x2 y
153+ = forall outer commons grp schemas params from
154+ . Expression outer commons grp schemas params from x1
155+ -> Expression outer commons grp schemas params from x2
156+ -> Expression outer commons grp schemas params from y
157+```
158+
159+There are also types `FunctionN` and `FunctionVar` for n-ary functions
160+and variadic functions.
161+
162+```
163+type FunctionN xs y
164+ = forall outer commons grp schemas params from
165+ . NP (Expression outer commons grp schemas params from) xs
166+ -> Expression outer commons grp schemas params from y
167+```
168+
169+An n-ary function takes an `NP` list of `Expression`s as its argument.
170+Squeal 0.5 adds a helpful operator `(*:)`, to help scrap your `Nil`s.
171+You can construct an `NP` list now by using the operator `(:*)`,
172+until your last element, using `(*:)` there. For instance, the function
173+`atan2_` takes two arguments, `atan2_ (pi *: 2)`.
174+
175+**Selections**
176+
177+Previously, Squeal provided a couple versions of `SELECT` depending
178+on whether you wanted to select all columns of a unique table
179+in the from clause, i.e. `*`, all columns of a particular table
180+in the from clause, i.e. `.*`, or a list of columns from the from clause.
181+
182+Squeal 0.5 refactors this pattern into a `Selection` GADT type, allowing
183+for abstraction and combinations that were not possible before.
184+
185+```Haskell
186+data Selection outer commons grp schemas params from row where
187+ Star
188+ :: HasUnique tab from row
189+ => Selection outer commons 'Ungrouped schemas params from row
190+ DotStar
191+ :: Has tab from row
192+ => Alias tab
193+ -> Selection outer commons 'Ungrouped schemas params from row
194+ List
195+ :: SListI row
196+ => NP (Aliased (Expression outer commons grp schemas params from)) row
197+ -> Selection outer commons grp schemas params from row
198+ Over
199+ :: SListI row
200+ => NP (Aliased (WindowFunction outer commons grp schemas params from)) row
201+ -> WindowDefinition outer commons grp schemas params from
202+ -> Selection outer commons grp schemas params from row
203+ Also
204+ :: Selection outer commons grp schemas params from right
205+ -> Selection outer commons grp schemas params from left
206+ -> Selection outer commons grp schemas params from (Join left right)
207+```
208+
209+In addition to the `Star`, `DotStar` and `List` constructors, there is an
210+`Also` constructor combinator, which enables users to combine `Selection`s.
211+Additionally, there is an `Over` constructor that is used to enable
212+window functions, described in the next section.
213+
214+To upgrade from Squeal 0.4, you will replace `selectStar` with `select Star`,
215+replace `selectDotStar #tab` with `select (DotStar #tab)`. The `List`
216+selection is such a common use case that there is a function `select_` which
217+automatically applies it, so to upgrade from Squeal 0.4, replace `select`
218+with `select_`. There are also independent `selectDistinct` and `selectDistinct_`
219+functions to filter out duplicate rows.
220+
221+**Window functions and aggregation**
222+
223+Previous versions of Squeal provided no support for window functions.
224+Squeal 0.5 adds support for window functions. We saw `Over` in the
225+previous section.
226+
227+```Haskell
228+Over
229+ :: SListI row
230+ => NP (Aliased (WindowFunction outer commons grp schemas params from)) row
231+ -> WindowDefinition outer commons grp schemas params from
232+ -> Selection outer commons grp schemas params from row
233+```
234+
235+`Over` combines window functions with window definitions. A `WindowDefinition`
236+is constructed using the `partitionBy` function, optionally with an `orderBy`
237+clause. For example,
238+
239+```Haskell
240+query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("rank" ::: Int64))
241+query = select
242+ (#col1 & Also (rank `as` #rank `Over` (partitionBy #col1 & orderBy [#col2 & Asc])))
243+ (from (table #tab))
244+```
245+
246+Here the `rank` function is a `WindowFunction`
247+
248+```Haskell
249+rank :: WinFun0 ('NotNull 'PGint8)
250+rank = UnsafeWindowFunction "rank()"
251+```
252+
253+`WinFun0` is a RankNType, like `Expr` was, used for no argument window functions.
254+Similarly, there are also `WinFun1` and `WinFunN` types for
255+window functions and n-ary window functions.
256+
257+In order to use the same syntax for certain window functions and aggregate functions,
258+a new typeclass `Aggregate` was introduced. So for instance, `sum_` can be
259+either a `Distinction` `Expression` or a `WindowFunction`, used either with
260+a `groupBy` or with a `partitionBy` in the appropriate way.
261+
262+```
263+data Distinction (expr :: kind -> Type) (ty :: kind)
264+ = All (expr ty)
265+ | Distinct (expr ty)
266+```
267+
268+Aggregate functions can be run over all rows or only over distinct rows,
269+while window functions bear no such distinction.
270+
271+**Migrations**
272+
273+Thanks to [https://github.com/Raveline](Raveline) Squeal 0.5 introduces
274+a function `defaultMain` to easily create a command line program to
275+run or rewind your migrations.
276+
277+Previously, Squeal's migrations were impure, allowing in addition to
278+running `Definition`s to run arbitrary `IO` operations, such as inserting
279+data into the database or printing out status messages. In order to
280+provide compatibility with other migration systems, Squeal 0.5 introduces
281+pure migrations, that is migrations that are only `Definition`s.
282+
283+```Haskell
284+data Migration p schemas0 schemas1 = Migration
285+ { name :: Text -- ^ The `name` of a `Migration`.
286+ -- Each `name` in a `Migration` should be unique.
287+ , up :: p schemas0 schemas1 -- ^ The `up` instruction of a `Migration`.
288+ , down :: p schemas1 schemas0 -- ^ The `down` instruction of a `Migration`.
289+ } deriving (GHC.Generic)
290+```
291+
292+A pure migration is a `Migration Definition`, a pair of inverse
293+`Definition`s with a unique name. To recover impure migrations, Squeal 0.5
294+introduces the `Terminally` type.
295+
296+```Haskell
297+newtype Terminally trans monad x0 x1 = Terminally
298+ { runTerminally :: trans x0 x1 monad () }
299+```
300+
301+`Terminally` applies the indexed monad transformer and the monad it transforms
302+to the unit type `()`, thereby turning an indexed monad into a `Category`. An
303+impure migration is a `Migration (Terminally PQ IO)`. You can always cast
304+a pure migration into an impure migration with the functor, `pureMigration`.
305+
306+```Haskell
307+pureMigration
308+ :: Migration Definition schemas0 schemas1
309+ -> Migration (Terminally PQ IO) schemas0 schemas1
310+```
311+
312+To run either pure or impure migrations, Squeal 0.5 introduces
313+a typeclass, `Migratory`.
314+
315+```
316+class Category p => Migratory p where
317+
318+ migrateUp
319+ :: AlignedList (Migration p) schemas0 schemas1
320+ -> PQ schemas0 schemas1 IO ()
321+
322+ migrateDown
323+ :: AlignedList (Migration p) schemas0 schemas1
324+ -> PQ schemas1 schemas0 IO ()
325+```
326+
327+The signatures of `migrateUp` and `migrateDown` have been changed
328+to make them easier to compose with other `PQ` actions.
329+
330+**Transactions**
331+
332+**Money**
333+
334+**Domains**
335+
336+**Time operations**
337+
338+**Literals**
339+
340+**Set returning functions**
341+
342+**Text search**
343+
344+**Lists**
345+
3346### Version 0.4
4347
5348Version 0.4 strengthens Squeal's type system, adds
squeal-postgresql/src/Squeal/PostgreSQL/Migration.hs+2−2
@@ -250,8 +250,8 @@ terminally = Terminally . void
250250-- | A `pureMigration` turns a `Migration` involving only pure SQL
251251-- `Definition`s into a `Migration` that may be combined with arbitrary `IO`.
252252pureMigration
253− :: Migration Definition schema0 schema1
254− -> Migration (Terminally PQ IO) schema0 schema1
253+ :: Migration Definition schemas0 schemas1
254+ -> Migration (Terminally PQ IO) schemas0 schemas1
255255pureMigration migration = Migration
256256 { name = name migration
257257 , up = terminally . define $ up migration