@@ -137,7 +137,7 @@ data Migration io schemas0 schemas1 = Migration
137 -- Each `name` in a `Migration` should be unique.
137 -- Each `name` in a `Migration` should be unique.
138 , up :: PQ schemas0 schemas1 io () -- ^ The `up` instruction of a `Migration`.
138 , up :: PQ schemas0 schemas1 io () -- ^ The `up` instruction of a `Migration`.
139 , down :: PQ schemas1 schemas0 io () -- ^ The `down` instruction of a `Migration`.
139 , down :: PQ schemas1 schemas0 io () -- ^ The `down` instruction of a `Migration`.
140− }
140+ } deriving (GHC.Generic)
142-- | Run `Migration`s by creating the `MigrationsTable`
142-- | Run `Migration`s by creating the `MigrationsTable`
143-- if it does not exist and then in a transaction, for each each `Migration`
143-- if it does not exist and then in a transaction, for each each `Migration`
@@ -146,11 +146,8 @@ data Migration io schemas0 schemas1 = Migration
147 :: MonadBaseControl IO io
147 :: MonadBaseControl IO io
148 => AlignedList (Migration io) schemas0 schemas1 -- ^ migrations to run
148 => AlignedList (Migration io) schemas0 schemas1 -- ^ migrations to run
149− -> PQ
149+ -> PQ schemas0 schemas1 io ()
150− ("migrations" ::: MigrationsSchema ': schemas0)
151− ("migrations" ::: MigrationsSchema ': schemas1)
153−migrateUp migration =
150+migrateUp migration = unsafePQ $
154 define createMigrations
151 define createMigrations
155 & pqBind okResult
152 & pqBind okResult
156 & pqThen (transactionallySchema_ (upMigrations migration))
153 & pqThen (transactionallySchema_ (upMigrations migration))
@@ -159,37 +156,27 @@ migrateUp migration =
159 upMigrations
156 upMigrations
160 :: MonadBaseControl IO io
157 :: MonadBaseControl IO io
161 => AlignedList (Migration io) schemas0 schemas1
158 => AlignedList (Migration io) schemas0 schemas1
162− -> PQ
159+ -> PQ MigrationsSchemas MigrationsSchemas io ()
163− ("migrations" ::: MigrationsSchema ': schemas0)
164− ("migrations" ::: MigrationsSchema ': schemas1)
166 upMigrations = \case
160 upMigrations = \case
167 Done -> return ()
161 Done -> return ()
168 step :>> steps -> upMigration step & pqThen (upMigrations steps)
162 step :>> steps -> upMigration step & pqThen (upMigrations steps)
170 upMigration
164 upMigration
171 :: MonadBase IO io
165 :: MonadBase IO io
172− => Migration io schemas0 schemas1 -> PQ
166+ => Migration io schemas0 schemas1
173− ("migrations" ::: MigrationsSchema ': schemas0)
167+ -> PQ MigrationsSchemas MigrationsSchemas io ()
174− ("migrations" ::: MigrationsSchema ': schemas1)
176 upMigration step =
168 upMigration step =
177 queryExecuted step
169 queryExecuted step
178− & pqBind (\ executed ->
170+ & pqBind ( \ executed -> unless (executed == 1)
179− if executed == 1 -- up step has already been executed
171+ $ unsafePQ (up step)
180− then PQ (\ _ -> return (K ())) -- unsafely switch schemas
182− pqEmbed (up step) -- safely switch schemas
183− & pqThen (manipulateParams insertMigration (Only (name step)))
172+ & pqThen (manipulateParams insertMigration (Only (name step)))
184− -- insert execution record
173+ -- insert execution record
185− & pqBind okResult)
174+ & pqBind okResult )
187 queryExecuted
176 queryExecuted
188 :: MonadBase IO io
177 :: MonadBase IO io
189− => Migration io schemas0 schemas1 -> PQ
178+ => Migration io schemas0 schemas1
190− ("migrations" ::: MigrationsSchema ': schemas0)
179+ -> PQ MigrationsSchemas MigrationsSchemas io Row
191− ("migrations" ::: MigrationsSchema ': schemas0)
193 queryExecuted step = do
180 queryExecuted step = do
194 result <- runQueryParams selectMigration (Only (name step))
181 result <- runQueryParams selectMigration (Only (name step))
195 okResult result
182 okResult result
@@ -202,11 +189,8 @@ migrateUp migration =
202migrateDown
189migrateDown
203 :: MonadBaseControl IO io
190 :: MonadBaseControl IO io
204 => AlignedList (Migration io) schemas0 schemas1 -- ^ migrations to rewind
191 => AlignedList (Migration io) schemas0 schemas1 -- ^ migrations to rewind
205− -> PQ
192+ -> PQ schema1 schema0 io ()
206− ("migrations" ::: MigrationsSchema ': schemas1)
207− ("migrations" ::: MigrationsSchema ': schemas0)
209−migrateDown migrations =
193+migrateDown migrations = unsafePQ $
210 define createMigrations
194 define createMigrations
211 & pqBind okResult
195 & pqBind okResult
212 & pqThen (transactionallySchema_ (downMigrations migrations))
196 & pqThen (transactionallySchema_ (downMigrations migrations))
@@ -214,37 +198,28 @@ migrateDown migrations =
215 downMigrations
199 downMigrations
216 :: MonadBaseControl IO io
200 :: MonadBaseControl IO io
217− => AlignedList (Migration io) schemas0 schemas1 -> PQ
201+ => AlignedList (Migration io) schemas0 schemas1
218− ("migrations" ::: MigrationsSchema ': schemas1)
202+ -> PQ MigrationsSchemas MigrationsSchemas io ()
219− ("migrations" ::: MigrationsSchema ': schemas0)
221 downMigrations = \case
203 downMigrations = \case
222 Done -> return ()
204 Done -> return ()
223 step :>> steps -> downMigrations steps & pqThen (downMigration step)
205 step :>> steps -> downMigrations steps & pqThen (downMigration step)
225 downMigration
207 downMigration
226 :: MonadBase IO io
208 :: MonadBase IO io
227− => Migration io schemas0 schemas1 -> PQ
209+ => Migration io schemas0 schemas1
228− ("migrations" ::: MigrationsSchema ': schemas1)
210+ -> PQ MigrationsSchemas MigrationsSchemas io ()
229− ("migrations" ::: MigrationsSchema ': schemas0)
231 downMigration step =
211 downMigration step =
232 queryExecuted step
212 queryExecuted step
233− & pqBind (\ executed ->
213+ & pqBind ( \ executed -> unless (executed == 0)
234− if executed == 0 -- up step has not been executed
214+ $ unsafePQ (down step)
235− then PQ (\ _ -> return (K ())) -- unsafely switch schemas
237− pqEmbed (down step) -- safely switch schemas
238− & pqThen (manipulateParams deleteMigration (Only (name step)))
215+ & pqThen (manipulateParams deleteMigration (Only (name step)))
239− -- delete execution record
216+ -- delete execution record
240− & pqBind okResult)
217+ & pqBind okResult )
242 queryExecuted
219 queryExecuted
243 :: MonadBase IO io
220 :: MonadBase IO io
244− => Migration io schemas0 schemas1 -> PQ
221+ => Migration io schemas0 schemas1
245− ("migrations" ::: MigrationsSchema ': schemas1)
222+ -> PQ MigrationsSchemas MigrationsSchemas io Row
246− ("migrations" ::: MigrationsSchema ': schemas1)
248 queryExecuted step = do
223 queryExecuted step = do
249 result <- runQueryParams selectMigration (Only (name step))
224 result <- runQueryParams selectMigration (Only (name step))
250 okResult result
225 okResult result
@@ -256,8 +231,8 @@ okResult result = do
256 when (not (status `elem` [CommandOk, TuplesOk])) $ do
231 when (not (status `elem` [CommandOk, TuplesOk])) $ do
257 errorMessageMaybe <- resultErrorMessage result
232 errorMessageMaybe <- resultErrorMessage result
258 case errorMessageMaybe of
233 case errorMessageMaybe of
259− Nothing -> error "migrateDown: unknown error"
234+ Nothing -> error "migration: unknown error"
260− Just msg -> error ("migrationDown: " <> show msg)
235+ Just msg -> error ("migration: " <> show msg)
262-- | The `TableType` for a Squeal migration.
237-- | The `TableType` for a Squeal migration.
263type MigrationsTable =
238type MigrationsTable =
@@ -275,57 +250,43 @@ instance SOP.Generic MigrationRow
275instance SOP.HasDatatypeInfo MigrationRow
250instance SOP.HasDatatypeInfo MigrationRow
277type MigrationsSchema = '["schema_migrations" ::: 'Table MigrationsTable]
252type MigrationsSchema = '["schema_migrations" ::: 'Table MigrationsTable]
253+type MigrationsSchemas = Public MigrationsSchema
279-- | Creates a `MigrationsTable` if it does not already exist.
255-- | Creates a `MigrationsTable` if it does not already exist.
280−createMigrations
256+createMigrations :: Definition MigrationsSchemas MigrationsSchemas
281− :: Has "migrations" schemas MigrationsSchema
282− => Definition schemas schemas
283createMigrations =
257createMigrations =
284− createSchemaIfNotExists #migrations >>>
285− createTableIfNotExists (#migrations ! #schema_migrations)
258+ createTableIfNotExists #schema_migrations
286 ( (text & notNullable) `as` #name :*
259 ( (text & notNullable) `as` #name :*
287 (timestampWithTimeZone & notNullable & default_ currentTimestamp)
260 (timestampWithTimeZone & notNullable & default_ currentTimestamp)
288 `as` #executed_at )
261 `as` #executed_at )
289 ( unique #name `as` #migrations_unique_name )
262 ( unique #name `as` #migrations_unique_name )
291-- | Inserts a `Migration` into the `MigrationsTable`
264-- | Inserts a `Migration` into the `MigrationsTable`
292−insertMigration
265+insertMigration :: Manipulation_ MigrationsSchemas (Only Text) ()
293− :: Has "migrations" schemas MigrationsSchema
294− => Manipulation '[] schemas '[ 'NotNull 'PGtext] '[]
295−insertMigration = insertInto_ (#migrations ! #schema_migrations) . Values_ $
266+insertMigration = insertInto_ #schema_migrations . Values_ $
296 (param @1) `as` #name :* defaultAs #executed_at
267 (param @1) `as` #name :* defaultAs #executed_at
298-- | Deletes a `Migration` from the `MigrationsTable`
269-- | Deletes a `Migration` from the `MigrationsTable`
299−deleteMigration
270+deleteMigration :: Manipulation_ MigrationsSchemas (Only Text) ()
300− :: Has "migrations" schemas MigrationsSchema
301− => Manipulation '[] schemas '[ 'NotNull 'PGtext ] '[]
302−deleteMigration = deleteFrom_ (#migrations ! #schema_migrations) (#name .== param @1)
271+deleteMigration = deleteFrom_ #schema_migrations (#name .== param @1)
304-- | Selects a `Migration` from the `MigrationsTable`, returning
273-- | Selects a `Migration` from the `MigrationsTable`, returning
305-- the time at which it was executed.
274-- the time at which it was executed.
306selectMigration
275selectMigration
307− :: Has "migrations" schemas MigrationsSchema
276+ :: Query_ MigrationsSchemas (Only Text) (P ("executed_at" ::: UTCTime))
308− => Query '[] '[] schemas '[ 'NotNull 'PGtext ]
309− '[ "executed_at" ::: 'NotNull 'PGtimestamptz ]
310−selectMigration = select_
277+selectMigration = select_ #executed_at
311− (#executed_at `as` #executed_at)
312− ( from (table ((#migrations ! #schema_migrations) `as` #m))
278+ $ from (table (#schema_migrations))
313− & where_ (#name .== param @1))
279+ & where_ (#name .== param @1)
315−fetchAllMigrations
281+fetchAllMigrations :: Query_ MigrationsSchemas () MigrationRow
316− :: Query '[] '[] '["migrations" ::: MigrationsSchema] '[] (RowPG MigrationRow)
317−fetchAllMigrations =
282+fetchAllMigrations = select_
318− select_ ( #name `as` #migrationName
319− :* #executed_at `as` #executedAt)
283+ (#name `as` #migrationName :* #executed_at `as` #executedAt)
320− (from (table (#migrations ! #schema_migrations)))
284+ (from (table #schema_migrations))
322unsafePQ :: (Functor m) => PQ db0 db1 m x -> PQ db0' db1' m x
286unsafePQ :: (Functor m) => PQ db0 db1 m x -> PQ db0' db1' m x
323unsafePQ (PQ pq) = PQ $ fmap (SOP.K . SOP.unK) . pq . SOP.K . SOP.unK
287unsafePQ (PQ pq) = PQ $ fmap (SOP.K . SOP.unK) . pq . SOP.K . SOP.unK
325−data Command = Display
328− deriving (GHC.Generic, Show)
289+data Command = Display | AllUp | AllDown deriving (GHC.Generic, Show)
330defaultMain
291defaultMain
331 :: ByteString
292 :: ByteString
@@ -338,24 +299,20 @@ defaultMain connectTo migrations = do
338 maybe (pure ()) (performCommand connectTo migrations) command
299 maybe (pure ()) (performCommand connectTo migrations) command
340readCommandFromArgs :: IO (Maybe Command)
301readCommandFromArgs :: IO (Maybe Command)
341−readCommandFromArgs = do
302+readCommandFromArgs = getArgs >>= \case
344− ["db:migrate"] -> pure . Just $ AllUp
303+ ["migrate"] -> pure . Just $ AllUp
345− ["db:rollback"] -> pure . Just $ AllDown
304+ ["rollback"] -> pure . Just $ AllDown
346− ["db:status"] -> pure . Just $ Display
305+ ["status"] -> pure . Just $ Display
347− _ -> displayUsage >> pure Nothing
306+ _ -> displayUsage >> pure Nothing
349displayUsage :: IO ()
308displayUsage :: IO ()
350displayUsage = do
309displayUsage = do
351 putStrLn "Invalid command. Use:"
310 putStrLn "Invalid command. Use:"
352− putStrLn "db:migrate to run all available migrations"
311+ putStrLn "migrate to run all available migrations"
353− putStrLn "db:rollback to rollback all available migrations"
312+ putStrLn "rollback to rollback all available migrations"
354− putStrLn "db:status to display migrations run and migrations left to run"
313+ putStrLn "status to display migrations run and migrations left to run"
356−type RunMigrationName = Text
358−getRunMigrationNames :: (MonadBase IO m) => PQ db0 db0 m [RunMigrationName]
315+getRunMigrationNames :: (MonadBase IO m) => PQ db0 db0 m [Text]
359getRunMigrationNames =
316getRunMigrationNames =
360 fmap migrationName <$> (unsafePQ (define createMigrations & pqThen (runQuery fetchAllMigrations)) >>= getRows)
317 fmap migrationName <$> (unsafePQ (define createMigrations & pqThen (runQuery fetchAllMigrations)) >>= getRows)
@@ -365,12 +322,12 @@ displayListOfNames xs =
365 let singleName n = T.putStrLn $ "\t- " <> n
322 let singleName n = T.putStrLn $ "\t- " <> n
366 in traverse_ singleName xs
323 in traverse_ singleName xs
368−displayUnrunned :: [RunMigrationName] -> IO ()
325+displayUnrunned :: [Text] -> IO ()
369displayUnrunned unrunned =
326displayUnrunned unrunned =
370 T.putStrLn "Migrations left to run:"
327 T.putStrLn "Migrations left to run:"
371 >> displayListOfNames unrunned
328 >> displayListOfNames unrunned
373−displayRunned :: [RunMigrationName] -> IO ()
330+displayRunned :: [Text] -> IO ()
374displayRunned runned =
331displayRunned runned =
375 T.putStrLn "Migrations already run:"
332 T.putStrLn "Migrations already run:"
376 >> displayListOfNames runned
333 >> displayListOfNames runned