Skip to content

Commit

Permalink
Get lpsmith's work building
Browse files Browse the repository at this point in the history
  • Loading branch information
mightybyte committed Oct 18, 2014
1 parent 65fb41e commit 1d32a28
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 79 deletions.
3 changes: 2 additions & 1 deletion snaplet-postgresql-simple.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ Library

exposed-modules:
Snap.Snaplet.PostgresqlSimple
-- Snap.Snaplet.Auth.Backends.PostgresqlSimple
Snap.Snaplet.Auth.Backends.PostgresqlSimple

other-modules:
Snap.Snaplet.PostgresqlSimple.Internal
Paths_snaplet_postgresql_simple

build-depends:
Expand Down
9 changes: 5 additions & 4 deletions src/Snap/Snaplet/Auth/Backends/PostgresqlSimple.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import Database.PostgreSQL.Simple.Types
import Snap
import Snap.Snaplet.Auth
import Snap.Snaplet.PostgresqlSimple
import Snap.Snaplet.PostgresqlSimple.Internal
import Snap.Snaplet.Session
import Web.ClientSession
import Paths_snaplet_postgresql_simple
Expand Down Expand Up @@ -99,7 +100,7 @@ initPostgresAuth sess db = makeSnaplet "postgresql-auth" desc datadir $ do
-- | Create the user table if it doesn't exist.
createTableIfMissing :: PostgresAuthManager -> IO ()
createTableIfMissing PostgresAuthManager{..} = do
withPG' pamConn $ \conn -> do
liftPG' pamConn $ \conn -> do
res <- P.query_ conn $ Query $ T.encodeUtf8 $
"select relname from pg_class where relname='"
`T.append` schemaless (tblName pamTable) `T.append` "'"
Expand Down Expand Up @@ -174,13 +175,13 @@ instance FromRow AuthUser where

querySingle :: (ToRow q, FromRow a)
=> Postgres -> Query -> q -> IO (Maybe a)
querySingle pc q ps = withPG' pc $ \conn -> return . listToMaybe =<<
querySingle pc q ps = liftPG' pc $ \conn -> return . listToMaybe =<<
P.query conn q ps

authExecute :: ToRow q
=> Postgres -> Query -> q -> IO ()
authExecute pc q ps = do
withPG' pc $ \conn -> P.execute conn q ps
liftPG' pc $ \conn -> P.execute conn q ps
return ()

instance P.ToField Password where
Expand Down Expand Up @@ -305,7 +306,7 @@ instance IAuthBackend PostgresAuthManager where
save PostgresAuthManager{..} u@AuthUser{..} = do
let (qstr, params) = saveQuery pamTable u
let q = Query $ T.encodeUtf8 qstr
let action = withPG' pamConn $ \conn -> do
let action = liftPG' pamConn $ \conn -> do
res <- P.query conn q params
return $ Right $ fromMaybe u $ listToMaybe res
E.catch action onFailure
Expand Down
76 changes: 2 additions & 74 deletions src/Snap/Snaplet/PostgresqlSimple.hs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,8 @@ module Snap.Snaplet.PostgresqlSimple (
, withTransaction
, withTransactionLevel
, withTransactionMode
{--
, formatMany
, formatQuery
--}

-- Re-exported from postgresql-simple
, P.Query
Expand All @@ -104,13 +102,11 @@ module Snap.Snaplet.PostgresqlSimple (
, P.TransactionMode(..)
, P.IsolationLevel(..)
, P.ReadWriteMode(..)
{--
, P.begin
, P.beginLevel
, P.beginMode
, P.rollback
, P.commit
--}
, (P.:.)(..)
, ToRow(..)
, FromRow(..)
Expand Down Expand Up @@ -149,31 +145,14 @@ import Database.PostgreSQL.Simple.FromRow
import qualified Database.PostgreSQL.Simple as P
import qualified Database.PostgreSQL.Simple.Transaction as P
import Snap
import Snap.Snaplet.PostgresqlSimple.Internal
import Paths_snaplet_postgresql_simple

-- This is actually more portable than using <>
(++) :: Monoid a => a -> a -> a
(++) = mappend
infixr 5 ++

------------------------------------------------------------------------------
-- | The state for the postgresql-simple snaplet. To use it in your app
-- include this in your application state and use pgsInit to initialize it.
data Postgres = PostgresPool (Pool P.Connection)
| PostgresConn P.Connection


------------------------------------------------------------------------------
-- | Instantiate this typeclass on 'Handler b YourAppState' so this snaplet
-- can find the connection source. If you need to have multiple instances of
-- the postgres snaplet in your application, then don't provide this instance
-- and leverage the default instance by using \"@with dbLens@\" in front of calls
-- to snaplet-postgresql-simple functions.
class (MonadCatchIO m) => HasPostgres m where
getPostgresState :: m Postgres
setLocalPostgresState :: Postgres -> m a -> m a


------------------------------------------------------------------------------
-- | Default instance
instance HasPostgres (Handler b Postgres) where
Expand Down Expand Up @@ -305,34 +284,6 @@ pgsInit' config = makeSnaplet "postgresql-simple" description datadir $ do
initHelper config


------------------------------------------------------------------------------
-- | Data type holding all the snaplet's config information.
data PGSConfig = PGSConfig
{ pgsConnStr :: ByteString
-- ^ A libpq connection string.
, pgsNumStripes :: Int
-- ^ The number of distinct sub-pools to maintain. The smallest
-- acceptable value is 1.
, pgsIdleTime :: Double
-- ^ Amount of time for which an unused resource is kept open. The
-- smallest acceptable value is 0.5 seconds.
, pgsResources :: Int
-- ^ Maximum number of resources to keep open per stripe. The smallest
-- acceptable value is 1.
}


------------------------------------------------------------------------------
-- | Returns a config object with default values and the specified connection
-- string.
pgsDefaultConfig :: ByteString
-- ^ A connection string such as \"host=localhost
-- port=5432 dbname=mydb\"
-> PGSConfig
pgsDefaultConfig connstr = PGSConfig connstr 1 5 20



------------------------------------------------------------------------------
-- | Builds a PGSConfig object from a configurator Config object. This
-- function uses getConnectionString to construct the connection string. The
Expand All @@ -355,27 +306,6 @@ initHelper PGSConfig{..} = do
return $ PostgresPool pool


------------------------------------------------------------------------------
-- | Function that reserves a single connection for the duration of the given
-- action.
withPG :: (HasPostgres m)
=> m b -> m b
withPG f = do
s <- getPostgresState
case s of
(PostgresPool p) -> withResource p (\c -> setLocalPostgresState (PostgresConn c) f)
(PostgresConn _) -> f

------------------------------------------------------------------------------
-- | Convenience function for executing a function that needs a database
-- connection.
liftPG :: (HasPostgres m) => (P.Connection -> IO b) -> m b
liftPG f = do
s <- getPostgresState
case s of
(PostgresPool p) -> liftIO (withResource p f)
(PostgresConn c) -> liftIO (f c)

------------------------------------------------------------------------------
-- | See 'P.query'
query :: (HasPostgres m, ToRow q, FromRow r)
Expand Down Expand Up @@ -500,13 +430,11 @@ withTransactionMode mode act = withPG $ CIO.block $ do
liftPG $ P.commit
return r

{--
formatMany :: (ToRow q, HasPostgres m)
=> P.Query -> [q] -> m ByteString
formatMany q qs = liftPG (\c -> P.formatMany c q qs)


formatQuery :: (ToRow q, HasPostgres m, MonadCatchIO m)
=> P.Query -> q -> m ByteString
formatQuery q qs = withPG (\c -> liftIO $ P.formatQuery c q qs)
--}
formatQuery q qs = liftPG (\c -> P.formatQuery c q qs)
90 changes: 90 additions & 0 deletions src/Snap/Snaplet/PostgresqlSimple/Internal.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ViewPatterns #-}

module Snap.Snaplet.PostgresqlSimple.Internal where

import Prelude hiding ((++))
import Control.Monad.CatchIO (MonadCatchIO)
import Control.Monad.IO.Class
import Data.ByteString (ByteString)
import Data.Pool
import qualified Database.PostgreSQL.Simple as P

------------------------------------------------------------------------------
-- | The state for the postgresql-simple snaplet. To use it in your app
-- include this in your application state and use pgsInit to initialize it.
data Postgres = PostgresPool (Pool P.Connection)
| PostgresConn P.Connection


------------------------------------------------------------------------------
-- | Instantiate this typeclass on 'Handler b YourAppState' so this snaplet
-- can find the connection source. If you need to have multiple instances of
-- the postgres snaplet in your application, then don't provide this instance
-- and leverage the default instance by using \"@with dbLens@\" in front of calls
-- to snaplet-postgresql-simple functions.
class (MonadCatchIO m) => HasPostgres m where
getPostgresState :: m Postgres
setLocalPostgresState :: Postgres -> m a -> m a


------------------------------------------------------------------------------
-- | Data type holding all the snaplet's config information.
data PGSConfig = PGSConfig
{ pgsConnStr :: ByteString
-- ^ A libpq connection string.
, pgsNumStripes :: Int
-- ^ The number of distinct sub-pools to maintain. The smallest
-- acceptable value is 1.
, pgsIdleTime :: Double
-- ^ Amount of time for which an unused resource is kept open. The
-- smallest acceptable value is 0.5 seconds.
, pgsResources :: Int
-- ^ Maximum number of resources to keep open per stripe. The smallest
-- acceptable value is 1.
}


------------------------------------------------------------------------------
-- | Returns a config object with default values and the specified connection
-- string.
pgsDefaultConfig :: ByteString
-- ^ A connection string such as \"host=localhost
-- port=5432 dbname=mydb\"
-> PGSConfig
pgsDefaultConfig connstr = PGSConfig connstr 1 5 20



------------------------------------------------------------------------------
-- | Function that reserves a single connection for the duration of the given
-- action.
withPG :: (HasPostgres m)
=> m b -> m b
withPG f = do
s <- getPostgresState
case s of
(PostgresPool p) -> withResource p (\c -> setLocalPostgresState (PostgresConn c) f)
(PostgresConn _) -> f


------------------------------------------------------------------------------
-- | Convenience function for executing a function that needs a database
-- connection.
liftPG :: (HasPostgres m) => (P.Connection -> IO b) -> m b
liftPG f = do
s <- getPostgresState
liftPG' s f


------------------------------------------------------------------------------
-- | Convenience function for executing a function that needs a database
-- connection.
liftPG' :: MonadIO m => Postgres -> (P.Connection -> IO b) -> m b
liftPG' (PostgresPool p) f = liftIO (withResource p f)
liftPG' (PostgresConn c) f = liftIO (f c)

0 comments on commit 1d32a28

Please sign in to comment.