on dev help sign in
remove P
7cc86fbEitan Chatav
squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+8−2
@@ -116,6 +116,13 @@ may be referenced using positional
116Haskell record or a generalized record using tuples of `P` types and normal Haskell
116Haskell record or a generalized record using tuples of `P` types and normal Haskell
117records, whose entries will be targeted using overloaded labels.
117records, whose entries will be targeted using overloaded labels.
118
118
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+
119simple insert:
126simple insert:
120
127
121>>> type Columns = '["col1" ::: 'NoDef :=> 'Null 'PGint4, "col2" ::: 'Def :=> 'NotNull 'PGint4]
128>>> type Columns = '["col1" ::: 'NoDef :=> 'Null 'PGint4, "col2" ::: 'Def :=> 'NotNull 'PGint4]
@@ -196,8 +203,7 @@ delete:
196
203
197>>> :{
204>>> :{
198let
205let
199− manipulation :: Manipulation_ (Public Schema) ()
206+ manipulation :: Manipulation_ (Public Schema) () (Row Int32 Int32)
200− (P ("col1" ::: Int32), P ("col2" ::: Int32))
201 manipulation = deleteFrom #tab NoUsing (#col1 .== #col2) (Returning Star)
207 manipulation = deleteFrom #tab NoUsing (#col1 .== #col2) (Returning Star)
202in printSQL manipulation
208in printSQL manipulation
203:}
209:}
squeal-postgresql/src/Squeal/PostgreSQL/Migration.hs+2−3
@@ -173,7 +173,6 @@ import Squeal.PostgreSQL.Expression.Time
173import Squeal.PostgreSQL.Expression.Type
173import Squeal.PostgreSQL.Expression.Type
174import Squeal.PostgreSQL.List
174import Squeal.PostgreSQL.List
175import Squeal.PostgreSQL.Manipulation
175import Squeal.PostgreSQL.Manipulation
176−import Squeal.PostgreSQL.PG
177import Squeal.PostgreSQL.PQ
176import Squeal.PostgreSQL.PQ
178import Squeal.PostgreSQL.Query
177import Squeal.PostgreSQL.Query
179import Squeal.PostgreSQL.Schema
178import Squeal.PostgreSQL.Schema
@@ -362,8 +361,8 @@ deleteMigration = deleteFrom_ #schema_migrations (#name .== param @1)
362-- | Selects a `Migration` from the `MigrationsTable`, returning
361-- | Selects a `Migration` from the `MigrationsTable`, returning
363-- the time at which it was inserted.
362-- the time at which it was inserted.
364selectMigration
363selectMigration
365− :: Query_ MigrationsSchemas (Only Text) (P ("executed_at" ::: UTCTime))
364+ :: Query_ MigrationsSchemas (Only Text) (Only UTCTime)
366−selectMigration = select_ #executed_at
365+selectMigration = select_ (#executed_at `as` #fromOnly)
367 $ from (table (#schema_migrations))
366 $ from (table (#schema_migrations))
368 & where_ (#name .== param @1)
367 & where_ (#name .== param @1)
369
368
squeal-postgresql/src/Squeal/PostgreSQL/PG.hs−24
@@ -79,7 +79,6 @@ import qualified Generics.SOP.Record as SOP
79import qualified Generics.SOP.Type.Metadata as Type
79import qualified Generics.SOP.Type.Metadata as Type
80
80
81import Squeal.PostgreSQL.Alias
81import Squeal.PostgreSQL.Alias
82−import Squeal.PostgreSQL.List
83import Squeal.PostgreSQL.Schema
82import Squeal.PostgreSQL.Schema
84
83
85-- $setup
84-- $setup
@@ -175,31 +174,8 @@ have `SOP.Generic` and `SOP.HasDatatypeInfo` instances;
175>>> :kind! RowPG Person
174>>> :kind! RowPG Person
176RowPG Person :: [(Symbol, NullityType)]
175RowPG Person :: [(Symbol, NullityType)]
177= '["name" ::: 'NotNull 'PGtext, "age" ::: 'NotNull 'PGint4]
176= '["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]
193-}
177-}
194type family RowPG (hask :: Type) :: RowType where
178type 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]
203 RowPG hask = RowOf (SOP.RecordCodeOf hask)
179 RowPG hask = RowOf (SOP.RecordCodeOf hask)
204
180
205-- | `RowOf` applies `NullPG` to the fields of a list.
181-- | `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.
145
145
146Let's see some examples of queries.
146Let's see some examples of queries.
147
147
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+
148simple query:
155simple query:
149
156
150>>> type Columns = '["col1" ::: 'NoDef :=> 'NotNull 'PGint4, "col2" ::: 'NoDef :=> 'NotNull 'PGint4]
157>>> type Columns = '["col1" ::: 'NoDef :=> 'NotNull 'PGint4, "col2" ::: 'NoDef :=> 'NotNull 'PGint4]
151>>> type Schema = '["tab" ::: 'Table ('[] :=> Columns)]
158>>> type Schema = '["tab" ::: 'Table ('[] :=> Columns)]
152>>> :{
159>>> :{
153let
160let
154− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
161+ query :: Query_ (Public Schema) () (Row Int32 Int32)
155 query = select Star (from (table #tab))
162 query = select Star (from (table #tab))
156in printSQL query
163in printSQL query
157:}
164:}
@@ -161,21 +168,21 @@ restricted query:
161
168
162>>> :{
169>>> :{
163let
170let
164− query :: Query_ (Public Schema) () (Sum Int32, P ("col1" ::: Int32))
171+ query :: Query_ (Public Schema) () (Row Int32 Int32)
165 query =
172 query =
166− select_ ((#col1 + #col2) `as` #getSum :* #col1)
173+ select_ ((#col1 + #col2) `as` #col1 :* #col1 `as` #col2)
167 ( from (table #tab)
174 ( from (table #tab)
168 & where_ (#col1 .> #col2)
175 & where_ (#col1 .> #col2)
169 & where_ (#col2 .> 0) )
176 & where_ (#col2 .> 0) )
170in printSQL query
177in printSQL query
171:}
178:}
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))
173
180
174subquery:
181subquery:
175
182
176>>> :{
183>>> :{
177let
184let
178− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
185+ query :: Query_ (Public Schema) () (Row Int32 Int32)
179 query = select Star (from (subquery (select Star (from (table #tab)) `as` #sub)))
186 query = select Star (from (subquery (select Star (from (table #tab)) `as` #sub)))
180in printSQL query
187in printSQL query
181:}
188:}
@@ -185,7 +192,7 @@ limits and offsets:
185
192
186>>> :{
193>>> :{
187let
194let
188− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
195+ query :: Query_ (Public Schema) () (Row Int32 Int32)
189 query = select Star (from (table #tab) & limit 100 & offset 2 & limit 50 & offset 2)
196 query = select Star (from (table #tab) & limit 100 & offset 2 & limit 50 & offset 2)
190in printSQL query
197in printSQL query
191:}
198:}
@@ -195,7 +202,7 @@ parameterized query:
195
202
196>>> :{
203>>> :{
197let
204let
198− query :: Query_ (Public Schema) (Only Int32) (P ("col1" ::: Int32), P ("col2" ::: Int32))
205+ query :: Query_ (Public Schema) (Only Int32) (Row Int32 Int32)
199 query = select Star (from (table #tab) & where_ (#col1 .> param @1))
206 query = select Star (from (table #tab) & where_ (#col1 .> param @1))
200in printSQL query
207in printSQL query
201:}
208:}
@@ -205,21 +212,21 @@ aggregation query:
205
212
206>>> :{
213>>> :{
207let
214let
208− query :: Query_ (Public Schema) () (Sum Int32, P ("col1" ::: Int32))
215+ query :: Query_ (Public Schema) () (Row Int32 Int32)
209 query =
216 query =
210− select_ ((fromNull 0 (sum_ (All #col2))) `as` #getSum :* #col1)
217+ select_ ((fromNull 0 (sum_ (All #col2))) `as` #col1 :* #col1 `as` #col2)
211 ( from (table (#tab `as` #table1))
218 ( from (table (#tab `as` #table1))
212 & groupBy #col1
219 & groupBy #col1
213 & having (#col1 + (fromNull 0 (sum_ (Distinct #col2))) .> 1) )
220 & having (#col1 + (fromNull 0 (sum_ (Distinct #col2))) .> 1) )
214in printSQL query
221in printSQL query
215:}
222:}
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)
217
224
218sorted query:
225sorted query:
219
226
220>>> :{
227>>> :{
221let
228let
222− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
229+ query :: Query_ (Public Schema) () (Row Int32 Int32)
223 query = select Star (from (table #tab) & orderBy [#col1 & Asc])
230 query = select Star (from (table #tab) & orderBy [#col1 & Asc])
224in printSQL query
231in printSQL query
225:}
232:}
@@ -282,8 +289,10 @@ self-join:
282
289
283>>> :{
290>>> :{
284let
291let
285− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
292+ query :: Query_ (Public Schema) () (Row Int32 Int32)
293+ query = select
294+ (#t1 & DotStar)
286− query = select (#t1 & DotStar) (from (table (#tab `as` #t1) & crossJoin (table (#tab `as` #t2))))
295+ (from (table (#tab `as` #t1) & crossJoin (table (#tab `as` #t2))))
287in printSQL query
296in printSQL query
288:}
297:}
289SELECT "t1".* FROM "tab" AS "t1" CROSS JOIN "tab" AS "t2"
298SELECT "t1".* FROM "tab" AS "t1" CROSS JOIN "tab" AS "t2"
@@ -292,17 +301,19 @@ value queries:
292
301
293>>> :{
302>>> :{
294let
303let
295− query :: Query_ schemas () (P ("foo" ::: Int32), P ("bar" ::: Bool))
304+ query :: Query_ schemas () (Row String Bool)
296− query = values (1 `as` #foo :* true `as` #bar) [2 `as` #foo :* false `as` #bar]
305+ query = values
306+ ("true" `as` #col1 :* true `as` #col2)
307+ ["false" `as` #col1 :* false `as` #col2]
297in printSQL query
308in printSQL query
298:}
309:}
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")
300
311
301set operations:
312set operations:
302
313
303>>> :{
314>>> :{
304let
315let
305− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
316+ query :: Query_ (Public Schema) () (Row Int32 Int32)
306 query = select Star (from (table #tab)) `unionAll` select Star (from (table #tab))
317 query = select Star (from (table #tab)) `unionAll` select Star (from (table #tab))
307in printSQL query
318in printSQL query
308:}
319:}
@@ -312,7 +323,7 @@ with queries:
312
323
313>>> :{
324>>> :{
314let
325let
315− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("col2" ::: Int32))
326+ query :: Query_ (Public Schema) () (Row Int32 Int32)
316 query = with (
327 query = with (
317 select Star (from (table #tab)) `as` #cte1 :>>
328 select Star (from (table #tab)) `as` #cte1 :>>
318 select Star (from (common #cte1)) `as` #cte2
329 select Star (from (common #cte1)) `as` #cte2
@@ -325,27 +336,27 @@ window function queries
325
336
326>>> :{
337>>> :{
327let
338let
328− query :: Query_ (Public Schema) () (P ("col1" ::: Int32), P ("rank" ::: Int64))
339+ query :: Query_ (Public Schema) () (Row Int32 Int64)
329 query = select
340 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])))
331 (from (table #tab))
342 (from (table #tab))
332in printSQL query
343in printSQL query
333:}
344:}
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"
335
346
336correlated subqueries
347correlated subqueries
337
348
338>>> :{
349>>> :{
339let
350let
340− query :: Query_ (Public Schema) () (P ("col1" ::: Int32))
351+ query :: Query_ (Public Schema) () (Only Int32)
341 query =
352 query =
342− select #col1 (from (table (#tab `as` #t1))
353+ select (#col1 `as` #fromOnly) (from (table (#tab `as` #t1))
343 & where_ (exists (
354 & where_ (exists (
344 select Star (from (table (#tab `as` #t2))
355 select Star (from (table (#tab `as` #t2))
345 & where_ (#t2 ! #col2 .== #t1 ! #col1)))))
356 & where_ (#t2 ! #col2 .== #t1 ! #col1)))))
346in printSQL query
357in printSQL query
347:}
358:}
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"))
349
360
350-}
361-}
351type family Query_
362type 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