on dev help sign in
remove P

* P records is a good idea eventually but needs be more fully baked

commit7cc86fb441216c738af801550f8a051df7ea715e authorEitan Chatav <eitan@Eitans-MacBook-Pro.local> dateMon 17 Jun 2019, 21:32 (7 years ago) parent2ce8fe7
5 files changed+45−92
squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+8−2 squeal-postgresql/src/Squeal/PostgreSQL/Migration.hs+2−3 squeal-postgresql/src/Squeal/PostgreSQL/PG.hs−24 squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+35−24 squeal-postgresql/src/Squeal/PostgreSQL/Tutorial.hs−39
squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+8−2
@@ -116,6 +116,13 @@ may be referenced using positional
116116Haskell record or a generalized record using tuples of `P` types and normal Haskell
117117records, whose entries will be targeted using overloaded labels.
118118
119+>>> :set -XDeriveAnyClass -XDerivingStrategies
120+>>> :{
121+data Row a b = Row { col1 :: a, col2 :: b }
122+ deriving stock (GHC.Generic)
123+ deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
124+:}
125+
119126simple insert:
120127
121128>>> type Columns = '["col1" ::: 'NoDef :=> 'Null 'PGint4, "col2" ::: 'Def :=> 'NotNull 'PGint4]
@@ -196,8 +203,7 @@ delete:
196203
197204>>> :{
198205let
199− manipulation :: Manipulation_ (Public Schema) ()
200− (P ("col1" ::: Int32), P ("col2" ::: Int32))
206+ manipulation :: Manipulation_ (Public Schema) () (Row Int32 Int32)
201207 manipulation = deleteFrom #tab NoUsing (#col1 .== #col2) (Returning Star)
202208in printSQL manipulation
203209:}
squeal-postgresql/src/Squeal/PostgreSQL/Migration.hs+2−3
@@ -173,7 +173,6 @@ import Squeal.PostgreSQL.Expression.Time
173173import Squeal.PostgreSQL.Expression.Type
174174import Squeal.PostgreSQL.List
175175import Squeal.PostgreSQL.Manipulation
176−import Squeal.PostgreSQL.PG
177176import Squeal.PostgreSQL.PQ
178177import Squeal.PostgreSQL.Query
179178import Squeal.PostgreSQL.Schema
@@ -362,8 +361,8 @@ deleteMigration = deleteFrom_ #schema_migrations (#name .== param @1)
362361-- | Selects a `Migration` from the `MigrationsTable`, returning
363362-- the time at which it was inserted.
364363selectMigration
365− :: Query_ MigrationsSchemas (Only Text) (P ("executed_at" ::: UTCTime))
366−selectMigration = select_ #executed_at
364+ :: Query_ MigrationsSchemas (Only Text) (Only UTCTime)
365+selectMigration = select_ (#executed_at `as` #fromOnly)
367366 $ from (table (#schema_migrations))
368367 & where_ (#name .== param @1)
369368
squeal-postgresql/src/Squeal/PostgreSQL/PG.hs−24
@@ -79,7 +79,6 @@ import qualified Generics.SOP.Record as SOP
7979import qualified Generics.SOP.Type.Metadata as Type
8080
8181import Squeal.PostgreSQL.Alias
82−import Squeal.PostgreSQL.List
8382import Squeal.PostgreSQL.Schema
8483
8584-- $setup
@@ -175,31 +174,8 @@ have `SOP.Generic` and `SOP.HasDatatypeInfo` instances;
175174>>> :kind! RowPG Person
176175RowPG Person :: [(Symbol, NullityType)]
177176= '["name" ::: 'NotNull 'PGtext, "age" ::: 'NotNull 'PGint4]
178−
179−Or to tuples of `SOP.P` types;
180−
181−>>> :kind! RowPG (SOP.P ("id" ::: Int32), SOP.P ("foreign_id" ::: Int32))
182−RowPG (SOP.P ("id" ::: Int32), SOP.P ("foreign_id" ::: Int32)) :: [(Symbol,
183− NullityType)]
184−= '[ '("id", 'NotNull 'PGint4), "foreign_id" ::: 'NotNull 'PGint4]
185−
186−Or to tuples which mix `SOP.P` types and record types.
187−
188−>>> :kind! RowPG (SOP.P ("id" ::: Int32), Person, SOP.P ("foreign_id" ::: Int32))
189−RowPG (SOP.P ("id" ::: Int32), Person, SOP.P ("foreign_id" ::: Int32)) :: [(Symbol,
190− NullityType)]
191−= '[ '("id", 'NotNull 'PGint4), '("name", 'NotNull 'PGtext),
192− '("age", 'NotNull 'PGint4), "foreign_id" ::: 'NotNull 'PGint4]
193177-}
194178type family RowPG (hask :: Type) :: RowType where
195− RowPG (hask1, hask2) = Join (RowPG hask1) (RowPG hask2)
196− RowPG (hask1, hask2, hask3) =
197− Join (RowPG hask1) (RowPG (hask2, hask3))
198− RowPG (hask1, hask2, hask3, hask4) =
199− Join (RowPG hask1) (RowPG (hask2, hask3, hask4))
200− RowPG (hask1, hask2, hask3, hask4, hask5) =
201− Join (RowPG hask1) (RowPG (hask2, hask3, hask4, hask5))
202− RowPG (SOP.P (col ::: ty)) = '[col ::: NullPG ty]
203179 RowPG hask = RowOf (SOP.RecordCodeOf hask)
204180
205181-- | `RowOf` applies `NullPG` to the fields of a list.
squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+35−24
@@ -145,13 +145,20 @@ records, whose entries will be targeted using overloaded labels.
145145
146146Let's see some examples of queries.
147147
148+>>> :set -XDeriveAnyClass -XDerivingStrategies
149+>>> :{
150+data Row a b = Row { col1 :: a, col2 :: b }
151+ deriving stock (GHC.Generic)
152+ deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
153+:}
154+
148155simple query:
149156
150157>>> type Columns = '["col1" ::: 'NoDef :=> 'NotNull 'PGint4, "col2" ::: 'NoDef :=> 'NotNull 'PGint4]
151158>>> type Schema = '["tab" ::: 'Table ('[] :=> Columns)]
152159>>> :{
153160let
154− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
161+ query :: Query_ (Public Schema) () (Row Int32 Int32)
155162 query = select Star (from (table #tab))
156163in printSQL query
157164:}
@@ -161,21 +168,21 @@ restricted query:
161168
162169>>> :{
163170let
164− query :: Query_ (Public Schema) () (Sum Int32, P ("col1" ::: Int32))
171+ query :: Query_ (Public Schema) () (Row Int32 Int32)
165172 query =
166− select_ ((#col1 + #col2) `as` #getSum :* #col1)
173+ select_ ((#col1 + #col2) `as` #col1 :* #col1 `as` #col2)
167174 ( from (table #tab)
168175 & where_ (#col1 .> #col2)
169176 & where_ (#col2 .> 0) )
170177in printSQL query
171178:}
172−SELECT ("col1" + "col2") AS "getSum", "col1" AS "col1" FROM "tab" AS "tab" WHERE (("col1" > "col2") AND ("col2" > 0))
179+SELECT ("col1" + "col2") AS "col1", "col1" AS "col2" FROM "tab" AS "tab" WHERE (("col1" > "col2") AND ("col2" > 0))
173180
174181subquery:
175182
176183>>> :{
177184let
178− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
185+ query :: Query_ (Public Schema) () (Row Int32 Int32)
179186 query = select Star (from (subquery (select Star (from (table #tab)) `as` #sub)))
180187in printSQL query
181188:}
@@ -185,7 +192,7 @@ limits and offsets:
185192
186193>>> :{
187194let
188− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
195+ query :: Query_ (Public Schema) () (Row Int32 Int32)
189196 query = select Star (from (table #tab) & limit 100 & offset 2 & limit 50 & offset 2)
190197in printSQL query
191198:}
@@ -195,7 +202,7 @@ parameterized query:
195202
196203>>> :{
197204let
198− query :: Query_ (Public Schema) (Only Int32) (P ("col1" ::: Int32), P ("col2" ::: Int32))
205+ query :: Query_ (Public Schema) (Only Int32) (Row Int32 Int32)
199206 query = select Star (from (table #tab) & where_ (#col1 .> param @1))
200207in printSQL query
201208:}
@@ -205,21 +212,21 @@ aggregation query:
205212
206213>>> :{
207214let
208− query :: Query_ (Public Schema) () (Sum Int32, P ("col1" ::: Int32))
215+ query :: Query_ (Public Schema) () (Row Int32 Int32)
209216 query =
210− select_ ((fromNull 0 (sum_ (All #col2))) `as` #getSum :* #col1)
217+ select_ ((fromNull 0 (sum_ (All #col2))) `as` #col1 :* #col1 `as` #col2)
211218 ( from (table (#tab `as` #table1))
212219 & groupBy #col1
213220 & having (#col1 + (fromNull 0 (sum_ (Distinct #col2))) .> 1) )
214221in printSQL query
215222:}
216−SELECT COALESCE(sum(ALL "col2"), 0) AS "getSum", "col1" AS "col1" FROM "tab" AS "table1" GROUP BY "col1" HAVING (("col1" + COALESCE(sum(DISTINCT "col2"), 0)) > 1)
223+SELECT COALESCE(sum(ALL "col2"), 0) AS "col1", "col1" AS "col2" FROM "tab" AS "table1" GROUP BY "col1" HAVING (("col1" + COALESCE(sum(DISTINCT "col2"), 0)) > 1)
217224
218225sorted query:
219226
220227>>> :{
221228let
222− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
229+ query :: Query_ (Public Schema) () (Row Int32 Int32)
223230 query = select Star (from (table #tab) & orderBy [#col1 & Asc])
224231in printSQL query
225232:}
@@ -282,8 +289,10 @@ self-join:
282289
283290>>> :{
284291let
285− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
286− query = select (#t1 & DotStar) (from (table (#tab `as` #t1) & crossJoin (table (#tab `as` #t2))))
292+ query :: Query_ (Public Schema) () (Row Int32 Int32)
293+ query = select
294+ (#t1 & DotStar)
295+ (from (table (#tab `as` #t1) & crossJoin (table (#tab `as` #t2))))
287296in printSQL query
288297:}
289298SELECT "t1".* FROM "tab" AS "t1" CROSS JOIN "tab" AS "t2"
@@ -292,17 +301,19 @@ value queries:
292301
293302>>> :{
294303let
295− query :: Query_ schemas () (P ("foo" ::: Int32), P ("bar" ::: Bool))
296− query = values (1 `as` #foo :* true `as` #bar) [2 `as` #foo :* false `as` #bar]
304+ query :: Query_ schemas () (Row String Bool)
305+ query = values
306+ ("true" `as` #col1 :* true `as` #col2)
307+ ["false" `as` #col1 :* false `as` #col2]
297308in printSQL query
298309:}
299−SELECT * FROM (VALUES (1, TRUE), (2, FALSE)) AS t ("foo", "bar")
310+SELECT * FROM (VALUES (E'true', TRUE), (E'false', FALSE)) AS t ("col1", "col2")
300311
301312set operations:
302313
303314>>> :{
304315let
305− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
316+ query :: Query_ (Public Schema) () (Row Int32 Int32)
306317 query = select Star (from (table #tab)) `unionAll` select Star (from (table #tab))
307318in printSQL query
308319:}
@@ -312,7 +323,7 @@ with queries:
312323
313324>>> :{
314325let
315− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
326+ query :: Query_ (Public Schema) () (Row Int32 Int32)
316327 query = with (
317328 select Star (from (table #tab)) `as` #cte1 :>>
318329 select Star (from (common #cte1)) `as` #cte2
@@ -325,27 +336,27 @@ window function queries
325336
326337>>> :{
327338let
328− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("rank" ::: Int64))
339+ query :: Query_ (Public Schema) () (Row Int32 Int64)
329340 query = select
330− (#col1 & Also (rank `as` #rank `Over` (partitionBy #col1 & orderBy [#col2 & Asc])))
341+ (#col1 & Also (rank `as` #col2 `Over` (partitionBy #col1 & orderBy [#col2 & Asc])))
331342 (from (table #tab))
332343in printSQL query
333344:}
334−SELECT "col1" AS "col1", rank() OVER (PARTITION BY "col1" ORDER BY "col2" ASC) AS "rank" FROM "tab" AS "tab"
345+SELECT "col1" AS "col1", rank() OVER (PARTITION BY "col1" ORDER BY "col2" ASC) AS "col2" FROM "tab" AS "tab"
335346
336347correlated subqueries
337348
338349>>> :{
339350let
340− query :: Query_ (Public Schema) () (P ("col1" ::: Int32))
351+ query :: Query_ (Public Schema) () (Only Int32)
341352 query =
342− select #col1 (from (table (#tab `as` #t1))
353+ select (#col1 `as` #fromOnly) (from (table (#tab `as` #t1))
343354 & where_ (exists (
344355 select Star (from (table (#tab `as` #t2))
345356 & where_ (#t2 ! #col2 .== #t1 ! #col1)))))
346357in printSQL query
347358:}
348−SELECT "col1" AS "col1" FROM "tab" AS "t1" WHERE EXISTS (SELECT * FROM "tab" AS "t2" WHERE ("t2"."col2" = "t1"."col1"))
359+SELECT "col1" AS "fromOnly" FROM "tab" AS "t1" WHERE EXISTS (SELECT * FROM "tab" AS "t2" WHERE ("t2"."col2" = "t1"."col1"))
349360
350361-}
351362type family Query_
squeal-postgresql/src/Squeal/PostgreSQL/Tutorial.hsdeleted−39
@@ -1,39 +0,0 @@
1−{-|
2−Module: Squeal.PostgreSQL.Tutorial
3−Description: Squeal tutorial module
4−Copyright: (c) Eitan Chatav, 2019
5−Maintainer: eitan@morphism.tech
6−Stability: experimental
7−
8−== `P` records
9−
10−A `P` record is an ad-hoc, anonymous record constructed
11−as a tuple of `P`s, a datatype from `Generics.SOP.Record`, like so:
12−
13−>>> type Rec = (P ("foo" ::: Double), P ("bar" ::: Char))
14−
15−Let's see what the image of `Rec` is under the `RowPG` type family.
16−
17−>>> :kind! RowPG Rec
18−RowPG Rec :: [(Symbol, NullityType)]
19−= '[ '("foo", 'NotNull 'PGfloat8), "bar" ::: 'NotNull ('PGchar 1)]
20−
21−`P` records are ad-hoc, anonymous records so unlike Haskell records
22−you don't have to define them outside of their use site, for instance
23−in the row type parameter of a `Query_` type family.
24−
25−>>> :{
26−let
27− query :: Query_ schemas () (P ("foo" ::: Double))
28− query = values_ (1 `as` #foo)
29−in printSQL query
30−:}
31−SELECT * FROM (VALUES (1)) AS t ("foo")
32−
33−You can even mix `P` records with normal Haskell records, which is very
34−useful for creating entity types, Haskell records with associated ids.
35−
36−>>> data Row = Row {foo :: Double, bar :: Char} deriving (GHC.Generic)
37−-}
38−
39−module Squeal.PostgreSQL.Tutorial where