packages feed

database-migrate (empty) → 0.0.1

raw patch · 6 files changed

+218/−0 lines, 6 filesdep +basedep +bytestringdep +containerssetup-changed

Dependencies added: base, bytestring, containers, directory, either, filepath, postgresql-simple, text, time, transformers

Files

+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2010, Mark Hibberd <mark@hibberd.id.au>+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++ 1. Redistributions of source code must retain the above copyright+    notice, this list of conditions and the following disclaimer.+ 2. Redistributions in binary form must reproduce the above copyright+    notice, this list of conditions and the following disclaimer in the+    documentation and/or other materials provided with the distribution.+ 3. Neither the name of the <ORGANIZATION> nor the names of its contributors+    may be used to endorse or promote products derived from this software+    without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main = defaultMain
+ database-migrate.cabal view
@@ -0,0 +1,58 @@+Name:               database-migrate+Version:            0.0.1+License:            BSD3+License-File:       LICENSE+Author:             Mark Hibberd <mark@hibberd.id.au>+Maintainer:         Mark Hibberd <mark@hibberd.id.au>+Copyright:          (c) 2012 Mark Hibberd+Synopsis:           Database versioning and migration+Category:           Database+Homepage:           https://github.com/markhibberd/database-migrate+Bug-reports:           https://github.com/markhibberd/database-migrate/issues+Cabal-Version:      >= 1.6+Build-Type:         Simple+Description:+  A database versioning and migration library.+  .+  /Note/: that this library is under heavy development, currently+  the PostgreSQL implementation is functional, but+  expected to change. It is intended that a type safe+  migration api and command line tools be added to this+  library before it be considered stable.++Source-Repository   head+  Type:             git+  Location:         https://github.com/markhibberd/migrate.git++Flag                small_base+  Description:      Choose the new, split-up base package.++Library+  Build-Depends:+                    base >= 3 && < 5+                    , text                          >= 0.11       && < 0.12+                    , directory                     >= 1.0        && < 2.0+                    , filepath                      >= 1.0        && < 2.0+                    , bytestring                    >= 0.9        && < 0.10+                    , time                          >= 1.0        && < 2.0+                    , postgresql-simple             >= 0.1        && < 1.0+                    , containers                    >= 0.4        && < 0.5+                    , either                        >= 3.0.2      && < 4.0+                    , transformers                  >= 0.2        && < 0.4++  GHC-Options:+                    -Wall -fno-warn-orphans++  Hs-Source-Dirs:+                    src++  Exposed-Modules:+                    Database.Migrate+                    Database.Migrate.Core+                    Database.Migrate.PostgreSQL++  Extensions:+                    MultiParamTypeClasses+                    OverloadedStrings++
+ src/Database/Migrate.hs view
@@ -0,0 +1,21 @@+-- |+-- Module:      Database.Migrate+-- Copyright:   (c) 2012 Mark Hibberd+-- License:     BSD3+-- Maintainer:  Mark Hibberd <mark@hibberd.id.au>+-- Portability: portable+--+-- A library to assist with managing database versioning+-- and migration.+--+-- Note: This library is under heavy development, currently+--       the PostgreSQL implementation is functional, but+--       expected to change. It is intended that a type safe+--       migration api and command line tools be added to this+--       library before it be considered stable.+module Database.Migrate (module X) where++import Database.Migrate.Core as X+-- import Database.Migrate.MySQL as X+import Database.Migrate.PostgreSQL as X+
+ src/Database/Migrate/Core.hs view
@@ -0,0 +1,72 @@+{-#LANGUAGE OverloadedStrings #-}+module Database.Migrate.Core where++import Control.Monad+import Control.Monad.IO.Class+import Control.Monad.Trans.Class+import Control.Monad.Trans.Either++import qualified Data.Set as S+import Data.Text hiding (foldr, filter, reverse, length)++import System.FilePath+import System.Directory+import System.IO++type MigrationId = Text+type Ddl = Text++data Migration =+  Migration {+      migration :: MigrationId+    , up :: Text+    , down :: Text+    , upsource :: Maybe FilePath+    , downsource :: Maybe FilePath+    }++data Context = Context {+    succeeded :: [MigrationId]+  , failed :: MigrationId+  , msg :: Text+  , rolledback :: Bool+  } deriving (Eq, Show)++type MigrationResultT = EitherT Context++class Monad m => MigrateDatabase m c where+  initialize :: c -> m ()+  runMigrations :: c -> (Migration -> Ddl) -> [Migration] -> MigrationResultT m [MigrationId]+  getMigrations :: c -> m [MigrationId]++pick :: [Migration] -> [MigrationId] -> [Migration]+pick ms ids =+  let available = foldr (S.insert . migration) S.empty ms+      installed = S.fromList ids+      torun = S.difference available installed+   in filter (\m -> S.member (migration m) torun) ms++latest :: MigrateDatabase m c => c -> [Migration] -> MigrationResultT m [MigrationId]+latest c migrations =+  lift (getMigrations c) >>= \installed -> runMigrations c up (pick migrations installed)++find :: FilePath -> EitherT String IO [Migration]+find b = liftIO (getDirectoryContents b) >>= \fs -> liftIO (migrationids b fs) >>=+  mapM (\p ->+         do downexists <- liftIO $ doesFileExist (b </> p <.> "down.sql")+            unless downexists (left $ "no down.sql for migration [" ++ p ++ "]")+            u <- liftIO . readFile $ b </> p <.> "up.sql"+            d <- liftIO . readFile $ b </> p <.> "down.sql"+            right (Migration (pack p) (pack u) (pack d) (Just $ b </> p <.> "up.sql") (Just $ b </> p <.> "down.sql")))++migrationids :: FilePath -> [FilePath] -> IO [String]+migrationids b ps =+  filterM (\p -> doesFileExist (b </> p)) ps >>= \files ->+    return (filter (\p -> takeExtensions p == ".up.sql" ) files) >>= \ups -> return (fmap dropExtensions ups)++readFile' :: FilePath -> IO String+readFile' p = withFile p ReadMode hGetContents++hGetContents' :: Handle -> IO String+hGetContents' h = hGetContents h >>= \s -> length s `seq` return s+
+ src/Database/Migrate/PostgreSQL.hs view
@@ -0,0 +1,37 @@+{-#LANGUAGE OverloadedStrings #-}+module Database.Migrate.PostgreSQL where++import Control.Exception (SomeException(..), handle)+import Control.Monad+import Control.Monad.IO.Class+import Control.Monad.Trans.Either++import Data.Text hiding (filter, reverse)+import Data.String (IsString(..))++import Database.PostgreSQL.Simple+import Database.Migrate.Core++instance MigrateDatabase IO Connection where+  initialize c = void $ execute_ c "CREATE TABLE IF NOT EXISTS MIGRATION_INFO (MIGRATION VARCHAR(50) PRIMARY KEY)"+  runMigrations = runall+  getMigrations c = fmap (fmap fromOnly) (query_ c "SELECT MIGRATION FROM MIGRATION_INFO")++record :: Connection -> MigrationId -> IO ()+record conn mid = void $ execute conn "INSERT INTO MIGRATION_INFO VALUES (?)" (Only mid)++runall :: Connection -> (Migration -> Ddl) -> [Migration] -> MigrationResultT IO [MigrationId]+runall c f ms =+  liftIO (begin c) >>+    (foldM (\rs m ->+             EitherT $+               do e <- runEitherT (saferun c f m)+                  case e of+                    Left emsg -> rollback c >> (return . Left $ Context (reverse rs) (migration m) emsg True)+                    Right r -> return . Right $ r:rs) [] ms) >>= \result -> liftIO (commit c) >> return (reverse result)++saferun :: Connection -> (Migration -> Ddl) -> Migration -> EitherT Text IO MigrationId+saferun c f m = EitherT $ handle (\e -> return (Left (pack . show $ (e :: SomeException)))) (fmap Right $ run c f m)++run :: Connection -> (Migration -> Ddl) -> Migration -> IO MigrationId+run c f m = execute_ c (fromString . unpack $ f m) >> record c (migration m) >> return (migration m)