postgresql-config (empty) → 0.0.1
raw patch · 7 files changed
+258/−0 lines, 7 filesdep +aesondep +basedep +bytestringsetup-changed
Dependencies added: aeson, base, bytestring, monad-control, mtl, postgresql-simple, resource-pool, time
Files
- LICENSE +30/−0
- README.md +30/−0
- Setup.hs +2/−0
- examples/Main.hs +14/−0
- examples/pgconfig.yml +8/−0
- postgresql-config.cabal +43/−0
- src/Database/PostgreSQL/Config.hs +131/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015, Aleksey Uimanov++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * 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.++ * Neither the name of Aleksey Uimanov nor the names of other+ 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+OWNER 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.
+ README.md view
@@ -0,0 +1,30 @@+# What?++Simple types and set of functions to quickly add configuration of+postgresql to your Yesod site or whatever.++# How?++Add separate file or section inside your existing config like that++```yml+database: "dbname"+host: "127.0.0.1" # optional+port: "5432" # optional+user: "dbuser"+password: "pass"+poolsize: "10" # optional maximum connections in pool+pooltimeout: "60" # optional minimum connection lifetime+poolstripes: "1" # optional count of stripes in pool+```++and then in your program something like that++```haskell+conf <- decodeFile "pgconfig.yml"+ >>= maybe (fail "Could not parse pgconfig.yml") return+pool <- createPGPool conf+pingPGPool pool+```++So now you have a pool and can perform queries any way you like.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ examples/Main.hs view
@@ -0,0 +1,14 @@+module Main where++import Data.Yaml+import Database.PostgreSQL.Config+++main :: IO ()+main = do+ conf <- decodeFile "pgconfig.yml"+ >>= maybe (fail "Oups!") return+ pool <- createPGPool conf+ putStrLn "Pool created"+ pingPGPool pool+ putStrLn "Connection performed"
+ examples/pgconfig.yml view
@@ -0,0 +1,8 @@+database: "dbname"+host: "127.0.0.1" # optional+port: "5432" # optional+user: "dbuser"+password: "pass"+poolsize: "10" # optional maximum connections in pool+pooltimeout: "60" # optional minimum connection lifetime+poolstripes: "1" # optional count of stripes in pool
+ postgresql-config.cabal view
@@ -0,0 +1,43 @@+name: postgresql-config+version: 0.0.1++synopsis: Types for easy adding postgresql configuration to your program++license: BSD3+license-file: LICENSE+author: Aleksey Uimanov+maintainer: s9gf4ult@gmail.com++category: Database+build-type: Simple+cabal-version: >=1.10++extra-source-files: examples/Main.hs+ , examples/pgconfig.yml+ , README.md++homepage: https://bitbucket.org/s9gf4ult/postgresql-config+source-repository head+ type: git+ location: git@bitbucket.org:s9gf4ult/postgresql-config.git++library+ hs-source-dirs: src+ default-language: Haskell2010++ default-extensions: RecordWildCards+ , DeriveDataTypeable+ , DeriveGeneric+ , FlexibleContexts+ , OverloadedStrings++ build-depends: base >=4.7 && <4.8+ , aeson+ , bytestring+ , monad-control+ , mtl+ , postgresql-simple+ , resource-pool+ , time++ exposed-modules: Database.PostgreSQL.Config
+ src/Database/PostgreSQL/Config.hs view
@@ -0,0 +1,131 @@+module Database.PostgreSQL.Config+ ( -- * Types+ PostgresConf(..)+ , PGPool(..)+ -- * Pool creation+ , createPGPool+ , pingPGPool+ -- * Helpers for __postgresql-query__+ , withPGPool+ , withPGPoolPrim+ ) where++import Prelude++import Control.Monad.Reader+import Control.Monad.Trans.Control+import Data.Aeson+import Data.ByteString ( ByteString )+import Data.Pool+import Data.Time+import Data.Typeable+import GHC.Generics++import qualified Database.PostgreSQL.Simple as PG++-- | Connection pool. Must be created from settings using+-- 'createPGPool'+newtype PGPool =+ PGPool+ { unPGPool :: (Pool PG.Connection)+ } deriving ( Show, Typeable, Generic )++{- | Configuration parsed from json or yaml file, or obtained by any+other way. Example configuration yml is:++@+database: "dbname"+host: "127.0.0.1" \# optional+port: "5432" \# optional+user: "dbuser"+password: "pass"+poolsize: "10" \# optional maximum connections in pool+pooltimeout: "60" \# optional minimum connection lifetime+poolstripes: "1" \# optional count of stripes in pool+@++-}++data PostgresConf = PostgresConf+ { pgConnStr :: ByteString+ -- ^ The connection string.+ , pgPoolSize :: Int+ -- ^ How many connections should be held on the connection pool.+ , pgPoolTimeout :: NominalDiffTime+ -- ^ Timeout to stay connection active+ , pgPoolStripes :: Int+ -- ^ Stripes in the pool+ } deriving (Ord, Eq, Show)++instance FromJSON PostgresConf where+ parseJSON = withObject "PostgresConf" $ \o -> do+ database <- o .: "database"+ host <- o .:? "host" .!= "127.0.0.1"+ port <- o .:? "port" .!= 5432+ user <- o .: "user"+ password <- o .: "password"+ pSize <- o .:? "poolsize" .!= 10+ pTimeout <- o .:? "pooltimeout" .!= 60+ pStripes <- o .:? "poolstripes" .!= 1+ let ci = PG.ConnectInfo+ { PG.connectHost = host+ , PG.connectPort = port+ , PG.connectUser = user+ , PG.connectPassword = password+ , PG.connectDatabase = database+ }+ cstr = PG.postgreSQLConnectionString ci+ return $ PostgresConf+ { pgConnStr = cstr+ , pgPoolSize = pSize+ , pgPoolTimeout = fromInteger pTimeout+ , pgPoolStripes = pStripes+ }++-- | Create pool from parsed configuration+createPGPool :: PostgresConf -> IO PGPool+createPGPool PostgresConf{..} =+ fmap PGPool+ $ createPool+ (PG.connectPostgreSQL pgConnStr)+ PG.close+ pgPoolStripes+ pgPoolTimeout+ pgPoolSize+++{- | Combinator for simple implementation of 'withPGConnection' method+from package __postgresql-query__. Typical usage is:++@+instance HasPostgres (HandlerT App IO) where+ withPGConnection = withPGPool appPGPool+@+-}+withPGPool :: (MonadReader site m, MonadBaseControl IO m)+ => (site -> PGPool)+ -> (PG.Connection -> m a)+ -> m a+withPGPool extract action = do+ (PGPool pool) <- asks extract+ withResource pool action++{- | Another combinator to implement 'withPGConnection'++@+instance HasPostgres (OurMonadT IO) where+ withPGConnection = withPGPoolPrim $ getPGPool \<$\> getSomeThing+@+-}+withPGPoolPrim :: (MonadBaseControl IO m)+ => m PGPool+ -> (PG.Connection -> m a)+ -> m a+withPGPoolPrim pget action = do+ (PGPool pool) <- pget+ withResource pool action++-- | Force to create at least one connection in pool. Usefull to check+-- connection settings at program start time+pingPGPool :: PGPool -> IO ()+pingPGPool (PGPool pool) = withResource pool $ const (return ())