-
Notifications
You must be signed in to change notification settings - Fork 189
Expand file tree
/
Copy pathSQL92.hs
More file actions
330 lines (279 loc) · 15.4 KB
/
SQL92.hs
File metadata and controls
330 lines (279 loc) · 15.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE CPP #-}
-- | Finally-tagless encoding of SQL92 DDL commands.
--
-- If you're writing a beam backend driver and you want to support migrations,
-- making an instance of your command syntax for 'IsSql92DdlCommandSyntax' and
-- making it satisfy 'Sql92SaneDdlCommandSyntax'.
module Database.Beam.Migrate.SQL.SQL92 where
import Database.Beam.Backend.SQL.SQL92
import Data.Aeson (Value)
import Data.Aeson.Types (Parser)
import Data.Hashable
import Data.Kind (Type)
import qualified Data.List.NonEmpty as NE (NonEmpty)
import Data.Text (Text)
import Data.Typeable (Typeable)
import GHC.Generics (Generic)
-- * Convenience type synonyms
-- | Syntax equalities that any reasonable DDL syntax would follow,
-- including equalities between beam-migrate and beam-core types.
type Sql92SaneDdlCommandSyntax cmd =
( Sql92SaneDdlCommandSyntaxMigrateOnly cmd
, Sql92ExpressionCastTargetSyntax (Sql92ExpressionSyntax cmd) ~
Sql92DdlCommandDataTypeSyntax cmd
, Sql92ColumnSchemaExpressionSyntax (Sql92DdlCommandColumnSchemaSyntax cmd) ~
Sql92ExpressionSyntax cmd )
-- | Syntax equalities that any reasonable DDL syntax with schema support would follow,
-- including equalities between beam-migrate and beam-core types.
type Sql92SaneDdlSchemaCommandSyntax cmd =
( Sql92SaneDdlSchemaCommandSyntaxMigrateOnly cmd
, Sql92ExpressionCastTargetSyntax (Sql92ExpressionSyntax cmd) ~
Sql92DdlCommandDataTypeSyntax cmd
, Sql92ColumnSchemaExpressionSyntax (Sql92DdlCommandColumnSchemaSyntax cmd) ~
Sql92ExpressionSyntax cmd )
-- | Syntax equalities for any reasonable DDL syntax, only including
-- types defined here.
type Sql92SaneDdlCommandSyntaxMigrateOnly cmd =
( IsSql92DdlCommandSyntax cmd
, Sql92SerializableDataTypeSyntax (Sql92DdlCommandDataTypeSyntax cmd)
, Sql92SerializableConstraintDefinitionSyntax (Sql92DdlCommandConstraintDefinitionSyntax cmd)
, Typeable (Sql92DdlCommandColumnSchemaSyntax cmd)
, Sql92AlterTableColumnSchemaSyntax
(Sql92AlterTableAlterTableActionSyntax (Sql92DdlCommandAlterTableSyntax cmd)) ~
Sql92CreateTableColumnSchemaSyntax (Sql92DdlCommandCreateTableSyntax cmd)
)
-- | Syntax equalities for any reasonable DDL syntax, only including
-- types defined here.
type Sql92SaneDdlSchemaCommandSyntaxMigrateOnly cmd =
( Sql92SaneDdlCommandSyntaxMigrateOnly cmd
, IsSql92DdlSchemaCommandSyntax cmd
)
type Sql92DdlCommandDataTypeSyntax syntax =
Sql92ColumnSchemaColumnTypeSyntax (Sql92DdlCommandColumnSchemaSyntax syntax)
type Sql92DdlCommandColumnSchemaSyntax syntax = Sql92CreateTableColumnSchemaSyntax (Sql92DdlCommandCreateTableSyntax syntax)
type Sql92DdlCommandConstraintDefinitionSyntax syntax =
Sql92ColumnSchemaColumnConstraintDefinitionSyntax (Sql92DdlCommandColumnSchemaSyntax syntax)
type Sql92DdlColumnSchemaConstraintSyntax syntax =
Sql92ColumnConstraintDefinitionConstraintSyntax (Sql92ColumnSchemaColumnConstraintDefinitionSyntax syntax)
type Sql92DdlCommandColumnConstraintSyntax syntax =
Sql92DdlColumnSchemaConstraintSyntax (Sql92DdlCommandColumnSchemaSyntax syntax)
type Sql92DdlCommandMatchTypeSyntax syntax =
Sql92ColumnConstraintMatchTypeSyntax (Sql92DdlCommandColumnConstraintSyntax syntax)
type Sql92DdlCommandReferentialActionSyntax syntax =
Sql92ColumnConstraintReferentialActionSyntax (Sql92DdlCommandColumnConstraintSyntax syntax)
type Sql92DdlCommandConstraintAttributesSyntax syntax =
Sql92ColumnConstraintDefinitionAttributesSyntax (Sql92DdlCommandConstraintDefinitionSyntax syntax)
type Sql92DdlCommandAlterTableActionSyntax syntax =
Sql92AlterTableAlterTableActionSyntax (Sql92DdlCommandAlterTableSyntax syntax)
-- Creation/deletion of schemas isn't supported by all backends (e.g. sqlite)
-- and therefore is considered separately from other DDL commands such as CREATE TABLE
class ( IsSql92CreateSchemaSyntax (Sql92DdlCommandCreateSchemaSyntax syntax)
, IsSql92DropSchemaSyntax (Sql92DdlCommandDropSchemaSyntax syntax)) =>
IsSql92DdlSchemaCommandSyntax syntax where
type Sql92DdlCommandCreateSchemaSyntax syntax :: Type
type Sql92DdlCommandDropSchemaSyntax syntax :: Type
createSchemaCmd :: Sql92DdlCommandCreateSchemaSyntax syntax -> syntax
dropSchemaCmd :: Sql92DdlCommandDropSchemaSyntax syntax -> syntax
class ( IsSql92CreateTableSyntax (Sql92DdlCommandCreateTableSyntax syntax)
, IsSql92DropTableSyntax (Sql92DdlCommandDropTableSyntax syntax)
, IsSql92AlterTableSyntax (Sql92DdlCommandAlterTableSyntax syntax)) =>
IsSql92DdlCommandSyntax syntax where
type Sql92DdlCommandCreateTableSyntax syntax :: Type
type Sql92DdlCommandAlterTableSyntax syntax :: Type
type Sql92DdlCommandDropTableSyntax syntax :: Type
createTableCmd :: Sql92DdlCommandCreateTableSyntax syntax -> syntax
dropTableCmd :: Sql92DdlCommandDropTableSyntax syntax -> syntax
alterTableCmd :: Sql92DdlCommandAlterTableSyntax syntax -> syntax
class IsSql92SchemaNameSyntax (Sql92CreateSchemaSchemaNameSyntax syntax) =>
IsSql92CreateSchemaSyntax syntax where
type Sql92CreateSchemaSchemaNameSyntax syntax :: Type
createSchemaSyntax :: Sql92CreateSchemaSchemaNameSyntax syntax
-> syntax
class IsSql92SchemaNameSyntax (Sql92DropSchemaSchemaNameSyntax syntax) =>
IsSql92DropSchemaSyntax syntax where
type Sql92DropSchemaSchemaNameSyntax syntax :: Type
dropSchemaSyntax :: Sql92DropSchemaSchemaNameSyntax syntax
-> syntax
class ( IsSql92TableConstraintSyntax (Sql92CreateTableTableConstraintSyntax syntax)
, IsSql92ColumnSchemaSyntax (Sql92CreateTableColumnSchemaSyntax syntax)
, IsSql92TableNameSyntax (Sql92CreateTableTableNameSyntax syntax) ) =>
IsSql92CreateTableSyntax syntax where
type Sql92CreateTableTableNameSyntax syntax :: Type
type Sql92CreateTableColumnSchemaSyntax syntax :: Type
type Sql92CreateTableTableConstraintSyntax syntax :: Type
type Sql92CreateTableOptionsSyntax syntax :: Type
createTableSyntax :: Maybe (Sql92CreateTableOptionsSyntax syntax)
-> Sql92CreateTableTableNameSyntax syntax
-> [ (Text, Sql92CreateTableColumnSchemaSyntax syntax) ]
-> [ Sql92CreateTableTableConstraintSyntax syntax ]
-> syntax
class IsSql92TableNameSyntax (Sql92DropTableTableNameSyntax syntax) =>
IsSql92DropTableSyntax syntax where
type Sql92DropTableTableNameSyntax syntax :: Type
dropTableSyntax :: Sql92DropTableTableNameSyntax syntax -> syntax
class ( IsSql92TableNameSyntax (Sql92AlterTableTableNameSyntax syntax),
IsSql92AlterTableActionSyntax (Sql92AlterTableAlterTableActionSyntax syntax) ) =>
IsSql92AlterTableSyntax syntax where
type Sql92AlterTableTableNameSyntax syntax :: Type
type Sql92AlterTableAlterTableActionSyntax syntax :: Type
alterTableSyntax :: Sql92AlterTableTableNameSyntax syntax -> Sql92AlterTableAlterTableActionSyntax syntax
-> syntax
class ( IsSql92ColumnSchemaSyntax (Sql92AlterTableColumnSchemaSyntax syntax)
, IsSql92AlterColumnActionSyntax (Sql92AlterTableAlterColumnActionSyntax syntax) ) =>
IsSql92AlterTableActionSyntax syntax where
type Sql92AlterTableAlterColumnActionSyntax syntax :: Type
type Sql92AlterTableColumnSchemaSyntax syntax :: Type
alterColumnSyntax :: Text -> Sql92AlterTableAlterColumnActionSyntax syntax
-> syntax
addColumnSyntax :: Text -> Sql92AlterTableColumnSchemaSyntax syntax -> syntax
dropColumnSyntax :: Text -> syntax
renameTableToSyntax :: Text -> syntax
renameColumnToSyntax :: Text -> Text -> syntax
class IsSql92AlterColumnActionSyntax syntax where
setNotNullSyntax, setNullSyntax :: syntax
class ( IsSql92ColumnConstraintDefinitionSyntax (Sql92ColumnSchemaColumnConstraintDefinitionSyntax columnSchema)
, IsSql92DataTypeSyntax (Sql92ColumnSchemaColumnTypeSyntax columnSchema)
, Typeable (Sql92ColumnSchemaColumnTypeSyntax columnSchema)
, Sql92DisplaySyntax (Sql92ColumnSchemaColumnTypeSyntax columnSchema)
, Hashable (Sql92ColumnSchemaColumnTypeSyntax columnSchema)
, Eq (Sql92ColumnSchemaColumnTypeSyntax columnSchema)
, Sql92DisplaySyntax (Sql92ColumnSchemaColumnConstraintDefinitionSyntax columnSchema)
, Eq (Sql92ColumnSchemaColumnConstraintDefinitionSyntax columnSchema)
, Hashable (Sql92ColumnSchemaColumnConstraintDefinitionSyntax columnSchema)
, IsSql92ExpressionSyntax (Sql92ColumnSchemaExpressionSyntax columnSchema)
, Typeable columnSchema, Sql92DisplaySyntax columnSchema, Eq columnSchema, Hashable columnSchema ) =>
IsSql92ColumnSchemaSyntax columnSchema where
type Sql92ColumnSchemaColumnTypeSyntax columnSchema :: Type
type Sql92ColumnSchemaExpressionSyntax columnSchema :: Type
type Sql92ColumnSchemaColumnConstraintDefinitionSyntax columnSchema :: Type
columnSchemaSyntax :: Sql92ColumnSchemaColumnTypeSyntax columnSchema {-^ Column type -}
-> Maybe (Sql92ColumnSchemaExpressionSyntax columnSchema) {-^ Default value -}
-> [ Sql92ColumnSchemaColumnConstraintDefinitionSyntax columnSchema ] {-^ Column constraints -}
-> Maybe Text {-^ Default collation -}
-> columnSchema
-- | Action to perform on referencing foreign keys when a row is modified.
data ForeignKeyAction
= ForeignKeyActionCascade
-- ^ @CASCADE@: propagate the action to referencing foreign key columns.
| ForeignKeyActionSetNull
-- ^ @SET NULL@: set the referencing foreign key colums to @NULL@.
| ForeignKeyActionSetDefault
-- ^ @SET DEFAULT@: set the referencing foreign key columns to their default
-- values.
| ForeignKeyActionRestrict
-- ^ @RESTRICT@: prohibit modification of a row when foreign key references
-- to that row exist.
| ForeignKeyNoAction
-- ^ @NO ACTION@
deriving (Show, Eq, Ord, Generic)
instance Hashable ForeignKeyAction
class Typeable constraint => IsSql92TableConstraintSyntax constraint where
primaryKeyConstraintSyntax :: NE.NonEmpty Text -> constraint
-- | Class for table constraint syntaxes that support the SQL @FOREIGN KEY@
-- clause.
class IsSql92TableConstraintSyntax constraint =>
IsSql92ForeignKeyTableConstraintSyntax constraint where
-- | Emit a @FOREIGN KEY (cols) REFERENCES tbl (refCols)@ table constraint.
--
-- Use 'addTableForeignKey' to attach a foreign key to a schema definition.
foreignKeyConstraintSyntax
:: NE.NonEmpty Text -- ^ local columns
-> Text -- ^ referenced table name
-> NE.NonEmpty Text -- ^ referenced columns
-> ForeignKeyAction -- ^ ON UPDATE action
-> ForeignKeyAction -- ^ ON DELETE action
-> constraint
class Typeable match => IsSql92MatchTypeSyntax match where
fullMatchSyntax :: match
partialMatchSyntax :: match
class Typeable refAction => IsSql92ReferentialActionSyntax refAction where
referentialActionCascadeSyntax :: refAction
referentialActionSetNullSyntax :: refAction
referentialActionSetDefaultSyntax :: refAction
referentialActionNoActionSyntax :: refAction
class ( IsSql92ColumnConstraintSyntax (Sql92ColumnConstraintDefinitionConstraintSyntax constraint)
, IsSql92ConstraintAttributesSyntax (Sql92ColumnConstraintDefinitionAttributesSyntax constraint)
, Typeable constraint ) =>
IsSql92ColumnConstraintDefinitionSyntax constraint where
type Sql92ColumnConstraintDefinitionConstraintSyntax constraint :: Type
type Sql92ColumnConstraintDefinitionAttributesSyntax constraint :: Type
constraintDefinitionSyntax :: Maybe Text -> Sql92ColumnConstraintDefinitionConstraintSyntax constraint
-> Maybe (Sql92ColumnConstraintDefinitionAttributesSyntax constraint)
-> constraint
class (Semigroup attrs, Monoid attrs, Typeable attrs) => IsSql92ConstraintAttributesSyntax attrs where
initiallyDeferredAttributeSyntax :: attrs
initiallyImmediateAttributeSyntax :: attrs
notDeferrableAttributeSyntax :: attrs
deferrableAttributeSyntax :: attrs
class ( IsSql92MatchTypeSyntax (Sql92ColumnConstraintMatchTypeSyntax constraint)
, IsSql92ReferentialActionSyntax (Sql92ColumnConstraintReferentialActionSyntax constraint)
, Typeable (Sql92ColumnConstraintExpressionSyntax constraint)
, Typeable constraint ) =>
IsSql92ColumnConstraintSyntax constraint where
type Sql92ColumnConstraintMatchTypeSyntax constraint :: Type
type Sql92ColumnConstraintReferentialActionSyntax constraint :: Type
type Sql92ColumnConstraintExpressionSyntax constraint :: Type
notNullConstraintSyntax :: constraint
uniqueColumnConstraintSyntax :: constraint
primaryKeyColumnConstraintSyntax :: constraint
checkColumnConstraintSyntax :: Sql92ColumnConstraintExpressionSyntax constraint -> constraint
referencesConstraintSyntax :: Text -> [ Text ]
-> Maybe (Sql92ColumnConstraintMatchTypeSyntax constraint)
-> Maybe (Sql92ColumnConstraintReferentialActionSyntax constraint) {-^ On update -}
-> Maybe (Sql92ColumnConstraintReferentialActionSyntax constraint) {-^ On delete -}
-> constraint
-- | 'IsSql92DataTypeSyntax'es that can be serialized to JSON
class Sql92SerializableDataTypeSyntax dataType where
serializeDataType :: dataType -> Value
-- | 'IsSql92ColumnConstraintDefinitionSyntax'es that can be serialized to JSON
class Sql92SerializableConstraintDefinitionSyntax constraint where
serializeConstraint :: constraint -> Value
-- | Syntax extension for @CREATE INDEX@ and @DROP INDEX@ DDL commands.
--
-- @CREATE INDEX@ is not part of SQL92 proper, but is a widely supported
-- extension.
--
-- @since 0.5.4.0
class ( IsSql92DdlCommandSyntax syntax
, Show (Sql92CreateIndexOptionsSyntax syntax)
, Eq (Sql92CreateIndexOptionsSyntax syntax)
, Hashable (Sql92CreateIndexOptionsSyntax syntax)
) => IsSql92CreateDropIndexSyntax syntax where
type family Sql92CreateIndexOptionsSyntax syntax
-- | Render a @CREATE INDEX@ command.
createIndexCmd
:: Text -- ^ index name
-> Sql92CreateTableTableNameSyntax (Sql92DdlCommandCreateTableSyntax syntax)
-- ^ table name
-> NE.NonEmpty Text -- ^ ordered column names
-> Sql92CreateIndexOptionsSyntax syntax -- ^ index options
-> syntax
-- | Render a @DROP INDEX@ command.
dropIndexCmd
:: Text -- ^ index name
-> syntax
-- | Default options for @CREATE INDEX@
defaultIndexOptions
:: Sql92CreateIndexOptionsSyntax syntax
-- | Serialize index options to a JSON 'Value', for predicate storage.
serializeIndexOptions :: Sql92CreateIndexOptionsSyntax syntax -> Value
-- | Deserialize index options from the JSON 'Value' produced by
-- 'serializeIndexOptions'.
deserializeIndexOptions :: Value -> Parser (Sql92CreateIndexOptionsSyntax syntax)
-- | Class for index syntaxes that support the SQL @UNIQUE@ modifier.
--
-- Backends implementing 'IsSql92CreateDropIndexSyntax' should also implement
-- this class to expose uniqueness as a portable concept, while still allowing
-- their 'Sql92CreateIndexOptionsSyntax' to carry additional backend-specific
-- options (e.g. index type, partial-index predicates).
--
-- @since 0.5.4.0
class IsSql92CreateDropIndexSyntax syntax => IsSql92UniqueIndexSyntax syntax where
-- | Update index options by setting the uniqueness
setUniqueIndexOptions :: Bool -- ^ unique?
-> Sql92CreateIndexOptionsSyntax syntax
-> Sql92CreateIndexOptionsSyntax syntax
-- | Query whether an index is unique, as specified in the index options.
indexIsUnique :: Sql92CreateIndexOptionsSyntax syntax -> Bool