{-#LANGUAGE TypeFamilies #-}
module Database.Migrant.Driver.Class
where

import Database.Migrant.MigrationName (MigrationName)
import Data.Text (Text)
import Text.Printf (printf)
import Control.Monad

-- | A migrations driver abstracts over the database to run over and the
-- associated migration mechanism.
class Driver d where
  --  | Migrations should be done transactionally, so we need to provide a
  --  way of wrapping things in a transaction. Implementations should make
  --  sure that whatever runs inside a transaction is actually transactional
  --  (i.e., atomic), including host exceptions.
  withTransaction :: (d -> IO a) -> d -> IO a

  -- | Initialize the migrations system on the backend. This should generally
  -- involve creating a table of ordered migration names, e.g.:
  -- @@@
  -- CREATE TABLE IF NOT EXISTS _migrations (id SERIAL PRIMARY KEY, name TEXT);
  -- @@@
  --
  -- **Note** that 'initMigrations' should be idempotent, that is, executing it
  -- when the migrations system has already been initialized should be a no-op.
  initMigrations :: d -> IO ()

  -- | Mark a migration as \"executed\". Typically, this will @INSERT@ a row
  -- into the migrations table.
  markUp :: MigrationName -> d -> IO ()

  -- | Mark a migration as \"not executed\" / \"rolled back\". Typically, this
  -- will @DELETE@ a row from the migrations table.
  markDown :: MigrationName -> d -> IO ()

  -- | Get the list of migrations applied to the backend, in the order they
  -- were applied.
  getMigrations :: d -> IO [MigrationName]

data DummyDriver = DummyDriver

instance Driver DummyDriver where
  withTransaction :: (DummyDriver -> IO a) -> DummyDriver -> IO a
withTransaction = (DummyDriver -> IO a) -> DummyDriver -> IO a
forall a. a -> a
id
  initMigrations :: DummyDriver -> IO ()
initMigrations = IO () -> DummyDriver -> IO ()
forall a b. a -> b -> a
const IO ()
forall (m :: * -> *) a. MonadPlus m => m a
mzero
  markUp :: MigrationName -> DummyDriver -> IO ()
markUp MigrationName
migration DummyDriver
_ =
    String -> MigrationName -> IO ()
forall r. PrintfType r => String -> r
printf String
"UP: %s" MigrationName
migration
  markDown :: MigrationName -> DummyDriver -> IO ()
markDown MigrationName
migration DummyDriver
_ =
    String -> MigrationName -> IO ()
forall r. PrintfType r => String -> r
printf String
"DOWN: %s" MigrationName
migration
  getMigrations :: DummyDriver -> IO [MigrationName]
getMigrations DummyDriver
_ = [MigrationName] -> IO [MigrationName]
forall (m :: * -> *) a. Monad m => a -> m a
return []