@@ -19,6 +19,8 @@ module Database.PostgreSQL.Simple.Migration
19
19
(
20
20
-- * Migration actions
21
21
runMigration
22
+ , runMigrations
23
+ , sequenceMigrations
22
24
23
25
-- * Migration types
24
26
, MigrationContext (.. )
@@ -68,13 +70,43 @@ runMigration (MigrationContext cmd verbose con) = case cmd of
68
70
MigrationInitialization ->
69
71
initializeSchema con verbose >> return MigrationSuccess
70
72
MigrationDirectory path ->
71
- executeDirectoryMigration con verbose path
73
+ executeDirectoryMigration con verbose path
72
74
MigrationScript name contents ->
73
75
executeMigration con verbose name contents
74
76
MigrationFile name path ->
75
77
executeMigration con verbose name =<< BS. readFile path
76
78
MigrationValidation validationCmd ->
77
79
executeValidation con verbose validationCmd
80
+ MigrationCommands commands ->
81
+ runMigrations verbose con commands
82
+
83
+ -- | Execute a sequence of migrations
84
+ --
85
+ -- Returns 'MigrationSuccess' if all of the provided 'MigrationCommand's
86
+ -- execute without error. If an error occurs, execution is stopped and the
87
+ -- 'MigrationError' is returned.
88
+ --
89
+ -- It is recommended to wrap 'runMigrations' inside a database transaction.
90
+ runMigrations
91
+ :: Bool
92
+ -- ^ Run in verbose mode
93
+ -> Connection
94
+ -- ^ The postgres connection to use
95
+ -> [MigrationCommand ]
96
+ -- ^ The commands to run
97
+ -> IO (MigrationResult String )
98
+ runMigrations verbose con commands =
99
+ sequenceMigrations [runMigration (MigrationContext c verbose con) | c <- commands]
100
+
101
+ -- | Run a sequence of contexts, stopping on the first failure
102
+ sequenceMigrations :: Monad m => [m (MigrationResult e )] -> m (MigrationResult e )
103
+ sequenceMigrations = \ case
104
+ [] -> pure MigrationSuccess
105
+ c: cs -> do
106
+ r <- c
107
+ case r of
108
+ MigrationError s -> pure (MigrationError s)
109
+ MigrationSuccess -> sequenceMigrations cs
78
110
79
111
-- | Executes all SQL-file based migrations located in the provided 'dir'
80
112
-- in alphabetical order.
@@ -140,6 +172,7 @@ initializeSchema con verbose = do
140
172
-- * 'MigrationScript': validate the presence and checksum of the given script.
141
173
-- * 'MigrationFile': validate the presence and checksum of the given file.
142
174
-- * 'MigrationValidation': always succeeds.
175
+ -- * 'MigrationCommands': validates all the sub-commands stopping at the first failure.
143
176
executeValidation :: Connection -> Bool -> MigrationCommand -> IO (MigrationResult String )
144
177
executeValidation con verbose cmd = case cmd of
145
178
MigrationInitialization ->
@@ -154,6 +187,8 @@ executeValidation con verbose cmd = case cmd of
154
187
validate name =<< BS. readFile path
155
188
MigrationValidation _ ->
156
189
return MigrationSuccess
190
+ MigrationCommands cs ->
191
+ sequenceMigrations (executeValidation con verbose <$> cs)
157
192
where
158
193
validate name contents =
159
194
checkScript con name (md5Hash contents) >>= \ case
@@ -222,8 +257,17 @@ data MigrationCommand
222
257
-- ^ Executes a migration based on the provided bytestring.
223
258
| MigrationValidation MigrationCommand
224
259
-- ^ Validates the provided MigrationCommand.
260
+ | MigrationCommands [MigrationCommand ]
261
+ -- ^ Performs a series of 'MigrationCommand's in sequence.
225
262
deriving (Show , Eq , Read , Ord )
226
263
264
+ instance Monoid MigrationCommand where
265
+ mempty = MigrationCommands []
266
+ mappend (MigrationCommands xs) (MigrationCommands ys) = MigrationCommands (xs ++ ys)
267
+ mappend (MigrationCommands xs) y = MigrationCommands (xs ++ [y])
268
+ mappend x (MigrationCommands ys) = MigrationCommands (x : ys)
269
+ mappend x y = MigrationCommands [x, y]
270
+
227
271
-- | A sum-type denoting the result of a single migration.
228
272
data CheckScriptResult
229
273
= ScriptOk
0 commit comments