Copyright | (c) Eitan Chatav 2017 |
---|---|
Maintainer | [email protected] |
Stability | experimental |
Safe Haskell | None |
Language | Haskell2010 |
Squeal.PostgreSQL.Schema
Description
A type-level DSL for kinds of PostgreSQL types, constraints, and aliases.
- data PGType
- = PGbool
- | PGint2
- | PGint4
- | PGint8
- | PGnumeric
- | PGfloat4
- | PGfloat8
- | PGchar Nat
- | PGvarchar Nat
- | PGtext
- | PGbytea
- | PGtimestamp
- | PGtimestamptz
- | PGdate
- | PGtime
- | PGtimetz
- | PGinterval
- | PGuuid
- | PGinet
- | PGjson
- | PGjsonb
- | PGvararray PGType
- | PGfixarray Nat PGType
- | UnsafePGType Symbol
- class HasOid (ty :: PGType) where
- data NullityType
- type ColumnType = (ColumnConstraint, NullityType)
- type ColumnsType = [(Symbol, ColumnType)]
- type RelationType = [(Symbol, NullityType)]
- type family NilRelation :: RelationType where ...
- type RelationsType = [(Symbol, RelationType)]
- type TableType = (TableConstraints, ColumnsType)
- type TablesType = [(Symbol, TableType)]
- type family NilTables :: TablesType where ...
- data Grouping
- class (KnownSymbol relation, KnownSymbol column) => GroupedBy relation column bys
- type (:=>) constraint ty = '(constraint, ty)
- data ColumnConstraint
- data TableConstraint
- = Check [Symbol]
- | Unique [Symbol]
- | PrimaryKey [Symbol]
- | ForeignKey [Symbol] Symbol [Symbol]
- type TableConstraints = [(Symbol, TableConstraint)]
- type family NilTableConstraints :: TableConstraints where ...
- type (:::) (alias :: Symbol) ty = '(alias, ty)
- data Alias (alias :: Symbol) = Alias
- renderAlias :: KnownSymbol alias => Alias alias -> ByteString
- data Aliased expression aliased where
- As :: KnownSymbol alias => expression ty -> Alias alias -> Aliased expression (alias ::: ty)
- renderAliasedAs :: (forall ty. expression ty -> ByteString) -> Aliased expression aliased -> ByteString
- type family AliasesOf aliaseds where ...
- class KnownSymbol alias => Has (alias :: Symbol) (fields :: [(Symbol, kind)]) (field :: kind) | alias fields -> field
- type HasUnique alias fields field = fields ~ '[alias ::: field]
- class IsLabel (x :: Symbol) a where
- class IsQualified table column expression where
- type family Join xs ys where ...
- type family Create alias x xs where ...
- type family Drop alias xs where ...
- type family Alter alias xs x where ...
- type family Rename alias0 alias1 xs where ...
- type family Elem x xs where ...
- type family In x xs :: Constraint where ...
- type PGNum ty = In ty '[PGint2, PGint4, PGint8, PGnumeric, PGfloat4, PGfloat8]
- type PGIntegral ty = In ty '[PGint2, PGint4, PGint8]
- type PGFloating ty = In ty '[PGfloat4, PGfloat8, PGnumeric]
- type family PGTypeOf (ty :: NullityType) :: PGType where ...
- type family SameTypes (columns0 :: ColumnsType) (columns1 :: ColumnsType) :: Constraint where ...
- type family AllNotNull (columns :: ColumnsType) :: Constraint where ...
- type family NotAllNull (columns :: ColumnsType) :: Constraint where ...
- type family NullifyType (ty :: NullityType) :: NullityType where ...
- type family NullifyRelation (columns :: RelationType) :: RelationType where ...
- type family NullifyRelations (tables :: RelationsType) :: RelationsType where ...
- type family ColumnsToRelation (columns :: ColumnsType) :: RelationType where ...
- type family RelationToColumns (relation :: RelationType) :: ColumnsType where ...
- type family TableToColumns (table :: TableType) :: ColumnsType where ...
- type family TablesToRelations (tables :: TablesType) :: RelationsType where ...
- type family RelationsToTables (tables :: RelationsType) :: TablesType where ...
- type family ConstraintInvolves column constraint where ...
- type family DropIfConstraintsInvolve column constraints where ...
- class SameField (fieldInfo :: FieldInfo) (fieldty :: (Symbol, NullityType))
- type family SameFields (datatypeInfo :: DatatypeInfo) (columns :: RelationType) :: Constraint where ...
Types
PGType
is the promoted datakind of PostgreSQL types.
>>>
import Squeal.PostgreSQL.Schema
>>>
:kind 'PGbool
'PGbool :: PGType
Constructors
PGbool | logical Boolean (true/false) |
PGint2 | signed two-byte integer |
PGint4 | signed four-byte integer |
PGint8 | signed eight-byte integer |
PGnumeric | arbitrary precision numeric type |
PGfloat4 | single precision floating-point number (4 bytes) |
PGfloat8 | double precision floating-point number (8 bytes) |
PGchar Nat | fixed-length character string |
PGvarchar Nat | variable-length character string |
PGtext | variable-length character string |
PGbytea | binary data ("byte array") |
PGtimestamp | date and time (no time zone) |
PGtimestamptz | date and time, including time zone |
PGdate | calendar date (year, month, day) |
PGtime | time of day (no time zone) |
PGtimetz | time of day, including time zone |
PGinterval | time span |
PGuuid | universally unique identifier |
PGinet | IPv4 or IPv6 host address |
PGjson | textual JSON data |
PGjsonb | binary JSON data, decomposed |
PGvararray PGType | variable length array |
PGfixarray Nat PGType | fixed length array |
UnsafePGType Symbol | an escape hatch for unsupported PostgreSQL types |
class HasOid (ty :: PGType) where Source #
The object identifier of a PGType
.
>>>
:set -XTypeApplications
>>>
oid @'PGbool
16
Minimal complete definition
Instances
data NullityType Source #
NullityType
encodes the potential presence or definite absence of a
NULL
allowing operations which are sensitive to such to be well typed.
>>>
:kind 'Null 'PGint4
'Null 'PGint4 :: NullityType>>>
:kind 'NotNull ('PGvarchar 50)
'NotNull ('PGvarchar 50) :: NullityType
Instances
Category TablesType Definition # | |
(KnownNat n, HasParameter ((-) n 1) params ty) => HasParameter n ((:) NullityType ty' params) ty Source # | |
PGTyped (PGTypeOf ty1) => HasParameter 1 ((:) NullityType ty1 tys) ty1 Source # | |
(~) FieldName field column => SameField (FieldInfo field) ((:::) NullityType column ty) Source # | |
FromValue pg y => FromColumnValue ((:::) NullityType column (NotNull pg)) y Source # | |
FromValue pg y => FromColumnValue ((:::) NullityType column (Null pg)) (Maybe y) Source # | |
AddColumn ((:=>) ColumnConstraint NullityType Def ty) Source # | |
AddColumn ((:=>) ColumnConstraint NullityType NoDef (Null ty)) Source # | |
type ColumnType = (ColumnConstraint, NullityType) Source #
ColumnType
encodes the allowance of DEFAULT
and NULL
and the
base PGType
for a column.
>>>
:set -XTypeFamilies -XTypeInType
>>>
import GHC.TypeLits
>>>
type family IdColumn :: ColumnType where IdColumn = 'Def :=> 'NotNull 'PGint4
>>>
type family EmailColumn :: ColumnType where EmailColumn = 'NoDef :=> 'Null 'PGtext
type ColumnsType = [(Symbol, ColumnType)] Source #
ColumnsType
is a row of ColumnType
s.
>>>
:{
type family UsersColumns :: ColumnsType where UsersColumns = '[ "name" ::: 'NoDef :=> 'NotNull 'PGtext , "id" ::: 'Def :=> 'NotNull 'PGint4 ] :}
type RelationType = [(Symbol, NullityType)] Source #
RelationType
is a row of NullityType
>>>
:{
type family PersonRelation :: RelationType where PersonRelation = '[ "name" ::: 'NotNull 'PGtext , "age" ::: 'NotNull 'PGint4 , "dateOfBirth" ::: 'Null 'PGdate ] :}
type family NilRelation :: RelationType where ... Source #
A monokinded empty RelationType
.
Equations
NilRelation = '[] |
type RelationsType = [(Symbol, RelationType)] Source #
RelationsType
is a row of RelationType
s, thought of as a product.
type TableType = (TableConstraints, ColumnsType) Source #
TableType
encodes a row of constraints on a table as well as the types
of its columns.
>>>
:{
type family UsersTable :: TableType where UsersTable = '[ "pk_users" ::: 'PrimaryKey '["id"] ] :=> '[ "id" ::: 'Def :=> 'NotNull 'PGint4 , "name" ::: 'NoDef :=> 'NotNull 'PGtext ] :}
type TablesType = [(Symbol, TableType)] Source #
TablesType
is a row of TableType
s, thought of as a union.
>>>
:{
type family Schema :: TablesType where Schema = '[ "users" ::: '[ "pk_users" ::: 'PrimaryKey '["id"] ] :=> '[ "id" ::: 'Def :=> 'NotNull 'PGint4 , "name" ::: 'NoDef :=> 'NotNull 'PGtext , "vec" ::: 'NoDef :=> 'NotNull ('PGvararray 'PGint2) ] , "emails" ::: '[ "pk_emails" ::: 'PrimaryKey '["id"] , "fk_user_id" ::: 'ForeignKey '["user_id"] "users" '["id"] ] :=> '[ "id" ::: 'Def :=> 'NotNull 'PGint4 , "user_id" ::: 'NoDef :=> 'NotNull 'PGint4 , "email" ::: 'NoDef :=> 'Null 'PGtext ] ] :}
type family NilTables :: TablesType where ... Source #
A monokinded empty TablesType
.
Equations
NilTables = '[] |
Grouping
class (KnownSymbol relation, KnownSymbol column) => GroupedBy relation column bys Source #
A GroupedBy
constraint indicates that a table qualified column is
a member of the auxiliary namespace created by GROUP BY
clauses and thus,
may be called in an output Expression
without aggregating.
Instances
(KnownSymbol relation, KnownSymbol column) => GroupedBy [(k, Symbol)] relation column ((:) (k, Symbol) ((,) k Symbol table column) bys) Source # | |
(KnownSymbol relation, KnownSymbol column, GroupedBy [a] relation column bys) => GroupedBy [a] relation column ((:) a tabcol bys) Source # | |
Constraints
type (:=>) constraint ty = '(constraint, ty) infixr 7 Source #
The constraint operator, :=>
is a type level pair
between a "constraint" and some type, for use in pairing
a ColumnConstraint
with a NullityType
to produce a ColumnType
or a TableConstraints
and a ColumnsType
to produce a TableType
.
data ColumnConstraint Source #
ColumnConstraint
encodes the availability of DEFAULT
for inserts and updates.
A column can be assigned a default value.
A data Manipulation
command can also
request explicitly that a column be set to its default value,
without having to know what that value is.
Constructors
Def |
|
NoDef |
|
Instances
data TableConstraint Source #
TableConstraint
encodes various forms of data constraints
of columns in a table.
TableConstraint
s give you as much control over the data in your tables
as you wish. If a user attempts to store data in a column that would
violate a constraint, an error is raised. This applies
even if the value came from the default value definition.
Constructors
Check [Symbol] | |
Unique [Symbol] | |
PrimaryKey [Symbol] | |
ForeignKey [Symbol] Symbol [Symbol] |
Instances
type TableConstraints = [(Symbol, TableConstraint)] Source #
A TableConstraints
is a row of TableConstraint
s.
type family NilTableConstraints :: TableConstraints where ... Source #
A monokinded empty TableConstraints
.
Equations
NilTableConstraints = '[] |
Aliases
type (:::) (alias :: Symbol) ty = '(alias, ty) infixr 6 Source #
The alias operator :::
is like a promoted version of As
,
a type level pair between
an alias and some type, like a column alias and either a ColumnType
or
NullityType
or a table alias and either a TableType
or a RelationType
or a constraint alias and a TableConstraint
.
data Alias (alias :: Symbol) Source #
Alias
es are proxies for a type level string or Symbol
and have an IsLabel
instance so that with -XOverloadedLabels
>>>
:set -XOverloadedLabels
>>>
#foobar :: Alias "foobar"
Alias
Constructors
Alias |
Instances
IsQualified table column (Alias table, Alias column) Source # | |
(~) Symbol alias1 alias2 => IsLabel alias1 (Alias alias2) Source # | |
Eq (Alias alias) Source # | |
Ord (Alias alias) Source # | |
Show (Alias alias) Source # | |
Generic (Alias alias) Source # | |
NFData (Alias alias) Source # | |
type Rep (Alias alias) Source # | |
renderAlias :: KnownSymbol alias => Alias alias -> ByteString Source #
>>>
renderAlias #jimbob
"jimbob"
data Aliased expression aliased where Source #
The As
operator is used to name an expression. As
is like a demoted
version of :::
.
>>>
Just "hello" `As` #hi :: Aliased Maybe ("hi" ::: String)
As (Just "hello") Alias
Constructors
As :: KnownSymbol alias => expression ty -> Alias alias -> Aliased expression (alias ::: ty) |
renderAliasedAs :: (forall ty. expression ty -> ByteString) -> Aliased expression aliased -> ByteString Source #
>>>
let renderMaybe = fromString . maybe "Nothing" (const "Just")
>>>
renderAliasedAs renderMaybe (Just (3::Int) `As` #an_int)
"Just AS an_int"
class KnownSymbol alias => Has (alias :: Symbol) (fields :: [(Symbol, kind)]) (field :: kind) | alias fields -> field Source #
Has alias fields field
is a constraint that proves that
fields
has a field of alias ::: field
.
type HasUnique alias fields field = fields ~ '[alias ::: field] Source #
HasUnique alias fields field
is a constraint that proves that
fields
is a singleton of alias ::: field
.
class IsLabel (x :: Symbol) a where #
Minimal complete definition
Instances
(~) Symbol alias1 alias2 => IsLabel alias1 (Alias alias2) # | |
(Has TableType alias schema table, (~) RelationType relation (ColumnsToRelation (TableToColumns table))) => IsLabel alias (Table schema relation) # | |
(HasUnique [(Symbol, NullityType)] relation relations columns, Has NullityType column columns ty, GroupedBy [(Symbol, Symbol)] relation column bys) => IsLabel column (Expression relations (Grouped bys) params ty) # | |
(HasUnique [(Symbol, NullityType)] relation relations columns, Has NullityType column columns ty) => IsLabel column (Expression relations Ungrouped params ty) # | |
class IsQualified table column expression where Source #
Analagous to IsLabel
, the constraint
IsQualified
defines !
for a column alias qualified
by a table alias.
Minimal complete definition
Instances
IsQualified table column (Alias table, Alias column) Source # | |
(Has [(Symbol, NullityType)] relation relations columns, Has NullityType column columns ty, GroupedBy [(Symbol, Symbol)] relation column bys) => IsQualified relation column (Expression relations (Grouped bys) params ty) Source # | |
(Has [(Symbol, NullityType)] relation relations columns, Has NullityType column columns ty) => IsQualified relation column (Expression relations Ungrouped params ty) Source # | |
Type Families
type family Join xs ys where ... Source #
Join
is simply promoted ++
and is used in JOIN
s in
FromClause
s.
type family Create alias x xs where ... Source #
Create alias x xs
adds alias ::: x
to the end of xs
and is used in
createTable
statements and in ALTER TABLE
addColumn
.
type family Drop alias xs where ... Source #
Drop alias xs
removes the type associated with alias
in xs
and is used in dropTable
statements
and in ALTER TABLE
dropColumn
statements.
type family Alter alias xs x where ... Source #
Alter alias xs x
replaces the type associated with an alias
in xs
with the type x
and is used in alterTable
and alterColumn
.
type family Rename alias0 alias1 xs where ... Source #
Rename alias0 alias1 xs
replaces the alias alias0
by alias1
in xs
and is used in alterTableRename
and
renameColumn
.
type family In x xs :: Constraint where ... Source #
In x xs
is a constraint that proves that x
is in xs
.
type PGNum ty = In ty '[PGint2, PGint4, PGint8, PGnumeric, PGfloat4, PGfloat8] Source #
PGNum
is a constraint on PGType
whose
Expression
s have a Num
constraint.
type PGIntegral ty = In ty '[PGint2, PGint4, PGint8] Source #
PGIntegral
is a constraint on PGType
whose
Expression
s
have div_
and
mod_
functions.
type PGFloating ty = In ty '[PGfloat4, PGfloat8, PGnumeric] Source #
PGFloating
is a constraint on PGType
whose
Expression
s
have Fractional
and Floating
constraints.
type family PGTypeOf (ty :: NullityType) :: PGType where ... Source #
PGTypeOf
forgets about NULL
and any column constraints.
Equations
PGTypeOf (nullity pg) = pg |
type family SameTypes (columns0 :: ColumnsType) (columns1 :: ColumnsType) :: Constraint where ... Source #
SameTypes
is a constraint that proves two ColumnsType
s have the same
length and the same ColumnType
s.
type family AllNotNull (columns :: ColumnsType) :: Constraint where ... Source #
AllNotNull
is a constraint that proves a ColumnsType
has no NULL
s.
Equations
AllNotNull '[] = () | |
AllNotNull ((column ::: (def :=> NotNull ty)) ': columns) = AllNotNull columns |
type family NotAllNull (columns :: ColumnsType) :: Constraint where ... Source #
NotAllNull
is a constraint that proves a ColumnsType
has some
NOT NULL
.
Equations
NotAllNull ((column ::: (def :=> NotNull ty)) ': columns) = () | |
NotAllNull ((column ::: (def :=> Null ty)) ': columns) = NotAllNull columns |
type family NullifyType (ty :: NullityType) :: NullityType where ... Source #
NullifyType
is an idempotent that nullifies a ColumnType
.
Equations
NullifyType (Null ty) = Null ty | |
NullifyType (NotNull ty) = Null ty |
type family NullifyRelation (columns :: RelationType) :: RelationType where ... Source #
NullifyRelation
is an idempotent that nullifies a ColumnsType
.
Equations
NullifyRelation '[] = '[] | |
NullifyRelation ((column ::: ty) ': columns) = (column ::: NullifyType ty) ': NullifyRelation columns |
type family NullifyRelations (tables :: RelationsType) :: RelationsType where ... Source #
NullifyRelations
is an idempotent that nullifies a RelationsType
used to nullify the left or right hand side of an outer join
in a FromClause
.
Equations
NullifyRelations '[] = '[] | |
NullifyRelations ((table ::: columns) ': tables) = (table ::: NullifyRelation columns) ': NullifyRelations tables |
type family ColumnsToRelation (columns :: ColumnsType) :: RelationType where ... Source #
ColumnsToRelation
removes column constraints.
Equations
ColumnsToRelation '[] = '[] | |
ColumnsToRelation ((column ::: (constraint :=> ty)) ': columns) = (column ::: ty) ': ColumnsToRelation columns |
type family RelationToColumns (relation :: RelationType) :: ColumnsType where ... Source #
RelationToColumns
adds `NoDef
column constraints.
Equations
RelationToColumns '[] = '[] | |
RelationToColumns ((column ::: ty) ': columns) = (column ::: (NoDef :=> ty)) ': RelationToColumns columns |
type family TableToColumns (table :: TableType) :: ColumnsType where ... Source #
TableToColumns
removes table constraints.
Equations
TableToColumns (constraints :=> columns) = columns |
type family TablesToRelations (tables :: TablesType) :: RelationsType where ... Source #
TablesToRelations
removes both table and column constraints.
Equations
TablesToRelations '[] = '[] | |
TablesToRelations ((alias ::: (constraint :=> columns)) ': tables) = (alias ::: ColumnsToRelation columns) ': TablesToRelations tables |
type family RelationsToTables (tables :: RelationsType) :: TablesType where ... Source #
RelationsToTables
adds both trivial table and column constraints.
Equations
RelationsToTables '[] = '[] | |
RelationsToTables ((alias ::: columns) ': relations) = (alias ::: ('[] :=> RelationToColumns columns)) ': RelationsToTables relations |
type family ConstraintInvolves column constraint where ... Source #
Check if a TableConstraint
involves a column
Equations
ConstraintInvolves column (Check columns) = column `Elem` columns | |
ConstraintInvolves column (Unique columns) = column `Elem` columns | |
ConstraintInvolves column (PrimaryKey columns) = column `Elem` columns | |
ConstraintInvolves column (ForeignKey columns tab refcolumns) = column `Elem` columns |
type family DropIfConstraintsInvolve column constraints where ... Source #
Drop all TableConstraint
s that involve a column
Equations
DropIfConstraintsInvolve column '[] = '[] | |
DropIfConstraintsInvolve column ((alias ::: constraint) ': constraints) = If (ConstraintInvolves column constraint) (DropIfConstraintsInvolve column constraints) ((alias ::: constraint) ': DropIfConstraintsInvolve column constraints) |
Generics
type family SameFields (datatypeInfo :: DatatypeInfo) (columns :: RelationType) :: Constraint where ... Source #
A SameFields
constraint proves that a
DatatypeInfo
of a record type has the same
field names as the column AliasesOf of a ColumnsType
.
Equations
SameFields (ADT _module _datatype '[Record _constructor fields]) columns = AllZip SameField fields columns | |
SameFields (Newtype _module _datatype (Record _constructor fields)) columns = AllZip SameField fields columns |