1
0
Fork 0
mirror of https://code.sup39.dev/repos/Wqawg synced 2024-12-28 23:34:51 +09:00

I made upgrades to the DB migration system in Funbot, apply them here too

This commit is contained in:
fr33domlover 2018-02-25 11:14:07 +00:00
parent b8681e2681
commit 3b4bd2a5e8
5 changed files with 38 additions and 38 deletions

View file

@ -124,7 +124,7 @@ data Unique = Unique
, uniqueFields :: [FieldName] , uniqueFields :: [FieldName]
} }
type SchemaT b m a = ReaderT (SchemaBackend b) (ReaderT b m) a type SchemaT b m = ReaderT (SchemaBackend b) (ReaderT b m)
-- | Ideally we'd make the @backend@ provide schema related specifics. The -- | Ideally we'd make the @backend@ provide schema related specifics. The
-- problem is that e.g. @SqlBackend@ is already defined in @persistent@ and -- problem is that e.g. @SqlBackend@ is already defined in @persistent@ and
@ -137,13 +137,15 @@ type SchemaT b m a = ReaderT (SchemaBackend b) (ReaderT b m) a
-- explicitly specifying the schema backend and using 'lift' for data manip. -- explicitly specifying the schema backend and using 'lift' for data manip.
class PersistSchema backend where class PersistSchema backend where
data SchemaBackend backend -- :: * data SchemaBackend backend -- :: *
hasSchemaEntity
:: MonadIO m => SchemaT backend m Bool
addEntity addEntity
:: MonadIO m => Entity -> SchemaT backend m () :: MonadIO m => Entity -> SchemaT backend m ()
removeEntity removeEntity
:: MonadIO m => EntityName -> SchemaT backend m () :: MonadIO m => EntityName -> SchemaT backend m ()
addField addField
:: MonadIO m :: MonadIO m
=> EntityName -> Field -> Maybe Text -> SchemaT backend m () => EntityName -> Maybe Text -> Field -> SchemaT backend m ()
renameField renameField
:: MonadIO m :: MonadIO m
=> EntityName -> FieldName -> FieldName -> SchemaT backend m () => EntityName -> FieldName -> FieldName -> SchemaT backend m ()

View file

@ -1,6 +1,6 @@
{- This file is part of Vervis. {- This file is part of Vervis.
- -
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>. - Written in 2016, 2017 by fr33domlover <fr33domlover@riseup.net>.
- -
- Copying is an act of love. Please copy, reuse and share. - Copying is an act of love. Please copy, reuse and share.
- -
@ -79,6 +79,11 @@ idSql = "id SERIAL8 PRIMARY KEY UNIQUE"
schemaBackend :: SchemaBackend SqlBackend schemaBackend :: SchemaBackend SqlBackend
schemaBackend = SqlSchemaBackend schemaBackend = SqlSchemaBackend
{ ssbRefType = SqlInt64 { ssbRefType = SqlInt64
, ssbDoesTableExist =
"SELECT COUNT(*) FROM pg_catalog.pg_tables \
\ WHERE schemaname != 'pg_catalog' AND \
\ schemaname != 'information_schema' AND \
\ tablename = ?"
, ssbCreateTable = \ table columns -> mconcat , ssbCreateTable = \ table columns -> mconcat
[ "CREATE TABLE ", table2sql table, " (" [ "CREATE TABLE ", table2sql table, " ("
, idSql , idSql

View file

@ -34,9 +34,10 @@ import Data.Char (isUpper, toLower)
import Data.Foldable (traverse_) import Data.Foldable (traverse_)
import Data.Maybe (isJust) import Data.Maybe (isJust)
import Data.Text (Text) import Data.Text (Text)
import Database.Persist.Sql (Sql, SqlBackend, rawExecute) import Database.Persist.Sql hiding (FieldType, Entity, Column)
import Database.Persist.Types (SqlType) import Database.Persist.Types (SqlType)
import qualified Data.Conduit.List as CL (head)
import qualified Data.Text as T import qualified Data.Text as T
import Database.Persist.Schema import Database.Persist.Schema
@ -56,6 +57,16 @@ data Column = Column
exec :: MonadIO m => Sql -> SchemaT SqlBackend m () exec :: MonadIO m => Sql -> SchemaT SqlBackend m ()
exec t = lift $ rawExecute t [] exec t = lift $ rawExecute t []
inquire
:: MonadIO m => Sql -> [PersistValue] -> SchemaT SqlBackend m PersistValue
inquire t vs = lift $ withRawQuery t vs $ do
l <- CL.head
case l of
Just [x] -> return x
Just [] -> error $ "inquire: got empty list " ++ show t
Just xs -> error $ "inquire: got multiple values " ++ show xs ++ show t
Nothing -> error $ "inquire: got nothing " ++ show t
camelWords :: Text -> [Text] camelWords :: Text -> [Text]
camelWords ident = camelWords ident =
let low = toLower let low = toLower
@ -100,6 +111,7 @@ mkcolumn ssb (Field name typ mnull) = Column
instance PersistSchema SqlBackend where instance PersistSchema SqlBackend where
data SchemaBackend SqlBackend = SqlSchemaBackend data SchemaBackend SqlBackend = SqlSchemaBackend
{ ssbRefType :: SqlType { ssbRefType :: SqlType
, ssbDoesTableExist :: Sql
, ssbCreateTable :: TableName -> [Column] -> Sql , ssbCreateTable :: TableName -> [Column] -> Sql
, ssbRenameTable :: TableName -> TableName -> Sql , ssbRenameTable :: TableName -> TableName -> Sql
, ssbDropTable :: TableName -> Sql , ssbDropTable :: TableName -> Sql
@ -119,6 +131,16 @@ instance PersistSchema SqlBackend where
:: TableName -> ConstraintName -> ConstraintName -> Sql :: TableName -> ConstraintName -> ConstraintName -> Sql
, ssbDropConstraint :: TableName -> ConstraintName -> Sql , ssbDropConstraint :: TableName -> ConstraintName -> Sql
} }
hasSchemaEntity = do
ssb <- ask
let table =
toPersistValue $ unTableName $ entity2table $ EntityName $
T.pack "SchemaVersion"
v <- inquire (ssbDoesTableExist ssb) [table]
case v of
PersistInt64 1 -> return True
PersistInt64 0 -> return False
_ -> error "hasSchemaEntity: count inquiry didn't return a number"
addEntity (Entity name fields uniques) = do addEntity (Entity name fields uniques) = do
ssb <- ask ssb <- ask
exec $ exec $
@ -127,7 +149,7 @@ instance PersistSchema SqlBackend where
removeEntity name = do removeEntity name = do
ssb <- ask ssb <- ask
exec $ ssbDropTable ssb $ entity2table name exec $ ssbDropTable ssb $ entity2table name
addField ent (Field name typ mnull) mdef = do addField ent mdef (Field name typ mnull) = do
ssb <- ask ssb <- ask
exec $ exec $
ssbAddColumn ssb ssbAddColumn ssb

View file

@ -28,46 +28,16 @@ import Database.Persist.Sql (SqlBackend, toSqlKey)
import Database.Persist.Schema import Database.Persist.Schema
import Database.Persist.Schema.PostgreSQL (schemaBackend) import Database.Persist.Schema.PostgreSQL (schemaBackend)
import Database.Persist.Migration
import Vervis.Model import Vervis.Model
key :: SchemaVersionId
key = toSqlKey 1
getDbSchemaVersion :: MonadIO m => ReaderT SqlBackend m (Maybe Int)
getDbSchemaVersion = fmap schemaVersionNumber <$> get key
setDbSchemaVersion :: MonadIO m => Int -> ReaderT SqlBackend m ()
setDbSchemaVersion v = repsert key $ SchemaVersion v
-- | Run the migration system. The second parameter is the list of migration
-- actions in chronological order. The migration process is:
--
-- * Check the schema version of the DB
-- * Compare to the schema version of the app, which is the length of the list
-- * If any migrations are required, run them
-- * Update the schema version in the DB
runMigrations
:: MonadIO m
=> SchemaBackend SqlBackend
-> [SchemaT SqlBackend m ()]
-> ReaderT SqlBackend m ()
runMigrations sb migrations = do
dver <- fromMaybe 0 <$> getDbSchemaVersion
let aver = length migrations
case compare aver dver of
LT -> error "Older app version running with newer DB schema version"
EQ -> return ()
GT -> do
let migs = drop dver migrations
runReaderT (sequence migs) sb
setDbSchemaVersion aver
changes :: MonadIO m => [SchemaT SqlBackend m ()] changes :: MonadIO m => [SchemaT SqlBackend m ()]
changes = changes =
[ addField "Workflow" [ addField "Workflow"
(Field "scope" (FTPrim SqlString) NotNull)
(Just "'WSSharer'") (Just "'WSSharer'")
(Field "scope" (FTPrim SqlString) NotNull)
--, lift $ do
] ]
migrateDB :: MonadIO m => ReaderT SqlBackend m () migrateDB :: MonadIO m => ReaderT SqlBackend m ()

View file

@ -83,6 +83,7 @@ library
Database.Persist.Local.Sql Database.Persist.Local.Sql
Database.Persist.Local.Sql.Orphan.Common Database.Persist.Local.Sql.Orphan.Common
Database.Persist.Local.Sql.Orphan.PersistQueryForest Database.Persist.Local.Sql.Orphan.PersistQueryForest
Database.Persist.Migration
Database.Persist.Schema Database.Persist.Schema
Database.Persist.Schema.PostgreSQL Database.Persist.Schema.PostgreSQL
Database.Persist.Schema.Sql Database.Persist.Schema.Sql