module Database.PostgreSQL.Query.SqlBuilder
(
SqlBuilder(..)
, ToSqlBuilder(..)
, Qp(..)
, emptyB
, runSqlBuilder
, mkIdent
, mkValue
, sqlBuilderPure
, sqlBuilderFromField
) where
import Prelude
import Blaze.ByteString.Builder
( Builder, toByteString )
import Control.Applicative
import Data.ByteString ( ByteString )
import Data.Monoid
import Data.String
import Data.Text ( Text )
import Data.Typeable ( Typeable )
import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.Internal
( buildAction )
import Database.PostgreSQL.Simple.ToField
import Database.PostgreSQL.Simple.Types
( Query(..), Identifier(..) )
import GHC.Generics ( Generic )
import qualified Blaze.ByteString.Builder.ByteString as BB
import qualified Blaze.ByteString.Builder.Char.Utf8 as BB
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
class ToSqlBuilder a where
toSqlBuilder :: a -> SqlBuilder
data Qp = forall row. (ToRow row) => Qp Query row
instance ToSqlBuilder Qp where
toSqlBuilder (Qp q row) = SqlBuilder $ \c ->
BB.fromByteString <$> formatQuery c q row
newtype SqlBuilder =
SqlBuilder
{ sqlBuild :: Connection -> IO Builder }
deriving (Typeable, Generic)
emptyB :: SqlBuilder
emptyB = mempty
runSqlBuilder :: Connection -> SqlBuilder -> IO Query
runSqlBuilder con (SqlBuilder bld) =
(Query . toByteString) <$> bld con
instance IsString SqlBuilder where
fromString s =
let b = fromString s :: ByteString
in toSqlBuilder b
instance ToSqlBuilder SqlBuilder where
toSqlBuilder = id
instance ToSqlBuilder Builder where
toSqlBuilder = sqlBuilderPure
instance ToSqlBuilder ByteString where
toSqlBuilder = sqlBuilderPure . BB.fromByteString
instance ToSqlBuilder BL.ByteString where
toSqlBuilder = sqlBuilderPure . BB.fromLazyByteString
instance ToSqlBuilder String where
toSqlBuilder = sqlBuilderPure . BB.fromString
instance ToSqlBuilder T.Text where
toSqlBuilder = sqlBuilderPure . BB.fromText
instance ToSqlBuilder TL.Text where
toSqlBuilder = sqlBuilderPure . BB.fromLazyText
mkIdent :: Text -> SqlBuilder
mkIdent t = sqlBuilderFromField "mkident a" $ Identifier t
mkValue :: (ToField a) => a -> SqlBuilder
mkValue a = sqlBuilderFromField "mkValue a" a
sqlBuilderPure :: Builder -> SqlBuilder
sqlBuilderPure b = SqlBuilder $ const $ pure b
sqlBuilderFromField :: (ToField a) => Query -> a -> SqlBuilder
sqlBuilderFromField q a =
SqlBuilder $ \c -> buildAction c q [] $ toField a
instance Monoid SqlBuilder where
mempty = sqlBuilderPure mempty
mappend (SqlBuilder a) (SqlBuilder b) =
SqlBuilder $ \c -> mappend <$> (a c) <*> (b c)