@@ -22,6 +22,8 @@ module Database.PostgreSQL.Simple.Migration
22
22
(
23
23
-- * Migration actions
24
24
runMigration
25
+ , runMigrations
26
+ , sequenceMigrations
25
27
26
28
-- * Migration types
27
29
, MigrationContext (.. )
@@ -73,13 +75,43 @@ runMigration (MigrationContext cmd verbose con) = case cmd of
73
75
MigrationInitialization ->
74
76
initializeSchema con verbose >> return MigrationSuccess
75
77
MigrationDirectory path ->
76
- executeDirectoryMigration con verbose path
78
+ executeDirectoryMigration con verbose path
77
79
MigrationScript name contents ->
78
80
executeMigration con verbose name contents
79
81
MigrationFile name path ->
80
82
executeMigration con verbose name =<< BS. readFile path
81
83
MigrationValidation validationCmd ->
82
84
executeValidation con verbose validationCmd
85
+ MigrationCommands commands ->
86
+ runMigrations verbose con commands
87
+
88
+ -- | Execute a sequence of migrations
89
+ --
90
+ -- Returns 'MigrationSuccess' if all of the provided 'MigrationCommand's
91
+ -- execute without error. If an error occurs, execution is stopped and the
92
+ -- 'MigrationError' is returned.
93
+ --
94
+ -- It is recommended to wrap 'runMigrations' inside a database transaction.
95
+ runMigrations
96
+ :: Bool
97
+ -- ^ Run in verbose mode
98
+ -> Connection
99
+ -- ^ The postgres connection to use
100
+ -> [MigrationCommand ]
101
+ -- ^ The commands to run
102
+ -> IO (MigrationResult String )
103
+ runMigrations verbose con commands =
104
+ sequenceMigrations [runMigration (MigrationContext c verbose con) | c <- commands]
105
+
106
+ -- | Run a sequence of contexts, stopping on the first failure
107
+ sequenceMigrations :: Monad m => [m (MigrationResult e )] -> m (MigrationResult e )
108
+ sequenceMigrations = \ case
109
+ [] -> pure MigrationSuccess
110
+ c: cs -> do
111
+ r <- c
112
+ case r of
113
+ MigrationError s -> pure (MigrationError s)
114
+ MigrationSuccess -> sequenceMigrations cs
83
115
84
116
-- | Executes all SQL-file based migrations located in the provided 'dir'
85
117
-- in alphabetical order.
@@ -145,6 +177,7 @@ initializeSchema con verbose = do
145
177
-- * 'MigrationScript': validate the presence and checksum of the given script.
146
178
-- * 'MigrationFile': validate the presence and checksum of the given file.
147
179
-- * 'MigrationValidation': always succeeds.
180
+ -- * 'MigrationCommands': validates all the sub-commands stopping at the first failure.
148
181
executeValidation :: Connection -> Bool -> MigrationCommand -> IO (MigrationResult String )
149
182
executeValidation con verbose cmd = case cmd of
150
183
MigrationInitialization ->
@@ -159,6 +192,8 @@ executeValidation con verbose cmd = case cmd of
159
192
validate name =<< BS. readFile path
160
193
MigrationValidation _ ->
161
194
return MigrationSuccess
195
+ MigrationCommands cs ->
196
+ sequenceMigrations (executeValidation con verbose <$> cs)
162
197
where
163
198
validate name contents =
164
199
checkScript con name (md5Hash contents) >>= \ case
@@ -227,8 +262,17 @@ data MigrationCommand
227
262
-- ^ Executes a migration based on the provided bytestring.
228
263
| MigrationValidation MigrationCommand
229
264
-- ^ Validates the provided MigrationCommand.
265
+ | MigrationCommands [MigrationCommand ]
266
+ -- ^ Performs a series of 'MigrationCommand's in sequence.
230
267
deriving (Show , Eq , Read , Ord )
231
268
269
+ instance Monoid MigrationCommand where
270
+ mempty = MigrationCommands []
271
+ mappend (MigrationCommands xs) (MigrationCommands ys) = MigrationCommands (xs ++ ys)
272
+ mappend (MigrationCommands xs) y = MigrationCommands (xs ++ [y])
273
+ mappend x (MigrationCommands ys) = MigrationCommands (x : ys)
274
+ mappend x y = MigrationCommands [x, y]
275
+
232
276
-- | A sum-type denoting the result of a single migration.
233
277
data CheckScriptResult
234
278
= ScriptOk
0 commit comments