{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} module Traction.Migration ( Migration (..) , migrate ) where import qualified Data.List as List import Data.Text (Text) import qualified Data.Set as Set import Database.PostgreSQL.Simple.SqlQQ (sql) import qualified Database.PostgreSQL.Simple as Postgresql import Traction.Prelude import Traction.Control import qualified Traction.Sql as Sql data Migration = Migration { migrationName :: Text , migrationQuery :: Postgresql.Query } deriving (Eq, Show) migrate :: [Migration] -> Db [Migration] migrate migrations = do void $ Sql.execute_ "SET client_min_messages TO WARNING" void $ Sql.execute_ [sql| CREATE TABLE IF NOT EXISTS migrations (migration TEXT PRIMARY KEY) |] installed <- (fmap . fmap) Postgresql.fromOnly $ Sql.query_ [sql| SELECT migration FROM migrations |] forM (diff migrations installed) $ \migration -> do void $ Sql.execute_ $ migrationQuery migration void $ Sql.execute [sql| INSERT INTO migrations (migration) VALUES (?) |] (Postgresql.Only $ migrationName migration) pure migration diff :: [Migration] -> [Text] -> [Migration] diff migrations installed = let installed' = Set.fromList installed missing = List.filter (\x -> not . Set.member (migrationName x) $ installed') migrations in missing