@@ -48,7 +48,9 @@ import Data.Word (Word64)
48import Database.PostgreSQL.Simple.Internal
48import Database.PostgreSQL.Simple.Internal
49import Database.PostgreSQL.Simple.Field (Field(..), RawResult(..))
49import Database.PostgreSQL.Simple.Field (Field(..), RawResult(..))
50import Database.PostgreSQL.Simple.BuiltinTypes
50import Database.PostgreSQL.Simple.BuiltinTypes
51+import Database.PostgreSQL.Simple.Types (Binary(..))
51import qualified Database.PostgreSQL.LibPQ as PQ
52import qualified Database.PostgreSQL.LibPQ as PQ
53+import System.IO.Unsafe (unsafePerformIO)
52import System.Locale (defaultTimeLocale)
54import System.Locale (defaultTimeLocale)
53import qualified Data.ByteString as SB
55import qualified Data.ByteString as SB
54import qualified Data.ByteString.Char8 as B8
56import qualified Data.ByteString.Char8 as B8
@@ -135,8 +137,13 @@ instance Result (Ratio Integer) where
135 where ok = mkCompats [Float,Double,Decimal,NewDecimal,Tiny,Short,Int24,
137 where ok = mkCompats [Float,Double,Decimal,NewDecimal,Tiny,Short,Int24,
136 Long,LongLong]
138 Long,LongLong]
141+unBinary (Binary x) = x
138instance Result SB.ByteString where
143instance Result SB.ByteString where
144+ convert f dat = if typeOid f == builtin2oid Bytea
145+ then unBinary <$> convert f dat
139− convert f = doConvert f okText $ pure
146+ else doConvert f okText' pure dat
141instance Result PQ.Oid where
148instance Result PQ.Oid where
142 convert f dat = PQ.Oid <$> atto (mkCompat Oid) decimal f dat
149 convert f dat = PQ.Oid <$> atto (mkCompat Oid) decimal f dat
@@ -144,6 +151,19 @@ instance Result PQ.Oid where
144instance Result LB.ByteString where
151instance Result LB.ByteString where
145 convert f dat = LB.fromChunks . (:[]) <$> convert f dat
152 convert f dat = LB.fromChunks . (:[]) <$> convert f dat
154+unescapeBytea :: Field -> SB.ByteString
155+ -> Either SomeException (Binary SB.ByteString)
156+unescapeBytea f str = case unsafePerformIO (PQ.unescapeBytea str) of
157+ Nothing -> returnError ConversionFailed f "unescapeBytea failed"
158+ Just str -> pure (Binary str)
160+instance Result (Binary SB.ByteString) where
161+ convert f dat = case format f of
162+ PQ.Text -> doConvert f okBinary (unescapeBytea f) dat
163+ PQ.Binary -> doConvert f okBinary (pure . Binary) dat
165+instance Result (Binary LB.ByteString) where
166+ convert f dat = Binary . LB.fromChunks . (:[]) . unBinary <$> convert f dat
148instance Result ST.Text where
168instance Result ST.Text where
149 convert f = doConvert f okText $ (either left Right . ST.decodeUtf8')
169 convert f = doConvert f okText $ (either left Right . ST.decodeUtf8')
@@ -200,8 +220,10 @@ mkCompat = Compat . shiftL 1 . fromEnum
200compat :: Compat -> Compat -> Bool
220compat :: Compat -> Compat -> Bool
201compat (Compat a) (Compat b) = a .&. b /= 0
221compat (Compat a) (Compat b) = a .&. b /= 0
203−okText, ok16, ok32, ok64 :: Compat
223+okText, okText', ok16, ok32, ok64 :: Compat
224+okText = mkCompats [Name,Text,Char,Bpchar,Varchar]
204−okText = mkCompats [Name,Text,Char,Bpchar,Varchar]
225+okText' = mkCompats [Name,Text,Char,Bpchar,Varchar,Unknown]
226+okBinary = mkCompats [Bytea]
205ok16 = mkCompats [Int2]
227ok16 = mkCompats [Int2]
206ok32 = mkCompats [Int2,Int4]
228ok32 = mkCompats [Int2,Int4]
207ok64 = mkCompats [Int2,Int4,Int8]
229ok64 = mkCompats [Int2,Int4,Int8]