@@ -39,9 +39,9 @@ module Squeal.PostgreSQL.Schema
39 , ColumnType
39 , ColumnType
40 , ColumnsType
40 , ColumnsType
41 , RelationType
41 , RelationType
42− , RelationProduct
42+ , RelationsType
43 , TableType
43 , TableType
44− , SchemaType
44+ , TablesType
45 , Grouping (..)
45 , Grouping (..)
46 -- * Constraints
46 -- * Constraints
@@ -77,11 +77,9 @@ module Squeal.PostgreSQL.Schema
77 , SameFields
77 , SameFields
78 -- * PostgreSQL Constraints
78 -- * PostgreSQL Constraints
80− , Unconstraint
80+ , ColumnsToRelation
81− , UnconstrainColumn
81+ , TableToColumns
82− , UnconstrainColumns
82+ , TablesToRelations
85 , ColumnConstraint (..)
83 , ColumnConstraint (..)
86 , TableConstraint (..)
84 , TableConstraint (..)
@@ -131,44 +129,74 @@ data NullityType
131 = Null PGType -- ^ @NULL@ may be present
129 = Null PGType -- ^ @NULL@ may be present
132 | NotNull PGType -- ^ @NULL@ is absent
130 | NotNull PGType -- ^ @NULL@ is absent
134−type RelationType = [(Symbol,NullityType)]
132+-- | `:=>` is a type level pair between an "constraint" and some type,
135−type RelationProduct = [(Symbol,RelationType)]
133+-- either a `ColumnConstraint` and a `NullityType` or a row of
134+-- `TableConstraint`s and a `TableType`.
135+type (:=>) constraint ty = '(constraint,ty)
138+-- | `:::` is like a promoted version of `As`, a type level pair between
139+-- an alias and some type, like a column alias and either a `ColumnType` or
140+-- `NullityType` or a table alias and either a `TableType` or a `RelationType`
141+-- or a constraint alias and a `TableConstraint`.
142+type (:::) (alias :: Symbol) ty = '(alias,ty)
145+-- | `ColumnConstraint` encodes the allowance of @DEFAULT@.
146+data ColumnConstraint
147+ = Def -- ^ @DEFAULT@ is available for inserts and updates
148+ | NoDef -- ^ @DEFAULT@ is unavailable for inserts and updates
137−-- | `ColumnType` encodes the allowance of @DEFAULT@ and the only way
150+-- | `ColumnType` encodes the allowance of @DEFAULT@ and @NULL@ and the
138−-- to generate an `Optional` `Squeal.PostgreSQL.Expression.Expression`
151+-- base `PGType` for a column.
139−-- is to use `Squeal.PostgreSQL.Expression.def`,
140−-- `Squeal.PostgreSQL.Expression.unDef` or
141−-- `Squeal.PostgreSQL.Expression.param`.
142type ColumnType = (ColumnConstraint,NullityType)
152type ColumnType = (ColumnConstraint,NullityType)
144−-- | `ColumnsType` is a kind synonym for a row of `ColumnType`s.
154+-- | `ColumnsType` is a row of `ColumnType`s.
145type ColumnsType = [(Symbol,ColumnType)]
155type ColumnsType = [(Symbol,ColumnType)]
147−type TableType = (TableConstraints,ColumnsType)
157+-- | `TableConstraint` encodes various forms of data constraints
148−type SchemaType = [(Symbol,TableType)]
158+-- of columns in a table.
162+ | PrimaryKey [Symbol]
163+ | ForeignKey [Symbol] Symbol [Symbol]
150−type family UnconstrainColumn (ty :: ColumnType) :: NullityType where
165+-- | `TableType` encodes a row of constraints on a table as well as the types
151− UnconstrainColumn (constraint :=> ty) = ty
166+-- of its columns.
167+type TableType = ([(Symbol,TableConstraint)],ColumnsType)
169+-- | `TablesType` is a row of `TableType`s, thought of as a union.
170+type TablesType = [(Symbol,TableType)]
172+-- | `RelationType` is a row of `NullityType`
173+type RelationType = [(Symbol,NullityType)]
153−type family UnconstrainColumns (columns :: ColumnsType) :: RelationType where
175+-- | `RelationsType` is a row of `RelationType`s, thought of as a product.
154− UnconstrainColumns '[] = '[]
176+type RelationsType = [(Symbol,RelationType)]
155− UnconstrainColumns (column ::: ty ': columns) =
156− column ::: UnconstrainColumn ty ': UnconstrainColumns columns
178+-- | `ColumnsToRelation` removes column constraints.
158−type family UnconstrainTable (table :: TableType) :: ColumnsType where
179+type family ColumnsToRelation (columns :: ColumnsType) :: RelationType where
159− UnconstrainTable (constraints :=> columns) = columns
180+ ColumnsToRelation '[] = '[]
181+ ColumnsToRelation (column ::: constraint :=> ty ': columns) =
182+ column ::: ty ': ColumnsToRelation columns
161−type family UnconstrainSchema (schema :: SchemaType) :: RelationProduct where
184+-- | `TableToColumns` removes table constraints.
162− UnconstrainSchema '[] = '[]
185+type family TableToColumns (table :: TableType) :: ColumnsType where
163− UnconstrainSchema (tab ::: constraints :=> columns ': tables) =
186+ TableToColumns (constraints :=> columns) = columns
164− tab ::: UnconstrainColumns columns ': UnconstrainSchema tables
187+
188+-- | `TablesToRelations` removes both table and column constraints.
189+type family TablesToRelations (tables :: TablesType) :: RelationsType where
190+ TablesToRelations '[] = '[]
191+ TablesToRelations (alias ::: constraint :=> columns ': tables) =
192+ alias ::: ColumnsToRelation columns ': TablesToRelations tables
166-- | `Grouping` is an auxiliary namespace, created by
194-- | `Grouping` is an auxiliary namespace, created by
167-- @GROUP BY@ clauses (`Squeal.PostgreSQL.Query.group`), and used
195-- @GROUP BY@ clauses (`Squeal.PostgreSQL.Query.group`), and used
168-- for typesafe aggregation
196-- for typesafe aggregation
169data Grouping
197data Grouping
170− = Ungrouped
198+ = Ungrouped -- ^ no aggregation permitted
171− | Grouped [(Symbol,Symbol)]
199+ | Grouped [(Symbol,Symbol)] -- ^ aggregation required for any column which is not grouped
173-- | `PGNum` is a constraint on `PGType` whose
201-- | `PGNum` is a constraint on `PGType` whose
174-- `Squeal.PostgreSQL.Expression.Expression`s have a `Num` constraint.
202-- `Squeal.PostgreSQL.Expression.Expression`s have a `Num` constraint.
@@ -186,12 +214,6 @@ type PGFloating ty = In ty '[ 'PGfloat4, 'PGfloat8, 'PGnumeric]
186-- `Squeal.PostgreSQL.Expression.mod_` functions.
214-- `Squeal.PostgreSQL.Expression.mod_` functions.
187type PGIntegral ty = In ty '[ 'PGint2, 'PGint4, 'PGint8]
215type PGIntegral ty = In ty '[ 'PGint2, 'PGint4, 'PGint8]
189−-- | `:::` is like a promoted version of `As`, a type level pair between
190−-- an alias and some type, usually a column alias and a `ColumnType` or
191−-- a table alias and a `ColumnsType`.
192−type (:::) (alias :: Symbol) (ty :: polykind) = '(alias,ty)
195-- | `Alias`es are proxies for a type level string or `Symbol`
217-- | `Alias`es are proxies for a type level string or `Symbol`
196-- and have an `IsLabel` instance so that with @-XOverloadedLabels@
218-- and have an `IsLabel` instance so that with @-XOverloadedLabels@
@@ -227,7 +249,7 @@ deriving instance Ord (expression ty)
227 => Ord (Aliased expression (alias ::: ty))
249 => Ord (Aliased expression (alias ::: ty))
228instance KnownSymbol alias
250instance KnownSymbol alias
229 => IsLabel alias (expression ty -> Aliased expression (alias ::: ty))
251 => IsLabel alias (expression ty -> Aliased expression (alias ::: ty))
230− where fromLabel = \ expression -> expression `As` Alias @alias
252+ where fromLabel expression = expression `As` Alias @alias
232-- | >>> let renderMaybe = fromString . maybe "Nothing" (const "Just")
254-- | >>> let renderMaybe = fromString . maybe "Nothing" (const "Just")
233-- >>> renderAliasedAs renderMaybe (Just (3::Int) `As` #an_int)
255-- >>> renderAliasedAs renderMaybe (Just (3::Int) `As` #an_int)
@@ -290,10 +312,10 @@ type family NullifyColumns (columns :: RelationType) :: RelationType where
290 NullifyColumns (column ::: ty ': columns) =
312 NullifyColumns (column ::: ty ': columns) =
291 column ::: NullifyType ty ': NullifyColumns columns
313 column ::: NullifyType ty ': NullifyColumns columns
293−-- | `NullifyTables` is an idempotent that nullifies a `RelationProduct`
315+-- | `NullifyTables` is an idempotent that nullifies a `RelationsType`
294-- used to nullify the left or right hand side of an outer join
316-- used to nullify the left or right hand side of an outer join
295-- in a `Squeal.PostgreSQL.Query.FromClause`.
317-- in a `Squeal.PostgreSQL.Query.FromClause`.
296−type family NullifyTables (tables :: RelationProduct) :: RelationProduct where
318+type family NullifyTables (tables :: RelationsType) :: RelationsType where
297 NullifyTables '[] = '[]
319 NullifyTables '[] = '[]
298 NullifyTables (table ::: columns ': tables) =
320 NullifyTables (table ::: columns ': tables) =
299 table ::: NullifyColumns columns ': NullifyTables tables
321 table ::: NullifyColumns columns ': NullifyTables tables
@@ -373,21 +395,7 @@ type family SameFields
374 = AllZip SameField fields columns
396 = AllZip SameField fields columns
376−type (:=>) (constraints :: constraint) ty = '(constraints,ty)
379−data ColumnConstraint
386− | PrimaryKey [Symbol]
387− | ForeignKey [Symbol] Symbol [Symbol]
389−type TableConstraints = [(Symbol,TableConstraint)]
390−type Unconstraint = ('[] :: TableConstraints)
398+-- type Unconstraint = ('[] :: [(Symbol,TableConstraint)])
392type family Aliases xs where
400type family Aliases xs where
393 Aliases '[] = '[]
401 Aliases '[] = '[]