postgresql-query-3.0.0: src/Database/PostgreSQL/Query/SqlBuilder/Builder.hs
module Database.PostgreSQL.Query.SqlBuilder.Builder
( SqlBuilder(..)
-- * Running
, runSqlBuilder
-- * Building
, emptyB
, mkValue
, mkMaskedValue
, sqlBuilderFromField
-- ** Unsafe
, sqlBuilderPure
, sqlBuilderFromByteString
) where
import Blaze.ByteString.Builder (Builder)
import Data.ByteString (ByteString)
import Data.Semigroup
import Data.String
import Data.Typeable
import Database.PostgreSQL.Query.SqlBuilder.Types
import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.Internal
import Database.PostgreSQL.Simple.ToField
import Database.PostgreSQL.Simple.Types
import GHC.Generics (Generic)
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
import qualified Blaze.ByteString.Builder as BB
import qualified Blaze.ByteString.Builder.Char.Utf8 as BB
-- | Builder wich can be effectively concatenated. Requires 'Connection'
-- inside for string quoting implemented in __libpq__. Builds two strings: query
-- string and log string which may differ.
newtype SqlBuilder = SqlBuilder
{ sqlBuild :: Connection -> LogMasker -> IO SqlBuilderResult
} deriving (Typeable, Generic)
instance Semigroup SqlBuilder where
(SqlBuilder a) <> (SqlBuilder b) =
SqlBuilder $ \c masker -> (<>) <$> (a c masker) <*> (b c masker)
instance Monoid SqlBuilder where
mempty = sqlBuilderPure mempty
mappend = (<>)
instance IsString SqlBuilder where
fromString s = SqlBuilder $ \_ _ -> return $ builderResultPure $ BB.fromString s
-- | Returns query string with log bytestring
runSqlBuilder :: Connection -> LogMasker -> SqlBuilder -> IO (Query, ByteString)
runSqlBuilder con masker (SqlBuilder bld) = toTuple <$> bld con masker
where
toTuple res =
( Query $ BB.toByteString $ sbQueryString res
, BB.toByteString $ sbLogString res )
-- | Typed synonym of 'mempty'
emptyB :: SqlBuilder
emptyB = mempty
-- | Shorthand function to convert single field value to builder
mkValue :: (ToField a) => a -> SqlBuilder
mkValue = sqlBuilderFromField FieldDefault
-- | Shorthand function to convert single masked field value (which should not
-- be shown in log)
mkMaskedValue :: (ToField a) => a -> SqlBuilder
mkMaskedValue = sqlBuilderFromField FieldMasked
sqlBuilderFromField :: (ToField a) => FieldOption -> a -> SqlBuilder
sqlBuilderFromField fo field = SqlBuilder $ \con masker -> do
qbs <- buildAction con "" [] $ toField field
let sbQueryString = qbs
sbLogString = masker fo qbs
return SqlBuilderResult{..}
-- | Lift pure bytestring builder to 'SqlBuilder'. This is unsafe to use
-- directly in your code.
sqlBuilderPure :: Builder -> SqlBuilder
sqlBuilderPure b = SqlBuilder $ \_ _ -> pure $ builderResultPure b
-- | Unsafe function to make SqlBuilder from arbitrary ByteString. Does not
-- perform any checks. Dont use it directly in your code unless you know what
-- you are doing.
sqlBuilderFromByteString :: ByteString -> SqlBuilder
sqlBuilderFromByteString = sqlBuilderPure . BB.fromByteString