haskoin-wallet-0.9.4: src/Haskoin/Wallet/Migration.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
module Haskoin.Wallet.Migration where
import Conduit (MonadUnliftIO)
import Control.Monad
import Control.Monad.Except
import Control.Monad.IO.Class (MonadIO (liftIO))
import Control.Monad.Reader (MonadTrans (lift))
import Data.Text (Text)
import Database.Esqueleto.Legacy as E
import Haskoin
import Haskoin.Wallet.Config
import Haskoin.Wallet.Database
import qualified Haskoin.Wallet.Migration.V0_9_0 as V0_9_0
import Haskoin.Wallet.Migration.SemVersion
getDatabaseTables :: (MonadUnliftIO m) => DB m [Text]
getDatabaseTables = do
s <- rawSql "select name from sqlite_master where type='table'" []
return $ unSingle <$> s
databaseVersion :: (MonadUnliftIO m) => DB m (Maybe SemVersion)
databaseVersion = do
tables <- getDatabaseTables
if null tables
then return Nothing
else
if "d_b_version" `elem` tables -- Version table was created at v0.9.0
then Just <$> getVersion
else return $ Just V0_9_0.migrateFrom
migrateDB :: (MonadUnliftIO m) => Ctx -> Config -> DB m ()
migrateDB ctx cfg = do
resE <- runExceptT $ do
verM <- lift databaseVersion
case verM of
Nothing -> do
lift $ do
globalMigration
setVersion currentVersion
Just ver -> migrateDB_ ctx ver
return verM
case resE of
Left err -> do
transactionUndo -- Roll back the migration and exit
error err
Right verM -> unless (verM == Just currentVersion) $ migrateDB ctx cfg
migrateDB_ ::
(MonadUnliftIO m) => Ctx -> SemVersion -> ExceptT String (DB m) ()
migrateDB_ ctx dbVer
| dbVer == V0_9_0.migrateFrom = do
liftIO $ printDBMigration V0_9_0.migrateFrom V0_9_0.migrateTo
V0_9_0.migrateDB ctx
| dbVer == currentVersion = return ()
-- In case we have a patch version in the database
| toMinor dbVer == currentVersion = lift $ setVersion currentVersion
| otherwise = error $ "Invalid migration version: " <> verString dbVer
printDBMigration :: SemVersion -> SemVersion -> IO ()
printDBMigration fromV toV =
putStrLn $ "Migrating from " <> verString fromV <> " to " <> verString toV