@@ -43,21 +43,29 @@ module Squeal.PostgreSQL.Schema
4343 , TableType
4444 , TablesType
4545 , Grouping (..)
46− -- * Constraints
47− , PGNum
48− , PGIntegral
49− , PGFloating
50− -- * Aliases
46+ -- * PostgreSQL Constraints
47+ , (:=>)
48+ , ColumnsToRelation
49+ , TableToColumns
50+ , TablesToRelations
51+ , ColumnConstraint (..)
52+ , TableConstraint (..)
53+ -- * AliasesOf
5154 , (:::)
5255 , Alias (Alias)
5356 , renderAlias
5457 , Aliased (As)
5558 , renderAliasedAs
59+ , AliasesOf
60+ , Has
61+ , HasUnique
5662 , IsLabel (..)
5763 , IsTableColumn (..)
5864 -- * Type Families
5965 , In
60− , HasUnique
66+ , PGNum
67+ , PGIntegral
68+ , PGFloating
6169 , PGTypeOf
6270 , SameTypes
6371 , AllNotNull
@@ -75,15 +83,6 @@ module Squeal.PostgreSQL.Schema
7583 -- * Generics
7684 , SameField
7785 , SameFields
78− -- * PostgreSQL Constraints
79− , (:=>)
80− , ColumnsToRelation
81− , TableToColumns
82− , TablesToRelations
83− , ColumnConstraint (..)
84− , TableConstraint (..)
85− , Aliases
86− , Has
8786 ) where
8887
8988import Control.DeepSeq
@@ -198,22 +197,6 @@ data Grouping
198197 = Ungrouped -- ^ no aggregation permitted
199198 | Grouped [(Symbol,Symbol)] -- ^ aggregation required for any column which is not grouped
200199
201−-- | `PGNum` is a constraint on `PGType` whose
202−-- `Squeal.PostgreSQL.Expression.Expression`s have a `Num` constraint.
203−type PGNum ty =
204− In ty '[ 'PGint2, 'PGint4, 'PGint8, 'PGnumeric, 'PGfloat4, 'PGfloat8]
205−
206−-- | `PGFloating` is a constraint on `PGType` whose
207−-- `Squeal.PostgreSQL.Expression.Expression`s
208−-- have `Fractional` and `Floating` constraints.
209−type PGFloating ty = In ty '[ 'PGfloat4, 'PGfloat8, 'PGnumeric]
210−
211−-- | `PGIntegral` is a constraint on `PGType` whose
212−-- `Squeal.PostgreSQL.Expression.Expression`s
213−-- have `Squeal.PostgreSQL.Expression.div_` and
214−-- `Squeal.PostgreSQL.Expression.mod_` functions.
215−type PGIntegral ty = In ty '[ 'PGint2, 'PGint4, 'PGint8]
216−
217200-- | `Alias`es are proxies for a type level string or `Symbol`
218201-- and have an `IsLabel` instance so that with @-XOverloadedLabels@
219202--
@@ -225,8 +208,8 @@ data Alias (alias :: Symbol) = Alias
225208instance alias1 ~ alias2 => IsLabel alias1 (Alias alias2) where
226209 fromLabel = Alias
227210
228−-- | >>> renderAlias #alias
229−-- "alias"
211+-- | >>> renderAlias #jimbob
212+-- "jimbob"
230213renderAlias :: KnownSymbol alias => Alias alias -> ByteString
231214renderAlias = fromString . symbolVal
232215
@@ -261,6 +244,25 @@ renderAliasedAs
261244renderAliasedAs render (expression `As` alias) =
262245 render expression <> " AS " <> renderAlias alias
263246
247+-- | `AliasesOf` retains the AliasesOf in a row.
248+type family AliasesOf aliaseds where
249+ AliasesOf '[] = '[]
250+ AliasesOf (alias ::: ty ': tys) = alias ': AliasesOf tys
251+
252+-- | @HasUnique alias xs x@ is a constraint that proves that @xs@ is a singleton
253+-- of @alias ::: x@.
254+type HasUnique alias xs x = xs ~ '[alias ::: x]
255+
256+-- | @Has alias xs x@ is a constraint that proves that @xs@ has a field
257+-- of @alias ::: x@.
258+class KnownSymbol alias =>
259+ Has (alias :: Symbol) (fields :: [(Symbol,kind)]) (field :: kind)
260+ | alias fields -> field where
261+instance {-# OVERLAPPING #-} KnownSymbol alias
262+ => Has alias (alias ::: field ': fields) field
263+instance {-# OVERLAPPABLE #-} (KnownSymbol alias, Has alias fields field)
264+ => Has alias (field' ': fields) field
265+
264266-- | Analagous to `IsLabel`, the constraint
265267-- `IsTableColumn` defines `!` for a column alias qualified
266268-- by a table alias.
@@ -274,9 +276,21 @@ type family In x xs :: Constraint where
274276 In x (x ': xs) = ()
275277 In x (y ': xs) = In x xs
276278
277−-- | @HasUnique alias xs x@ is a constraint that proves that @xs@ is a singleton
278−-- of @alias ::: x@.
279−type HasUnique alias xs x = xs ~ '[alias ::: x]
279+-- | `PGNum` is a constraint on `PGType` whose
280+-- `Squeal.PostgreSQL.Expression.Expression`s have a `Num` constraint.
281+type PGNum ty =
282+ In ty '[ 'PGint2, 'PGint4, 'PGint8, 'PGnumeric, 'PGfloat4, 'PGfloat8]
283+
284+-- | `PGFloating` is a constraint on `PGType` whose
285+-- `Squeal.PostgreSQL.Expression.Expression`s
286+-- have `Fractional` and `Floating` constraints.
287+type PGFloating ty = In ty '[ 'PGfloat4, 'PGfloat8, 'PGnumeric]
288+
289+-- | `PGIntegral` is a constraint on `PGType` whose
290+-- `Squeal.PostgreSQL.Expression.Expression`s
291+-- have `Squeal.PostgreSQL.Expression.div_` and
292+-- `Squeal.PostgreSQL.Expression.mod_` functions.
293+type PGIntegral ty = In ty '[ 'PGint2, 'PGint4, 'PGint8]
280294
281295-- | `PGTypeOf` forgets about @NULL@ and any column constraints.
282296type family PGTypeOf (ty :: NullityType) :: PGType where
@@ -382,7 +396,7 @@ instance field ~ column => SameField ('Type.FieldInfo field) (column ::: ty)
382396
383397-- | A `SameFields` constraint proves that a
384398-- `Generics.SOP.Type.Metadata.DatatypeInfo` of a record type has the same
385−-- field names as the column aliases of a `ColumnsType`.
399+-- field names as the column AliasesOf of a `ColumnsType`.
386400type family SameFields
387401 (datatypeInfo :: Type.DatatypeInfo) (columns :: RelationType)
388402 :: Constraint where
@@ -394,17 +408,3 @@ type family SameFields
394408 ('Type.Newtype _module _datatype ('Type.Record _constructor fields))
395409 columns
396410 = AllZip SameField fields columns
397−
398−-- type Unconstraint = ('[] :: [(Symbol,TableConstraint)])
399−
400−type family Aliases xs where
401− Aliases '[] = '[]
402− Aliases ((alias ::: x) ': xs) = alias ': Aliases xs
403−
404−class KnownSymbol alias =>
405− Has (alias :: Symbol) (fields :: [(Symbol,kind)]) (field :: kind)
406− | alias fields -> field where
407−instance {-# OVERLAPPING #-} KnownSymbol alias
408− => Has alias (alias ::: field ': fields) field
409−instance {-# OVERLAPPABLE #-} (KnownSymbol alias, Has alias fields field)
410− => Has alias (field' ': fields) field