on dev help sign in
schema work
commit43ad64569b3cf833c188f9ae0496712e0380b398 authorEitan Chatav <eitan.chatav@gmail.com> dateTue 4 Sep 2018, 17:20 (8 years ago) parentc51650e
3 files changed+224−156
squeal-postgresql/src/Squeal/PostgreSQL/Expression.hs+29−29 squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+41−32 squeal-postgresql/src/Squeal/PostgreSQL/Schema.hs+154−95
squeal-postgresql/src/Squeal/PostgreSQL/Expression.hs+29−29
@@ -555,7 +555,7 @@ unsafeVariadicFunction
555555unsafeVariadicFunction fun x = UnsafeExpression $
556556 fun <> parenthesized (commaSeparated (hcollapse (hmap (K . renderExpression) x)))
557557
558−instance PGNum ty
558+instance ty `In` PGNum
559559 => Num (Expression schema from grouping params (nullity ty)) where
560560 (+) = unsafeBinaryOp "+"
561561 (-) = unsafeBinaryOp "-"
@@ -567,12 +567,12 @@ instance PGNum ty
567567 . fromString
568568 . show
569569
570−instance (PGNum ty, PGFloating ty) => Fractional
570+instance (ty `In` PGNum, ty `In` PGFloating) => Fractional
571571 (Expression schema from grouping params (nullity ty)) where
572572 (/) = unsafeBinaryOp "/"
573573 fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
574574
575−instance (PGNum ty, PGFloating ty) => Floating
575+instance (ty `In` PGNum, ty `In` PGFloating) => Floating
576576 (Expression schema from grouping params (nullity ty)) where
577577 pi = UnsafeExpression "pi()"
578578 exp = unsafeFunction "exp"
@@ -602,7 +602,7 @@ instance (PGNum ty, PGFloating ty) => Floating
602602-- :}
603603-- atan2(pi(), 2)
604604atan2_
605− :: PGFloating float
605+ :: float `In` PGFloating
606606 => Expression schema from grouping params (nullity float)
607607 -- ^ numerator
608608 -> Expression schema from grouping params (nullity float)
@@ -636,7 +636,7 @@ cast ty x = UnsafeExpression $ parenthesized $
636636-- :}
637637-- (5 / 2)
638638quot_
639− :: PGIntegral int
639+ :: int `In` PGIntegral
640640 => Expression schema from grouping params (nullity int)
641641 -- ^ numerator
642642 -> Expression schema from grouping params (nullity int)
@@ -654,7 +654,7 @@ quot_ = unsafeBinaryOp "/"
654654-- :}
655655-- (5 % 2)
656656rem_
657− :: PGIntegral int
657+ :: int `In` PGIntegral
658658 => Expression schema from grouping params (nullity int)
659659 -- ^ numerator
660660 -> Expression schema from grouping params (nullity int)
@@ -670,7 +670,7 @@ rem_ = unsafeBinaryOp "%"
670670-- :}
671671-- trunc(pi())
672672trunc
673− :: PGFloating frac
673+ :: frac `In` PGFloating
674674 => Expression schema from grouping params (nullity frac)
675675 -- ^ fractional number
676676 -> Expression schema from grouping params (nullity frac)
@@ -684,7 +684,7 @@ trunc = unsafeFunction "trunc"
684684-- :}
685685-- round(pi())
686686round_
687− :: PGFloating frac
687+ :: frac `In` PGFloating
688688 => Expression schema from grouping params (nullity frac)
689689 -- ^ fractional number
690690 -> Expression schema from grouping params (nullity frac)
@@ -698,7 +698,7 @@ round_ = unsafeFunction "round"
698698-- :}
699699-- ceiling(pi())
700700ceiling_
701− :: PGFloating frac
701+ :: frac `In` PGFloating
702702 => Expression schema from grouping params (nullity frac)
703703 -- ^ fractional number
704704 -> Expression schema from grouping params (nullity frac)
@@ -955,7 +955,7 @@ Table 9.44: json and jsonb operators
955955
956956-- | Get JSON value (object field or array element) at a key.
957957(.->)
958− :: (PGjson_ json, PGjsonKey key)
958+ :: (json `In` PGJsonType, key `In` PGJsonKey)
959959 => Expression schema from grouping params (nullity json)
960960 -> Expression schema from grouping params (nullity key)
961961 -> Expression schema from grouping params ('Null json)
@@ -964,7 +964,7 @@ infixl 8 .->
964964
965965-- | Get JSON value (object field or array element) at a key, as text.
966966(.->>)
967− :: (PGjson_ json, PGjsonKey key)
967+ :: (json `In` PGJsonType, key `In` PGJsonKey)
968968 => Expression schema from grouping params (nullity json)
969969 -> Expression schema from grouping params (nullity key)
970970 -> Expression schema from grouping params ('Null 'PGtext)
@@ -973,7 +973,7 @@ infixl 8 .->>
973973
974974-- | Get JSON value at a specified path.
975975(.#>)
976− :: (PGjson_ json, PGtextArray "(.#>)" path)
976+ :: (json `In` PGJsonType, PGTextArray "(.#>)" path)
977977 => Expression schema from grouping params (nullity json)
978978 -> Expression schema from grouping params (nullity path)
979979 -> Expression schema from grouping params ('Null json)
@@ -982,7 +982,7 @@ infixl 8 .#>
982982
983983-- | Get JSON value at a specified path as text.
984984(.#>>)
985− :: (PGjson_ json, PGtextArray "(.#>>)" path)
985+ :: (json `In` PGJsonType, PGTextArray "(.#>>)" path)
986986 => Expression schema from grouping params (nullity json)
987987 -> Expression schema from grouping params (nullity path)
988988 -> Expression schema from grouping params ('Null 'PGtext)
@@ -1061,7 +1061,7 @@ infixl 6 .-.
10611061-- | Delete the field or element with specified path (for JSON arrays, negative
10621062-- integers count from the end)
10631063(#-.)
1064− :: PGtextArray "(#-.)" arrayty
1064+ :: PGTextArray "(#-.)" arrayty
10651065 => Expression schema from grouping params (nullity 'PGjsonb)
10661066 -> Expression schema from grouping params (nullity arrayty)
10671067 -> Expression schema from grouping params (nullity 'PGjsonb)
@@ -1111,7 +1111,7 @@ toJsonb = unsafeFunction "to_jsonb"
11111111-- | Returns the array as a JSON array. A PostgreSQL multidimensional array
11121112-- becomes a JSON array of arrays.
11131113arrayToJson
1114− :: PGarray "arrayToJson" arr
1114+ :: PGArray "arrayToJson" arr
11151115 => Expression schema from grouping params (nullity arr)
11161116 -> Expression schema from grouping params (nullity 'PGjson)
11171117arrayToJson = unsafeFunction "array_to_json"
@@ -1178,7 +1178,7 @@ jsonbBuildObject
11781178-- taken as alternating key/value pairs, or two dimensions such that each inner
11791179-- array has exactly two elements, which are taken as a key/value pair.
11801180jsonObject
1181− :: PGarrayOf "jsonObject" arr ('NotNull 'PGtext)
1181+ :: PGArrayOf "jsonObject" arr ('NotNull 'PGtext)
11821182 => Expression schema from grouping params (nullity arr)
11831183 -> Expression schema from grouping params (nullity 'PGjson)
11841184jsonObject = unsafeFunction "json_object"
@@ -1188,7 +1188,7 @@ jsonObject = unsafeFunction "json_object"
11881188-- taken as alternating key/value pairs, or two dimensions such that each inner
11891189-- array has exactly two elements, which are taken as a key/value pair.
11901190jsonbObject
1191− :: PGarrayOf "jsonbObject" arr ('NotNull 'PGtext)
1191+ :: PGArrayOf "jsonbObject" arr ('NotNull 'PGtext)
11921192 => Expression schema from grouping params (nullity arr)
11931193 -> Expression schema from grouping params (nullity 'PGjsonb)
11941194jsonbObject = unsafeFunction "jsonb_object"
@@ -1196,8 +1196,8 @@ jsonbObject = unsafeFunction "jsonb_object"
11961196-- | This is an alternate form of 'jsonObject' that takes two arrays; one for
11971197-- keys and one for values, that are zipped pairwise to create a JSON object.
11981198jsonZipObject
1199− :: ( PGarrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1200− , PGarrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
1199+ :: ( PGArrayOf "jsonZipObject" keysArray ('NotNull 'PGtext)
1200+ , PGArrayOf "jsonZipObject" valuesArray ('NotNull 'PGtext))
12011201 => Expression schema from grouping params (nullity keysArray)
12021202 -> Expression schema from grouping params (nullity valuesArray)
12031203 -> Expression schema from grouping params (nullity 'PGjson)
@@ -1208,8 +1208,8 @@ jsonZipObject ks vs =
12081208-- keys and one for values, that are zipped pairwise to create a binary JSON
12091209-- object.
12101210jsonbZipObject
1211− :: ( PGarrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1212− , PGarrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
1211+ :: ( PGArrayOf "jsonbZipObject" keysArray ('NotNull 'PGtext)
1212+ , PGArrayOf "jsonbZipObject" valuesArray ('NotNull 'PGtext))
12131213 => Expression schema from grouping params (nullity keysArray)
12141214 -> Expression schema from grouping params (nullity valuesArray)
12151215 -> Expression schema from grouping params (nullity 'PGjsonb)
@@ -1320,7 +1320,7 @@ jsonbStripNulls = unsafeFunction "jsonb_strip_nulls"
13201320-- operators, negative integers that appear in path count from the end of JSON
13211321-- arrays.
13221322jsonbSet
1323− :: PGtextArray "jsonbSet" arr
1323+ :: PGTextArray "jsonbSet" arr
13241324 => Expression schema from grouping params (nullity 'PGjsonb)
13251325 -> Expression schema from grouping params (nullity arr)
13261326 -> Expression schema from grouping params (nullity 'PGjsonb)
@@ -1339,7 +1339,7 @@ jsonbSet tgt path val createMissing = case createMissing of
13391339-- exist. As with the path orientated operators, negative integers that appear
13401340-- in path count from the end of JSON arrays.
13411341jsonbInsert
1342− :: PGtextArray "jsonbInsert" arr
1342+ :: PGTextArray "jsonbInsert" arr
13431343 => Expression schema from grouping params (nullity 'PGjsonb)
13441344 -> Expression schema from grouping params (nullity arr)
13451345 -> Expression schema from grouping params (nullity 'PGjsonb)
@@ -1383,7 +1383,7 @@ unsafeAggregateDistinct fun x = UnsafeExpression $ mconcat
13831383-- :}
13841384-- sum("col")
13851385sum_
1386− :: PGNum ty
1386+ :: ty `In` PGNum
13871387 => Expression schema from 'Ungrouped params (nullity ty)
13881388 -- ^ what to sum
13891389 -> Expression schema from ('Grouped bys) params (nullity ty)
@@ -1397,7 +1397,7 @@ sum_ = unsafeAggregate "sum"
13971397-- :}
13981398-- sum(DISTINCT "col")
13991399sumDistinct
1400− :: PGNum ty
1400+ :: ty `In` PGNum
14011401 => Expression schema from 'Ungrouped params (nullity ty)
14021402 -- ^ what to sum
14031403 -> Expression schema from ('Grouped bys) params (nullity ty)
@@ -1428,7 +1428,7 @@ instance PGAvg 'PGinterval 'PGinterval
14281428-- :}
14291429-- bit_and("col")
14301430bitAnd
1431− :: PGIntegral int
1431+ :: int `In` PGIntegral
14321432 => Expression schema from 'Ungrouped params (nullity int)
14331433 -- ^ what to aggregate
14341434 -> Expression schema from ('Grouped bys) params (nullity int)
@@ -1442,7 +1442,7 @@ bitAnd = unsafeAggregate "bit_and"
14421442-- :}
14431443-- bit_or("col")
14441444bitOr
1445− :: PGIntegral int
1445+ :: int `In` PGIntegral
14461446 => Expression schema from 'Ungrouped params (nullity int)
14471447 -- ^ what to aggregate
14481448 -> Expression schema from ('Grouped bys) params (nullity int)
@@ -1456,7 +1456,7 @@ bitOr = unsafeAggregate "bit_or"
14561456-- :}
14571457-- bit_and(DISTINCT "col")
14581458bitAndDistinct
1459− :: PGIntegral int
1459+ :: int `In` PGIntegral
14601460 => Expression schema from 'Ungrouped params (nullity int)
14611461 -- ^ what to aggregate
14621462 -> Expression schema from ('Grouped bys) params (nullity int)
@@ -1470,7 +1470,7 @@ bitAndDistinct = unsafeAggregateDistinct "bit_and"
14701470-- :}
14711471-- bit_or(DISTINCT "col")
14721472bitOrDistinct
1473− :: PGIntegral int
1473+ :: int `In` PGIntegral
14741474 => Expression schema from 'Ungrouped params (nullity int)
14751475 -- ^ what to aggregate
14761476 -> Expression schema from ('Grouped bys) params (nullity int)
squeal-postgresql/src/Squeal/PostgreSQL/Manipulation.hs+41−32
@@ -232,13 +232,14 @@ insertRows
232232 :: ( SOP.SListI columns
233233 , SOP.SListI results
234234 , Has tab schema ('Table table)
235+ , row ~ TableToRow table
235236 , columns ~ TableToColumns table )
236237 => Alias tab -- ^ table to insert into
237238 -> NP (Aliased (ColumnValue schema '[] params)) columns -- ^ row to insert
238239 -> [NP (Aliased (ColumnValue schema '[] params)) columns] -- ^ more rows to insert
239− -> ConflictClause schema columns params
240+ -> ConflictClause schema table params
240241 -- ^ what to do in case of constraint conflict
241− -> ReturningClause schema columns params results -- ^ results to return
242+ -> ReturningClause schema params row results -- ^ results to return
242243 -> Manipulation schema params results
243244insertRows tab rw rws conflict returning = UnsafeManipulation $
244245 "INSERT" <+> "INTO" <+> renderAlias tab
@@ -262,12 +263,13 @@ insertRow
262263 :: ( SOP.SListI columns
263264 , SOP.SListI results
264265 , Has tab schema ('Table table)
266+ , row ~ TableToRow table
265267 , columns ~ TableToColumns table )
266268 => Alias tab -- ^ table to insert into
267269 -> NP (Aliased (ColumnValue schema '[] params)) columns -- ^ row to insert
268− -> ConflictClause schema columns params
270+ -> ConflictClause schema table params
269271 -- ^ what to do in case of constraint conflict
270− -> ReturningClause schema columns params results -- ^ results to return
272+ -> ReturningClause schema params row results -- ^ results to return
271273 -> Manipulation schema params results
272274insertRow tab rw = insertRows tab rw []
273275
@@ -298,12 +300,13 @@ insertQuery
298300 :: ( SOP.SListI columns
299301 , SOP.SListI results
300302 , Has tab schema ('Table table)
303+ , row ~ TableToRow table
301304 , columns ~ TableToColumns table )
302305 => Alias tab -- ^ table to insert into
303− -> Query schema params (ColumnsToRow columns)
304− -> ConflictClause schema columns params
306+ -> Query schema params (TableToRow table)
307+ -> ConflictClause schema table params
305308 -- ^ what to do in case of constraint conflict
306− -> ReturningClause schema columns params results -- ^ results to return
309+ -> ReturningClause schema params row results -- ^ results to return
307310 -> Manipulation schema params results
308311insertQuery tab query conflict returning = UnsafeManipulation $
309312 "INSERT" <+> "INTO" <+> renderAlias tab
@@ -317,7 +320,7 @@ insertQuery_
317320 , Has tab schema ('Table table)
318321 , columns ~ TableToColumns table )
319322 => Alias tab -- ^ table to insert into
320− -> Query schema params (ColumnsToRow columns)
323+ -> Query schema params (TableToRow table)
321324 -> Manipulation schema params '[]
322325insertQuery_ tab query =
323326 insertQuery tab query OnConflictDoRaise (Returning Nil)
@@ -351,17 +354,15 @@ data ColumnValue
351354-- values are desired.
352355data ReturningClause
353356 (schema :: SchemaType)
354− (columns :: ColumnsType)
355357 (params :: [NullityType])
356− (results :: RowType)
358+ (row0 :: RowType)
359+ (row1 :: RowType)
357360 where
358361 ReturningStar
359− :: results ~ ColumnsToRow columns
360− => ReturningClause schema columns params results
362+ :: ReturningClause schema params row row
361363 Returning
362− :: rel ~ ColumnsToRow columns
363− => NP (Aliased (Expression schema '[table ::: rel] 'Ungrouped params)) results
364− -> ReturningClause schema columns params results
364+ :: NP (Aliased (Expression schema '[table ::: row0] 'Ungrouped params)) row1
365+ -> ReturningClause schema params row0 row1
365366
366367-- | Render a `ReturningClause`.
367368renderReturningClause
@@ -379,18 +380,22 @@ renderReturningClause = \case
379380-- `OnConflictDoNothing` simply avoids inserting a row.
380381-- `OnConflictDoUpdate` updates the existing row that conflicts with the row
381382-- proposed for insertion.
382−data ConflictClause (schema :: SchemaType) (columns :: ColumnsType) params where
383− OnConflictDoRaise :: ConflictClause schema columns params
384− OnConflictDoNothing :: ConflictClause schema columns params
385− OnConflictDoUpdate
386− :: NP (Aliased (ColumnValue schema (ColumnsToRow columns) params)) columns
387− -> [Condition schema '[table ::: ColumnsToRow columns] 'Ungrouped params]
388− -> ConflictClause schema columns params
383+data ConflictClause
384+ (schema :: SchemaType)
385+ (table :: TableType)
386+ (params :: [NullityType]) where
387+ OnConflictDoRaise :: ConflictClause schema table params
388+ OnConflictDoNothing :: ConflictClause schema table params
389+ OnConflictDoUpdate
390+ :: (row ~ TableToRow table, columns ~ TableToColumns table)
391+ => NP (Aliased (ColumnValue schema row params)) columns
392+ -> [Condition schema '[t ::: row] 'Ungrouped params]
393+ -> ConflictClause schema table params
389394
390395-- | Render a `ConflictClause`.
391396renderConflictClause
392− :: SOP.SListI columns
393− => ConflictClause schema columns params
397+ :: SOP.SListI (TableToColumns table)
398+ => ConflictClause schema table params
394399 -> ByteString
395400renderConflictClause = \case
396401 OnConflictDoRaise -> ""
@@ -422,13 +427,14 @@ update
422427 :: ( SOP.SListI columns
423428 , SOP.SListI results
424429 , Has tab schema ('Table table)
430+ , row ~ TableToRow table
425431 , columns ~ TableToColumns table )
426432 => Alias tab -- ^ table to update
427− -> NP (Aliased (ColumnValue schema (ColumnsToRow columns) params)) columns
433+ -> NP (Aliased (ColumnValue schema row params)) columns
428434 -- ^ modified values to replace old values
429− -> Condition schema '[tab ::: ColumnsToRow columns] 'Ungrouped params
435+ -> (forall t. Condition schema '[t ::: row] 'Ungrouped params)
430436 -- ^ condition under which to perform update on a row
431− -> ReturningClause schema columns params results -- ^ results to return
437+ -> ReturningClause schema params row results -- ^ results to return
432438 -> Manipulation schema params results
433439update tab columns wh returning = UnsafeManipulation $
434440 "UPDATE"
@@ -452,11 +458,12 @@ update tab columns wh returning = UnsafeManipulation $
452458update_
453459 :: ( SOP.SListI columns
454460 , Has tab schema ('Table table)
461+ , row ~ TableToRow table
455462 , columns ~ TableToColumns table )
456463 => Alias tab -- ^ table to update
457− -> NP (Aliased (ColumnValue schema (ColumnsToRow columns) params)) columns
464+ -> NP (Aliased (ColumnValue schema row params)) columns
458465 -- ^ modified values to replace old values
459− -> Condition schema '[tab ::: ColumnsToRow columns] 'Ungrouped params
466+ -> (forall t. Condition schema '[t ::: row] 'Ungrouped params)
460467 -- ^ condition under which to perform update on a row
461468 -> Manipulation schema params '[]
462469update_ tab columns wh = update tab columns wh (Returning Nil)
@@ -469,11 +476,12 @@ DELETE statements
469476deleteFrom
470477 :: ( SOP.SListI results
471478 , Has tab schema ('Table table)
479+ , row ~ TableToRow table
472480 , columns ~ TableToColumns table )
473481 => Alias tab -- ^ table to delete from
474− -> Condition schema '[tab ::: ColumnsToRow columns] 'Ungrouped params
482+ -> Condition schema '[tab ::: row] 'Ungrouped params
475483 -- ^ condition under which to delete a row
476− -> ReturningClause schema columns params results -- ^ results to return
484+ -> ReturningClause schema params row results -- ^ results to return
477485 -> Manipulation schema params results
478486deleteFrom tab wh returning = UnsafeManipulation $
479487 "DELETE FROM" <+> renderAlias tab
@@ -483,9 +491,10 @@ deleteFrom tab wh returning = UnsafeManipulation $
483491-- | Delete rows returning `Nil`.
484492deleteFrom_
485493 :: ( Has tab schema ('Table table)
494+ , row ~ TableToRow table
486495 , columns ~ TableToColumns table )
487496 => Alias tab -- ^ table to delete from
488− -> Condition schema '[tab ::: ColumnsToRow columns] 'Ungrouped params
497+ -> (forall t. Condition schema '[t ::: row] 'Ungrouped params)
489498 -- ^ condition under which to delete a row
490499 -> Manipulation schema params '[]
491500deleteFrom_ tab wh = deleteFrom tab wh (Returning Nil)
squeal-postgresql/src/Squeal/PostgreSQL/Schema.hs+154−95
@@ -34,17 +34,24 @@ it defines an embedding of Haskell types into Postgres types.
3434#-}
3535
3636module Squeal.PostgreSQL.Schema
37− ( -- * Types
37+ ( -- * Postgres Types
3838 PGType (..)
39− , HasOid (..)
4039 , NullityType (..)
41− , ColumnType
42− -- * Tables
43− , ColumnsType
4440 , RowType
4541 , FromType
42+ -- * Haskell to Postgres Types
43+ , PG
44+ , NullPG
45+ , TuplePG
46+ , RowPG
47+ , Json (..)
48+ , Jsonb (..)
49+ , Composite (..)
50+ , Enumerated (..)
51+ -- * Schema Types
52+ , ColumnType
53+ , ColumnsType
4654 , TableType
47− -- * Schema
4855 , SchemumType (..)
4956 , SchemaType
5057 -- * Constraints
@@ -61,7 +68,6 @@ module Squeal.PostgreSQL.Schema
6168 , Aliased (As)
6269 , Aliasable (as)
6370 , renderAliasedAs
64− , AliasesOf
6571 , Has
6672 , HasUnique
6773 , HasAll
@@ -73,57 +79,45 @@ module Squeal.PostgreSQL.Schema
7379 , PGlabel (..)
7480 , renderLabel
7581 , renderLabels
82+ , LabelsPG
7683 -- * Grouping
7784 , Grouping (..)
7885 , GroupedBy
79− -- * Type Families
80− , Join
86+ -- * Aligned lists
87+ , AlignedList (..)
88+ , single
89+ -- * Data Definitions
8190 , Create
8291 , Drop
8392 , Alter
8493 , Rename
94+ , DropIfConstraintsInvolve
95+ -- * Lists
96+ , Join
8597 , Elem
8698 , In
8799 , Length
100+ -- * Type Classifications
101+ , HasOid (..)
88102 , PGNum
89103 , PGIntegral
90104 , PGFloating
91105 , PGTypeOf
92− , PGarrayOf
93− , PGarray
94− , PGtextArray
106+ , PGArrayOf
107+ , PGArray
108+ , PGTextArray
109+ , PGJsonType
110+ , PGJsonKey
95111 , SamePGType
96112 , AllNotNull
97113 , NotAllNull
114+ -- * Nullifications
98115 , NullifyType
99116 , NullifyRow
100117 , NullifyFrom
101− , ColumnsToRow
118+ -- * Table Conversions
102119 , TableToColumns
103120 , TableToRow
104− , ConstraintInvolves
105− , DropIfConstraintsInvolve
106− -- ** JSON support
107− , PGjson_
108− , PGjsonKey
109− -- * Immersion
110− , PG
111− , Json (..)
112− , Jsonb (..)
113− , Composite (..)
114− , Enumerated (..)
115− , NullPG
116− , TuplePG
117− , LabelsPG
118− , RowPG
119− , RowOf
120− , FieldPG
121− , ConstructorsOf
122− , ConstructorNameOf
123− , ConstructorNamesOf
124− -- * Aligned lists
125− , AlignedList (..)
126− , single
127121 ) where
128122
129123import Control.Category
@@ -305,19 +299,24 @@ type family Uniquely
305299-- :}
306300type TableType = (TableConstraints,ColumnsType)
307301
308−-- | `RowType` is a row of `NullityType`
309−--
310−-- >>> :{
311−-- type family PersonRelation :: RowType where
312−-- PersonRelation =
313−-- '[ "name" ::: 'NotNull 'PGtext
314−-- , "age" ::: 'NotNull 'PGint4
315−-- , "dateOfBirth" ::: 'Null 'PGdate
316−-- ]
317−-- :}
302+{- | A `RowType` is a row of `NullityType`. They correspond to Haskell
303+record types by means of `RowPG` and are used in many places.
304+
305+>>> :{
306+type family PersonRow :: RowType where
307+ PersonRow =
308+ '[ "name" ::: 'NotNull 'PGtext
309+ , "age" ::: 'NotNull 'PGint4
310+ , "dateOfBirth" ::: 'Null 'PGdate
311+ ]
312+:}
313+-}
318314type RowType = [(Symbol,NullityType)]
319315
320−-- | `FromType` is a row of `RowType`s, thought of as a product.
316+{- | `FromType` is a row of `RowType`s. It can be thought of as
317+a product, or horizontal gluing and is used in `Squeal.PostgreSQL.Query.FromClause`s
318+and `Squeal.PostgreSQL.Query.TableExpression`s.
319+-}
321320type FromType = [(Symbol,RowType)]
322321
323322-- | `ColumnsToRow` removes column constraints.
@@ -435,11 +434,6 @@ renderAliasedAs
435434renderAliasedAs render (expression `As` alias) =
436435 render expression <> " AS " <> renderAlias alias
437436
438−-- | `AliasesOf` retains the AliasesOf in a row.
439−type family AliasesOf aliaseds where
440− AliasesOf '[] = '[]
441− AliasesOf (alias ::: ty ': tys) = alias ': AliasesOf tys
442−
443437-- | @HasUnique alias fields field@ is a constraint that proves that
444438-- @fields@ is a singleton of @alias ::: field@.
445439type HasUnique alias fields field = fields ~ '[alias ::: field]
@@ -486,21 +480,15 @@ type family Elem x xs where
486480-- | @In x xs@ is a constraint that proves that @x@ is in @xs@.
487481type family In x xs :: Constraint where In x xs = Elem x xs ~ 'True
488482
489−-- | `PGNum` is a constraint on `PGType` whose
490−-- `Squeal.PostgreSQL.Expression.Expression`s have a `Num` constraint.
491−type PGNum ty =
492− In ty '[ 'PGint2, 'PGint4, 'PGint8, 'PGnumeric, 'PGfloat4, 'PGfloat8]
483+-- | Numeric Postgres types.
484+type PGNum =
485+ '[ 'PGint2, 'PGint4, 'PGint8, 'PGnumeric, 'PGfloat4, 'PGfloat8]
493486
494−-- | `PGFloating` is a constraint on `PGType` whose
495−-- `Squeal.PostgreSQL.Expression.Expression`s
496−-- have `Fractional` and `Floating` constraints.
497−type PGFloating ty = In ty '[ 'PGfloat4, 'PGfloat8, 'PGnumeric]
487+-- | Floating Postgres types.
488+type PGFloating = '[ 'PGfloat4, 'PGfloat8, 'PGnumeric]
498489
499−-- | `PGIntegral` is a constraint on `PGType` whose
500−-- `Squeal.PostgreSQL.Expression.Expression`s
501−-- have `Squeal.PostgreSQL.Expression.div_` and
502−-- `Squeal.PostgreSQL.Expression.mod_` functions.
503−type PGIntegral ty = In ty '[ 'PGint2, 'PGint4, 'PGint8]
490+-- | Integral Postgres types.
491+type PGIntegral = '[ 'PGint2, 'PGint4, 'PGint8]
504492
505493-- | Error message helper for displaying unavailable\/unknown\/placeholder type
506494-- variables whose kind is known.
@@ -511,27 +499,27 @@ type ErrPGfixarrayOf t = ErrArrayOf ('ShowType 'PGfixarray :<>: 'Text " " :<>: P
511499type ErrPGvararrayOf t = ErrArrayOf ('ShowType 'PGvararray) t
512500
513501-- | Ensure a type is a valid array type.
514−type family PGarray name arr :: Constraint where
515− PGarray name ('PGvararray x) = ()
516− PGarray name ('PGfixarray n x) = ()
517− PGarray name val = TypeError
518− ('Text name :<>: 'Text ": Unsatisfied PGarray constraint. Expected either: "
502+type family PGArray name arr :: Constraint where
503+ PGArray name ('PGvararray x) = ()
504+ PGArray name ('PGfixarray n x) = ()
505+ PGArray name val = TypeError
506+ ('Text name :<>: 'Text ": Unsatisfied PGArray constraint. Expected either: "
519507 :$$: 'Text " • " :<>: ErrPGvararrayOf (Placeholder PGType)
520508 :$$: 'Text " • " :<>: ErrPGfixarrayOf (Placeholder PGType)
521509 :$$: 'Text "But got: " :<>: 'ShowType val)
522510
523511-- | Ensure a type is a valid array type with a specific element type.
524−type family PGarrayOf name arr ty :: Constraint where
525− PGarrayOf name ('PGvararray x) ty = x ~ ty
526− PGarrayOf name ('PGfixarray n x) ty = x ~ ty
527− PGarrayOf name val ty = TypeError
528− ( 'Text name :<>: 'Text "Unsatisfied PGarrayOf constraint. Expected either: "
512+type family PGArrayOf name arr ty :: Constraint where
513+ PGArrayOf name ('PGvararray x) ty = x ~ ty
514+ PGArrayOf name ('PGfixarray n x) ty = x ~ ty
515+ PGArrayOf name val ty = TypeError
516+ ( 'Text name :<>: 'Text "Unsatisfied PGArrayOf constraint. Expected either: "
529517 :$$: 'Text " • " :<>: ErrPGvararrayOf ( 'ShowType ty )
530518 :$$: 'Text " • " :<>: ErrPGfixarrayOf ( 'ShowType ty )
531519 :$$: 'Text "But got: " :<>: 'ShowType val)
532520
533521-- | Ensure a type is a valid array type whose elements are text.
534−type PGtextArray name arr = PGarrayOf name arr ('NotNull 'PGtext)
522+type PGTextArray name arr = PGArrayOf name arr ('NotNull 'PGtext)
535523
536524-- | `PGTypeOf` forgets about @NULL@ and any column constraints.
537525type family PGTypeOf (ty :: NullityType) :: PGType where
@@ -628,6 +616,12 @@ type family DropIfConstraintsInvolve column constraints where
628616 (DropIfConstraintsInvolve column constraints)
629617 (alias ::: constraint ': DropIfConstraintsInvolve column constraints)
630618
619+{- | Calculate the `Length` of a type level list
620+
621+>>> :kind! Length '[Char,String,Bool,Double]
622+Length '[Char,String,Bool,Double] :: Nat
623+= 4
624+-}
631625type family Length (xs :: [k]) :: Nat where
632626 Length (x : xs) = 1 + Length xs
633627 Length '[] = 0
@@ -639,8 +633,28 @@ data SchemumType
639633 | View RowType
640634 | Typedef PGType
641635
642−-- | The schema of a database consists of a list of aliased,
643−-- user-defined `SchemumType`s.
636+{- | The schema of a database consists of a list of aliased,
637+user-defined `SchemumType`s.
638+
639+>>> :{
640+type family Schema :: SchemaType where
641+ Schema =
642+ '[ "users" ::: 'Table (
643+ '[ "pk_users" ::: 'PrimaryKey '["id"] ] :=>
644+ '[ "id" ::: 'Def :=> 'NotNull 'PGint4
645+ , "name" ::: 'NoDef :=> 'NotNull 'PGtext
646+ ])
647+ , "emails" ::: 'Table (
648+ '[ "pk_emails" ::: 'PrimaryKey '["id"]
649+ , "fk_user_id" ::: 'ForeignKey '["user_id"] "users" '["id"]
650+ ] :=>
651+ '[ "id" ::: 'Def :=> 'NotNull 'PGint4
652+ , "user_id" ::: 'NoDef :=> 'NotNull 'PGint4
653+ , "email" ::: 'NoDef :=> 'Null 'PGtext
654+ ])
655+ ]
656+:}
657+-}
644658type SchemaType = [(Symbol,SchemumType)]
645659
646660-- | `IsPGlabel` looks very much like the `IsLabel` class. Whereas
@@ -664,12 +678,16 @@ renderLabels
664678renderLabels = hcollapse
665679 . hcmap (Proxy @KnownSymbol) (K . renderLabel)
666680
667−-- | The `PG` type family embeds a subset of Haskell types
668−-- as Postgres basic types.
669−--
670−-- >>> :kind! PG LocalTime
671−-- PG LocalTime :: PGType
672−-- = 'PGtimestamp
681+{- | The `PG` type family embeds a subset of Haskell types
682+as Postgres types. As an open type family, `PG` is extensible.
683+
684+>>> :kind! PG LocalTime
685+PG LocalTime :: PGType
686+= 'PGtimestamp
687+
688+>>> newtype MyDouble = My Double
689+>>> type instance PG MyDouble = 'PGfloat8
690+-}
673691type family PG (hask :: Type) :: PGType
674692type instance PG Bool = 'PGbool
675693type instance PG Int16 = 'PGint2
@@ -716,28 +734,53 @@ type instance PG (hask, hask, hask, hask, hask, hask, hask, hask, hask, hask)
716734type instance PG (Composite hask) = 'PGcomposite (RowPG hask)
717735type instance PG (Enumerated hask) = 'PGenum (LabelsPG hask)
718736
737+{- | The `Json` newtype is an indication that the Haskell
738+type it's applied to should be stored as `PGjson`.
739+-}
719740newtype Json hask = Json {getJson :: hask}
720741 deriving (Eq, Ord, Show, Read, GHC.Generic)
742+
743+{- | The `Jsonb` newtype is an indication that the Haskell
744+type it's applied to should be stored as `PGjsonb`.
745+-}
721746newtype Jsonb hask = Jsonb {getJsonb :: hask}
722747 deriving (Eq, Ord, Show, Read, GHC.Generic)
748+
749+{- | The `Composite` newtype is an indication that the Haskell
750+type it's applied to should be stored as a `PGcomposite`.
751+-}
723752newtype Composite record = Composite {getComposite :: record}
724753 deriving (Eq, Ord, Show, Read, GHC.Generic)
754+
755+{- | The `Enumerated` newtype is an indication that the Haskell
756+type it's applied to should be stored as `PGenum`.
757+-}
725758newtype Enumerated enum = Enumerated {getEnumerated :: enum}
726759 deriving (Eq, Ord, Show, Read, GHC.Generic)
727760
728−-- | The `LabelsPG` type family calculates the constructors of a
729−-- Haskell enum type.
730−--
731−-- >>> data Schwarma = Beef | Lamb | Chicken deriving GHC.Generic
732−-- >>> instance Generic Schwarma
733−-- >>> instance HasDatatypeInfo Schwarma
734−-- >>> :kind! LabelsPG Schwarma
735−-- LabelsPG Schwarma :: [Type.ConstructorName]
736−-- = '["Beef", "Lamb", "Chicken"]
761+{-| The `LabelsPG` type family calculates the constructors of a
762+Haskell enum type.
763+
764+>>> data Schwarma = Beef | Lamb | Chicken deriving GHC.Generic
765+>>> instance Generic Schwarma
766+>>> instance HasDatatypeInfo Schwarma
767+>>> :kind! LabelsPG Schwarma
768+LabelsPG Schwarma :: [Type.ConstructorName]
769+= '["Beef", "Lamb", "Chicken"]
770+-}
737771type family LabelsPG (hask :: Type) :: [Type.ConstructorName] where
738772 LabelsPG hask =
739773 ConstructorNamesOf (ConstructorsOf (DatatypeInfoOf hask))
740774
775+{- | `RowPG` turns a Haskell record type into a `RowType`.
776+
777+>>> data Person = Person { name :: Text, age :: Int32 } deriving GHC.Generic
778+>>> instance Generic Person
779+>>> instance HasDatatypeInfo Person
780+>>> :kind! RowPG Person
781+RowPG Person :: [(Symbol, NullityType)]
782+= '["name" ::: 'NotNull 'PGtext, "age" ::: 'NotNull 'PGint4]
783+-}
741784type family RowPG (hask :: Type) :: RowType where
742785 RowPG hask = RowOf (RecordCodeOf hask)
743786
@@ -748,10 +791,26 @@ type family RowOf (fields :: [(Symbol, Type)]) :: RowType where
748791type family FieldPG (field :: (Symbol, Type)) :: (Symbol, NullityType) where
749792 FieldPG (field ::: hask) = field ::: NullPG hask
750793
794+{- | `NullPG` turns a Haskell type into a `NullityType`.
795+
796+>>> :kind! NullPG Double
797+NullPG Double :: NullityType
798+= 'NotNull 'PGfloat8
799+>>> :kind! NullPG (Maybe Double)
800+NullPG (Maybe Double) :: NullityType
801+= 'Null 'PGfloat8
802+-}
751803type family NullPG (hask :: Type) :: NullityType where
752804 NullPG (Maybe hask) = 'Null (PG hask)
753805 NullPG hask = 'NotNull (PG hask)
754806
807+{- | `TuplePG` turns a Haskell tuple type (including record types) into
808+the corresponding list of `NullityType`s.
809+
810+>>> :kind! TuplePG (Double, Maybe Char)
811+TuplePG (Double, Maybe Char) :: [NullityType]
812+= '['NotNull 'PGfloat8, 'Null ('PGchar 1)]
813+-}
755814type family TuplePG (hask :: Type) :: [NullityType] where
756815 TuplePG hask = TupleOf (TupleCodeOf hask (Code hask))
757816
@@ -800,10 +859,10 @@ type family ConstructorNamesOf (constructors :: [Type.ConstructorInfo])
800859 ConstructorNameOf constructor ': ConstructorNamesOf constructors
801860
802861-- | Is a type a valid JSON key?
803−type PGjsonKey key = key `In` '[ 'PGint2, 'PGint4, 'PGtext ]
862+type PGJsonKey = '[ 'PGint2, 'PGint4, 'PGtext ]
804863
805864-- | Is a type a valid JSON type?
806−type PGjson_ json = json `In` '[ 'PGjson, 'PGjsonb ]
865+type PGJsonType = '[ 'PGjson, 'PGjsonb ]
807866
808867-- | An `AlignedList` is a type-aligned list or free category.
809868data AlignedList p x0 x1 where