module Database.Connection where
import Control.Monad.IO.Class (liftIO, MonadIO)
import Control.Concurrent
import Control.Exception (finally)
import Database.PostgreSQL.Simple
import Network.URI
import System.IO.Unsafe
conns :: Chan Connection
conns = unsafePerformIO $ newChan
createConnection :: ConnectInfo -> IO ()
createConnection config = connect config >>= writeChan conns
parseDbURL :: String -> ConnectInfo
parseDbURL uri = case mdbURI of
Nothing -> defaultConnectInfo
Just dbURI | uriScheme dbURI == "postgres:" ->
let auth = uriAuthority dbURI
in ConnectInfo { connectPort = toPort auth
, connectHost = toHostname auth
, connectUser = toUsername auth
, connectPassword = toPassword auth
, connectDatabase = toDatabase . uriPath $ dbURI}
| otherwise -> defaultConnectInfo
where mdbURI = parseURI uri
toPort (Just (URIAuth _ _ "")) = 5432
toPort (Just (URIAuth _ _ (':':p))) = read p
toPort _ = 5432
toHostname (Just (URIAuth _ h _)) = h
toHostname _ = "localhost"
toUsername (Just (URIAuth ua _ _)) = takeWhile (\x -> x /= ':' && x /= '@') ua
toUsername Nothing = ""
toPassword (Just (URIAuth ua _ _)) = case dropWhile (/= ':') ua of
(':':password) -> takeWhile (/= '@') password
_ -> ""
toPassword Nothing = ""
toDatabase ('/':db) = db
toDatabase _ = ""
withConnection :: MonadIO m => (Connection -> IO b) -> m b
withConnection func = liftIO $ do
conn <- readChan conns
finally (func conn) (writeChan conns conn)