@@ -12,6 +12,7 @@ Squeal data definition language.
1212 DataKinds
1313 , DeriveDataTypeable
1414 , DeriveGeneric
15+ , FlexibleContexts
1516 , GADTs
1617 , GeneralizedNewtypeDeriving
1718 , KindSignatures
@@ -29,7 +30,7 @@ module Squeal.PostgreSQL.Definition
2930 , (>>>)
3031 -- * Create
3132 , createTable
32− , TableConstraint (UnsafeTableConstraint, renderTableConstraint)
33+ , TableConstraintExpression (..)
3334 , check
3435 , unique
3536 , primaryKey
@@ -43,12 +44,12 @@ module Squeal.PostgreSQL.Definition
4344 -- * Alter
4445 , alterTable
4546 , alterTableRename
46− , alterTableAddConstraint
47− , AlterColumns (UnsafeAlterColumns, renderAlterColumns)
47+ , addConstraint
48+ , AlterTable (UnsafeAlterTable, renderAlterTable)
4849 , addColumnDefault
4950 , addColumnNull
5051 , dropColumn
51− , dropColumnCascade
52+ -- , dropColumnCascade
5253 , renameColumn
5354 , alterColumn
5455 , AlterColumn (UnsafeAlterColumn, renderAlterColumn)
@@ -82,8 +83,8 @@ statements
8283-- database, like a `createTable`, `dropTable`, or `alterTable` command.
8384-- `Definition`s may be composed using the `>>>` operator.
8485newtype Definition
85− (schema0 :: TablesType)
86− (schema1 :: TablesType)
86+ (schema0 :: SchemaType)
87+ (schema1 :: SchemaType)
8788 = UnsafeDefinition { renderDefinition :: ByteString }
8889 deriving (GHC.Generic,Show,Eq,Ord,NFData)
8990
@@ -105,27 +106,26 @@ CREATE statements
105106-- :}
106107-- "CREATE TABLE tab (a int, b real);"
107108createTable
108− :: (KnownSymbol table, SOP.SListI columns)
109− => Alias table -- ^ the name of the table to add
109+ :: ( KnownSymbol tab
110+ , SOP.SListI columns
111+ , SOP.SListI constraints
112+ , table ~ (constraints :=> (column ': columns)))
113+ => Alias tab -- ^ the name of the table to add
110114 -> NP (Aliased TypeExpression) (column ': columns)
111115 -- ^ the names and datatype of each column
112− -> [TableConstraint schema (column ': columns)]
116+ -> NP (TableConstraintExpression schema (column ': columns)) constraints
113117 -- ^ constraints that must hold for the table
114− -> Definition schema (Create table (column ': columns) schema)
118+ -> Definition schema (Create tab table schema)
115119createTable table columns constraints = UnsafeDefinition $
116120 "CREATE TABLE" <+> renderAlias table
117121 <+> parenthesized
118122 ( renderCommaSeparated renderColumnDef columns
119− <> renderConstraints constraints )
123+ <> renderCommaSeparated renderTableConstraintExpression constraints )
120124 <> ";"
121125 where
122126 renderColumnDef :: Aliased TypeExpression x -> ByteString
123127 renderColumnDef (ty `As` column) =
124128 renderAlias column <+> renderTypeExpression ty
125− renderConstraints :: [TableConstraint schema columns] -> ByteString
126− renderConstraints = \case
127− [] -> ""
128− _ -> ", " <> commaSeparated (renderTableConstraint <$> constraints)
129129
130130-- | Data types are a way to limit the kind of data that can be stored in a
131131-- table. For many applications, however, the constraint they provide is
@@ -139,10 +139,12 @@ createTable table columns constraints = UnsafeDefinition $
139139-- as you wish. If a user attempts to store data in a column that would
140140-- violate a constraint, an error is raised. This applies
141141-- even if the value came from the default value definition.
142−newtype TableConstraint
143− (schema :: TablesType)
142+newtype TableConstraintExpression
143+ (schema :: SchemaType)
144144 (columns :: ColumnsType)
145− = UnsafeTableConstraint { renderTableConstraint :: ByteString }
145+ (tableConstraint :: TableConstraint)
146+ = UnsafeTableConstraintExpression
147+ { renderTableConstraintExpression :: ByteString }
146148 deriving (GHC.Generic,Show,Eq,Ord,NFData)
147149
148150-- | A `check` constraint is the most generic `TableConstraint` type.
@@ -160,8 +162,8 @@ newtype TableConstraint
160162check
161163 :: Condition '[table ::: columns] 'Ungrouped '[]
162164 -- ^ condition to check
163− -> TableConstraint schema columns
164−check condition = UnsafeTableConstraint $
165+ -> TableConstraintExpression schema columns 'Check
166+check condition = UnsafeTableConstraintExpression $
165167 "CHECK" <+> parenthesized (renderExpression condition)
166168
167169-- | A `unique` constraint ensure that the data contained in a column,
@@ -179,8 +181,8 @@ unique
179181 :: SOP.SListI subcolumns
180182 => NP (Column columns) subcolumns
181183 -- ^ unique column or group of columns
182− -> TableConstraint schema columns
183−unique columns = UnsafeTableConstraint $
184+ -> TableConstraintExpression schema columns ( 'Uniques (Aliases subcolumns))
185+unique columns = UnsafeTableConstraintExpression $
184186 "UNIQUE" <+> parenthesized (renderCommaSeparated renderColumn columns)
185187
186188-- | A `primaryKey` constraint indicates that a column, or group of columns,
@@ -196,11 +198,11 @@ unique columns = UnsafeTableConstraint $
196198-- :}
197199-- "CREATE TABLE tab (id serial, name text NOT NULL, PRIMARY KEY (id));"
198200primaryKey
199− :: (SOP.SListI subcolumns, AllNotNull subcolumns)
201+ :: (SOP.SListI subcolumns, NotAllNull subcolumns)
200202 => NP (Column columns) subcolumns
201203 -- ^ identifying column or group of columns
202− -> TableConstraint schema columns
203−primaryKey columns = UnsafeTableConstraint $
204+ -> TableConstraintExpression schema columns ('Uniques (Aliases subcolumns))
205+primaryKey columns = UnsafeTableConstraintExpression $
204206 "PRIMARY KEY" <+> parenthesized (renderCommaSeparated renderColumn columns)
205207
206208-- | A `foreignKey` specifies that the values in a column
@@ -237,14 +239,14 @@ primaryKey columns = UnsafeTableConstraint $
237239-- :}
238240-- "CREATE TABLE users (id serial, username text NOT NULL, PRIMARY KEY (id)); CREATE TABLE emails (id serial, userid integer NOT NULL, email text NOT NULL, PRIMARY KEY (id), FOREIGN KEY (userid) REFERENCES users (id) ON DELETE CASCADE ON UPDATE RESTRICT);"
239241foreignKey
240− :: ( HasTable reftable schema refcolumns
242+ :: ( SchemaHasTable tab schema refcolumns
241243 , SameTypes subcolumns refsubcolumns
242244 , AllNotNull subcolumns
243245 , SOP.SListI subcolumns
244246 , SOP.SListI refsubcolumns)
245247 => NP (Column columns) subcolumns
246248 -- ^ column or columns in the table
247− -> Alias reftable
249+ -> Alias tab
248250 -- ^ reference table
249251 -> NP (Column refcolumns) refsubcolumns
250252 -- ^ reference column or columns in the reference table
@@ -252,9 +254,10 @@ foreignKey
252254 -- ^ what to do when reference is deleted
253255 -> OnUpdateClause
254256 -- ^ what to do when reference is updated
255− -> TableConstraint schema columns
257+ -> TableConstraintExpression schema columns
258+ ('ForeignKey (Aliases subcolumns) tab (Aliases refsubcolumns))
256259foreignKey columns reftable refcolumns onDelete onUpdate =
257− UnsafeTableConstraint $
260+ UnsafeTableConstraintExpression $
258261 "FOREIGN KEY" <+> parenthesized (renderCommaSeparated renderColumn columns)
259262 <+> "REFERENCES" <+> renderAlias reftable
260263 <+> parenthesized (renderCommaSeparated renderColumn refcolumns)
@@ -320,14 +323,14 @@ ALTER statements
320323
321324-- | `alterTable` changes the definition of a table from the schema.
322325alterTable
323− :: HasTable table schema columns0
324− => Alias table -- ^ table to alter
325− -> AlterColumns columns0 columns1 -- ^ alteration to perform
326− -> Definition schema (Alter table schema columns1)
326+ :: (KnownSymbol tab, (tab ::: table0) `In` schema)
327+ => Alias tab -- ^ table to alter
328+ -> AlterTable schema table0 table1 -- ^ alteration to perform
329+ -> Definition schema (Alter tab schema table1)
327330alterTable table alteration = UnsafeDefinition $
328331 "ALTER TABLE"
329332 <+> renderAlias table
330− <+> renderAlterColumns alteration
333+ <+> renderAlterTable alteration
331334 <> ";"
332335
333336-- | `alterTableRename` changes the name of a table from the schema.
@@ -354,21 +357,29 @@ alterTableRename table0 table1 = UnsafeDefinition $
354357-- in renderDefinition definition
355358-- :}
356359-- "ALTER TABLE tab ADD CHECK ((col > 0));"
357−alterTableAddConstraint
358− :: HasTable table schema columns
359− => Alias table -- ^ table to constrain
360− -> TableConstraint schema columns -- ^ what constraint to add
361− -> Definition schema schema
362−alterTableAddConstraint table constraint = UnsafeDefinition $
363− "ALTER TABLE" <+> renderAlias table
364− <+> "ADD" <+> renderTableConstraint constraint <> ";"
365−
366−-- | An `AlterColumns` describes the alteration to perform on the columns
360+-- alterTableAddConstraint
361+-- :: (HasTable table schema columns, (table ::: table0) `In` schema)
362+-- => Alias table -- ^ table to constrain
363+-- -> TableConstraintExpression schema columns constraint -- ^ what constraint to add
364+-- -> Definition schema (Alter table schema (AddConstraint constraint table0))
365+-- alterTableAddConstraint table constraint = UnsafeDefinition $
366+-- "ALTER TABLE" <+> renderAlias table
367+-- <+> "ADD" <+> renderTableConstraintExpression constraint <> ";"
368+
369+addConstraint
370+ :: (tab ::: table) `In` schema
371+ => Alias tab
372+ -> TableConstraintExpression schema columns constraint
373+ -> AlterTable schema table (AddConstraint constraint table)
374+addConstraint = undefined
375+
376+-- | An `AlterTable` describes the alteration to perform on the columns
367377-- of a table.
368−newtype AlterColumns
369− (columns0 :: ColumnsType)
370− (columns1 :: ColumnsType) =
371− UnsafeAlterColumns {renderAlterColumns :: ByteString}
378+newtype AlterTable
379+ (schema :: SchemaType)
380+ (table0 :: TableType)
381+ (table1 :: TableType) =
382+ UnsafeAlterTable {renderAlterTable :: ByteString}
372383 deriving (GHC.Generic,Show,Eq,Ord,NFData)
373384
374385-- | An `addColumnDefault` adds a new `Optional` column. The new column is
@@ -389,9 +400,9 @@ newtype AlterColumns
389400addColumnDefault
390401 :: (KnownSymbol column, 'Default `In` constraints)
391402 => Alias column -- ^ column to add
392− -> TypeExpression '(constraints, ty) -- ^ type of the new column
393− -> AlterColumns columns (Create column '(constraints, ty) columns)
394−addColumnDefault column ty = UnsafeAlterColumns $
403+ -> TypeExpression (constraints :=> ty) -- ^ type of the new column
404+ -> AlterTable schema table (Add column (constraints :=> ty) table)
405+addColumnDefault column ty = UnsafeAlterTable $
395406 "ADD COLUMN" <+> renderAlias column <+> renderTypeExpression ty
396407
397408-- | An `addColumnNull` adds a new `Null` column. The new column is initially
@@ -411,9 +422,9 @@ addColumnDefault column ty = UnsafeAlterColumns $
411422addColumnNull
412423 :: KnownSymbol column
413424 => Alias column -- ^ column to add
414− -> TypeExpression '( '[], ('Null ty)) -- ^ type of the new column
415− -> AlterColumns columns (Create column '( '[], ('Null ty)) columns)
416−addColumnNull column ty = UnsafeAlterColumns $
425+ -> TypeExpression ( '[] :=> 'Null ty) -- ^ type of the new column
426+ -> AlterTable schema table (Add column ( '[] :=> 'Null ty) table)
427+addColumnNull column ty = UnsafeAlterTable $
417428 "ADD COLUMN" <+> renderAlias column <+> renderTypeExpression ty
418429
419430-- | A `dropColumn` removes a column. Whatever data was in the column
@@ -435,8 +446,8 @@ addColumnNull column ty = UnsafeAlterColumns $
435446dropColumn
436447 :: KnownSymbol column
437448 => Alias column -- ^ column to remove
438− -> AlterColumns columns (Drop column columns)
439−dropColumn column = UnsafeAlterColumns $
449+ -> AlterTable schema ('[] :=> columns) ('[] :=> Drop column columns)
450+dropColumn column = UnsafeAlterTable $
440451 "DROP COLUMN" <+> renderAlias column
441452
442453-- | Like `dropColumn` but authorizes dropping everything that depends
@@ -453,12 +464,12 @@ dropColumn column = UnsafeAlterColumns $
453464-- in renderDefinition definition
454465-- :}
455466-- "ALTER TABLE tab DROP COLUMN col2 CASCADE;"
456−dropColumnCascade
457− :: KnownSymbol column
458− => Alias column -- ^ column to remove
459− -> AlterColumns columns (Drop column columns)
460−dropColumnCascade column = UnsafeAlterColumns $
461− "DROP COLUMN" <+> renderAlias column <+> "CASCADE"
467+-- dropColumnCascade
468+-- :: KnownSymbol column
469+-- => Alias column -- ^ column to remove
470+-- -> AlterTable schema columns (Drop column columns)
471+-- dropColumnCascade column = UnsafeAlterTable $
472+-- "DROP COLUMN" <+> renderAlias column <+> "CASCADE"
462473
463474-- | A `renameColumn` renames a column.
464475--
@@ -475,8 +486,9 @@ renameColumn
475486 :: (KnownSymbol column0, KnownSymbol column1)
476487 => Alias column0
477488 -> Alias column1
478− -> AlterColumns columns (Rename column0 column1 columns)
479−renameColumn column0 column1 = UnsafeAlterColumns $
489+ -> AlterTable schema ('[] :=> columns)
490+ ('[] :=> Rename column0 column1 columns)
491+renameColumn column0 column1 = UnsafeAlterTable $
480492 "RENAME COLUMN" <+> renderAlias column0 <+> "TO" <+> renderAlias column1
481493
482494-- | An `alterColumn` alters a single column.
@@ -484,8 +496,8 @@ alterColumn
484496 :: (KnownSymbol column, HasColumn column columns ty0)
485497 => Alias column -- ^ column to alter
486498 -> AlterColumn ty0 ty1 -- ^ alteration to perform
487− -> AlterColumns columns (Alter column columns ty1)
488−alterColumn column alteration = UnsafeAlterColumns $
499+ -> AlterTable schema ('[] :=> columns) ('[] :=> Alter column columns ty1)
500+alterColumn column alteration = UnsafeAlterTable $
489501 "ALTER COLUMN" <+> renderAlias column <+> renderAlterColumn alteration
490502
491503-- | An `AlterColumn` describes the alteration to perform on a single column.
@@ -523,7 +535,7 @@ setDefault expression = UnsafeAlterColumn $
523535-- in renderDefinition definition
524536-- :}
525537-- "ALTER TABLE tab ALTER COLUMN col DROP DEFAULT;"
526−dropDefault :: AlterColumn '(constraints, ty) '(DropDefault constraints, ty)
538+dropDefault :: AlterColumn ty (DropConstraint 'Default ty)
527539dropDefault = UnsafeAlterColumn $ "DROP DEFAULT"
528540
529541-- | A `setNotNull` adds a @NOT NULL@ constraint to a column.