@@ -39,9 +39,9 @@ module Squeal.PostgreSQL.Schema
3939 , ColumnType
4040 , ColumnsType
4141 , RelationType
42− , RelationProduct
42+ , RelationsType
4343 , TableType
44− , SchemaType
44+ , TablesType
4545 , Grouping (..)
4646 -- * Constraints
4747 , PGNum
@@ -77,11 +77,9 @@ module Squeal.PostgreSQL.Schema
7777 , SameFields
7878 -- * PostgreSQL Constraints
7979 , (:=>)
80− , Unconstraint
81− , UnconstrainColumn
82− , UnconstrainColumns
83− , UnconstrainTable
84− , UnconstrainSchema
80+ , ColumnsToRelation
81+ , TableToColumns
82+ , TablesToRelations
8583 , ColumnConstraint (..)
8684 , TableConstraint (..)
8785 , Aliases
@@ -131,44 +129,74 @@ data NullityType
131129 = Null PGType -- ^ @NULL@ may be present
132130 | NotNull PGType -- ^ @NULL@ is absent
133131
134−type RelationType = [(Symbol,NullityType)]
135−type RelationProduct = [(Symbol,RelationType)]
132+-- | `:=>` is a type level pair between an "constraint" and some type,
133+-- either a `ColumnConstraint` and a `NullityType` or a row of
134+-- `TableConstraint`s and a `TableType`.
135+type (:=>) constraint ty = '(constraint,ty)
136+infixr 7 :=>
137+
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)
143+infixr 6 :::
144+
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
136149
137−-- | `ColumnType` encodes the allowance of @DEFAULT@ and the only way
138−-- to generate an `Optional` `Squeal.PostgreSQL.Expression.Expression`
139−-- is to use `Squeal.PostgreSQL.Expression.def`,
140−-- `Squeal.PostgreSQL.Expression.unDef` or
141−-- `Squeal.PostgreSQL.Expression.param`.
150+-- | `ColumnType` encodes the allowance of @DEFAULT@ and @NULL@ and the
151+-- base `PGType` for a column.
142152type ColumnType = (ColumnConstraint,NullityType)
143153
144−-- | `ColumnsType` is a kind synonym for a row of `ColumnType`s.
154+-- | `ColumnsType` is a row of `ColumnType`s.
145155type ColumnsType = [(Symbol,ColumnType)]
146156
147−type TableType = (TableConstraints,ColumnsType)
148−type SchemaType = [(Symbol,TableType)]
157+-- | `TableConstraint` encodes various forms of data constraints
158+-- of columns in a table.
159+data TableConstraint
160+ = Check
161+ | Unique [Symbol]
162+ | PrimaryKey [Symbol]
163+ | ForeignKey [Symbol] Symbol [Symbol]
149164
150−type family UnconstrainColumn (ty :: ColumnType) :: NullityType where
151− UnconstrainColumn (constraint :=> ty) = ty
165+-- | `TableType` encodes a row of constraints on a table as well as the types
166+-- of its columns.
167+type TableType = ([(Symbol,TableConstraint)],ColumnsType)
168+
169+-- | `TablesType` is a row of `TableType`s, thought of as a union.
170+type TablesType = [(Symbol,TableType)]
171+
172+-- | `RelationType` is a row of `NullityType`
173+type RelationType = [(Symbol,NullityType)]
152174
153−type family UnconstrainColumns (columns :: ColumnsType) :: RelationType where
154− UnconstrainColumns '[] = '[]
155− UnconstrainColumns (column ::: ty ': columns) =
156− column ::: UnconstrainColumn ty ': UnconstrainColumns columns
175+-- | `RelationsType` is a row of `RelationType`s, thought of as a product.
176+type RelationsType = [(Symbol,RelationType)]
157177
158−type family UnconstrainTable (table :: TableType) :: ColumnsType where
159− UnconstrainTable (constraints :=> columns) = columns
178+-- | `ColumnsToRelation` removes column constraints.
179+type family ColumnsToRelation (columns :: ColumnsType) :: RelationType where
180+ ColumnsToRelation '[] = '[]
181+ ColumnsToRelation (column ::: constraint :=> ty ': columns) =
182+ column ::: ty ': ColumnsToRelation columns
160183
161−type family UnconstrainSchema (schema :: SchemaType) :: RelationProduct where
162− UnconstrainSchema '[] = '[]
163− UnconstrainSchema (tab ::: constraints :=> columns ': tables) =
164− tab ::: UnconstrainColumns columns ': UnconstrainSchema tables
184+-- | `TableToColumns` removes table constraints.
185+type family TableToColumns (table :: TableType) :: ColumnsType where
186+ TableToColumns (constraints :=> columns) = columns
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
165193
166194-- | `Grouping` is an auxiliary namespace, created by
167195-- @GROUP BY@ clauses (`Squeal.PostgreSQL.Query.group`), and used
168196-- for typesafe aggregation
169197data Grouping
170− = Ungrouped
171− | Grouped [(Symbol,Symbol)]
198+ = Ungrouped -- ^ no aggregation permitted
199+ | Grouped [(Symbol,Symbol)] -- ^ aggregation required for any column which is not grouped
172200
173201-- | `PGNum` is a constraint on `PGType` whose
174202-- `Squeal.PostgreSQL.Expression.Expression`s have a `Num` constraint.
@@ -186,12 +214,6 @@ type PGFloating ty = In ty '[ 'PGfloat4, 'PGfloat8, 'PGnumeric]
186214-- `Squeal.PostgreSQL.Expression.mod_` functions.
187215type PGIntegral ty = In ty '[ 'PGint2, 'PGint4, 'PGint8]
188216
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)
193−infixr 6 :::
194−
195217-- | `Alias`es are proxies for a type level string or `Symbol`
196218-- and have an `IsLabel` instance so that with @-XOverloadedLabels@
197219--
@@ -227,7 +249,7 @@ deriving instance Ord (expression ty)
227249 => Ord (Aliased expression (alias ::: ty))
228250instance KnownSymbol alias
229251 => IsLabel alias (expression ty -> Aliased expression (alias ::: ty))
230− where fromLabel = \ expression -> expression `As` Alias @alias
252+ where fromLabel expression = expression `As` Alias @alias
231253
232254-- | >>> let renderMaybe = fromString . maybe "Nothing" (const "Just")
233255-- >>> renderAliasedAs renderMaybe (Just (3::Int) `As` #an_int)
@@ -290,10 +312,10 @@ type family NullifyColumns (columns :: RelationType) :: RelationType where
290312 NullifyColumns (column ::: ty ': columns) =
291313 column ::: NullifyType ty ': NullifyColumns columns
292314
293−-- | `NullifyTables` is an idempotent that nullifies a `RelationProduct`
315+-- | `NullifyTables` is an idempotent that nullifies a `RelationsType`
294316-- used to nullify the left or right hand side of an outer join
295317-- in a `Squeal.PostgreSQL.Query.FromClause`.
296−type family NullifyTables (tables :: RelationProduct) :: RelationProduct where
318+type family NullifyTables (tables :: RelationsType) :: RelationsType where
297319 NullifyTables '[] = '[]
298320 NullifyTables (table ::: columns ': tables) =
299321 table ::: NullifyColumns columns ': NullifyTables tables
@@ -373,21 +395,7 @@ type family SameFields
373395 columns
374396 = AllZip SameField fields columns
375397
376−type (:=>) (constraints :: constraint) ty = '(constraints,ty)
377−infixr 7 :=>
378−
379−data ColumnConstraint
380− = Def
381− | NoDef
382−
383−data TableConstraint
384− = Check
385− | Unique [Symbol]
386− | PrimaryKey [Symbol]
387− | ForeignKey [Symbol] Symbol [Symbol]
388−
389−type TableConstraints = [(Symbol,TableConstraint)]
390−type Unconstraint = ('[] :: TableConstraints)
398+-- type Unconstraint = ('[] :: [(Symbol,TableConstraint)])
391399
392400type family Aliases xs where
393401 Aliases '[] = '[]