@@ -66,9 +66,9 @@ module Database.PostgreSQL.Simple
6666 -- ** Exceptions
6767 , SqlError(..)
6868 , PQ.ExecStatus(..)
69− , FormatError(fmtMessage, fmtQuery, fmtParams)
70− , QueryError(qeMessage, qeQuery)
71− , ResultError(errSQLType, errHaskellType, errMessage)
69+ , FormatError(..)
70+ , QueryError(..)
71+ , ResultError(..)
7272 -- * Connection management
7373 , Base.connectPostgreSQL
7474 , Base.close
@@ -114,19 +114,18 @@ import Blaze.ByteString.Builder
114114 ( Builder, fromByteString, toByteString )
115115import Blaze.ByteString.Builder.Char8 (fromChar)
116116import Blaze.Text ( integral )
117−import Control.Applicative ((<$>), pure)
117+import Control.Applicative ((<$>))
118118import Control.Exception as E
119119import Control.Monad (foldM)
120120import Data.ByteString (ByteString)
121121import Data.Int (Int64)
122122import Data.List (intersperse)
123123import Data.Monoid (mconcat)
124−import Data.Typeable (Typeable)
125124import Database.PostgreSQL.Simple.Compat ( (<>) )
126125import Database.PostgreSQL.Simple.FromField (ResultError(..))
127126import Database.PostgreSQL.Simple.FromRow (FromRow(..))
128127import Database.PostgreSQL.Simple.Ok
129−import Database.PostgreSQL.Simple.ToField (Action(..), inQuotes)
128+import Database.PostgreSQL.Simple.ToField (Action(..))
130129import Database.PostgreSQL.Simple.ToRow (ToRow(..))
131130import Database.PostgreSQL.Simple.Types
132131 ( Binary(..), In(..), Only(..), Query(..), (:.)(..) )
@@ -135,21 +134,9 @@ import Database.PostgreSQL.Simple.Transaction
135134import Database.PostgreSQL.Simple.TypeInfo
136135import qualified Database.PostgreSQL.LibPQ as PQ
137136import qualified Data.ByteString.Char8 as B
138−import qualified Data.Text as T
139−import qualified Data.Text.Encoding as TE
140137import Control.Monad.Trans.Reader
141138import Control.Monad.Trans.State.Strict
142139
143−-- | Exception thrown if a 'Query' could not be formatted correctly.
144−-- This may occur if the number of \'@?@\' characters in the query
145−-- string does not match the number of parameters provided.
146−data FormatError = FormatError {
147− fmtMessage :: String
148− , fmtQuery :: Query
149− , fmtParams :: [ByteString]
150− } deriving (Eq, Show, Typeable)
151−
152−instance Exception FormatError
153140
154141-- | Format a query string.
155142--
@@ -286,40 +273,17 @@ parseTemplate template =
286273
287274 skipSpace = B.dropWhile isSpace_ascii
288275
289−escapeStringConn :: Connection -> ByteString -> IO (Either ByteString ByteString)
290−escapeStringConn = escapeWrap PQ.escapeStringConn
291−
292−escapeIdentifier :: Connection -> ByteString -> IO (Either ByteString ByteString)
293−escapeIdentifier = escapeWrap PQ.escapeIdentifier
294−
295−escapeByteaConn :: Connection -> ByteString -> IO (Either ByteString ByteString)
296−escapeByteaConn = escapeWrap PQ.escapeByteaConn
297−
298−escapeWrap :: (PQ.Connection -> ByteString -> IO (Maybe ByteString))
299− -> Connection
300− -> ByteString
301− -> IO (Either ByteString ByteString)
302−escapeWrap f conn s =
303− withConnection conn $ \c ->
304− f c s >>= checkError c
305276
306−checkError :: PQ.Connection -> Maybe a -> IO (Either ByteString a)
307−checkError _ (Just x) = return $ Right x
308−checkError c Nothing = Left . maybe "" id <$> PQ.errorMessage c
309277
310278buildQuery :: Connection -> Query -> ByteString -> [Action] -> IO Builder
311−buildQuery conn q template xs = zipParams (split template) <$> mapM sub xs
312− where err' msg = fmtError (utf8ToString msg) q xs
313− quote = either err' (inQuotes . fromByteString)
314− utf8ToString = T.unpack . TE.decodeUtf8
315− sub (Plain b) = pure b
316− sub (Escape s) = quote <$> escapeStringConn conn s
317− sub (EscapeByteA s) = quote <$> escapeByteaConn conn s
318− sub (EscapeIdentifier s) = either err' fromByteString <$>
319− escapeIdentifier conn s
320− sub (Many ys) = mconcat <$> mapM sub ys
321− split s = fromByteString h : if B.null t then [] else split (B.tail t)
322− where (h,t) = B.break (=='?') s
279+buildQuery conn q template xs =
280+ zipParams (split template) <$> mapM (buildAction conn q xs) xs
281+ where split s =
282+ let (h,t) = B.break (=='?') s
283+ in fromByteString h
284+ : if B.null t
285+ then []
286+ else split (B.tail t)
323287 zipParams (t:ts) (p:ps) = t <> p <> zipParams ts ps
324288 zipParams [t] [] = t
325289 zipParams _ _ = fmtError (show (B.count '?' template) ++
@@ -659,17 +623,6 @@ ellipsis bs
659623 | B.length bs > 15 = B.take 10 bs `B.append` "[...]"
660624 | otherwise = bs
661625
662−fmtError :: String -> Query -> [Action] -> a
663−fmtError msg q xs = throw FormatError {
664− fmtMessage = msg
665− , fmtQuery = q
666− , fmtParams = map twiddle xs
667− }
668− where twiddle (Plain b) = toByteString b
669− twiddle (Escape s) = s
670− twiddle (EscapeByteA s) = s
671− twiddle (EscapeIdentifier s) = s
672− twiddle (Many ys) = B.concat (map twiddle ys)
673626
674627-- $use
675628--