Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added putCopyData and putCopyEnd

Still need to document the functions themselves.
  • Loading branch information...
commit 86855d208f71fa49363e0f64fdd83566e758beff 1 parent f9ffdf1
@joeyadams authored
Showing with 65 additions and 0 deletions.
  1. +65 −0 Database/PostgreSQL/LibPQ.hsc
View
65 Database/PostgreSQL/LibPQ.hsc
@@ -144,7 +144,13 @@ module Database.PostgreSQL.LibPQ
, unescapeBytea
-- * Using COPY FROM
+ , CopyResult(..)
+ , putCopyData
+ , putCopyEnd
+
+ -- ** Formatting datums
, formatCopyRow
+ , putCopyRow
-- * Asynchronous Command Processing
-- $asynccommand
@@ -1509,6 +1515,55 @@ unescapeBytea bs =
return $ Just $ B.fromForeignPtr tofp 0 $ fromIntegral l
+data CopyResult = CopyOk -- ^ The data was sent.
+ | CopyError -- ^ An error occurred (use 'errorMessage'
+ -- to retrieve details).
+ | CopyWouldBlock -- ^ The data was not sent because the
+ -- attempt would block (this case is only
+ -- possible if the connection is in
+ -- nonblocking mode) Wait for
+ -- write-ready (e.g. by using
+ -- 'Control.Concurrent.threadWaitWrite'
+ -- on the 'socket') and try again.
+
+
+toCopyResult :: CInt -> CopyResult
+toCopyResult n | n < 0 = CopyError
+ | n == 0 = CopyWouldBlock
+ | otherwise = CopyOk
+
+
+putCopyData :: Connection -> B.ByteString -> IO CopyResult
+putCopyData conn bs =
+ B.unsafeUseAsCStringLen bs $ putCopyCString conn
+
+
+putCopyCString :: Connection -> CStringLen -> IO CopyResult
+putCopyCString conn (str, len) =
+ fmap toCopyResult $
+ withConn conn $ \ptr -> c_PQputCopyData ptr str (fromIntegral len)
+
+
+putCopyEnd :: Connection -> Maybe B.ByteString -> IO CopyResult
+putCopyEnd conn Nothing =
+ fmap toCopyResult $
+ withConn conn $ \ptr -> c_PQputCopyEnd ptr nullPtr
+putCopyEnd conn (Just errormsg) =
+ fmap toCopyResult $
+ B.useAsCString errormsg $ \errormsg_cstr ->
+ withConn conn $ \ptr -> c_PQputCopyEnd ptr errormsg_cstr
+
+
+-- | A combination of 'putCopyData' and 'formatCopyRow'. This should be
+-- slightly more efficient than:
+--
+-- >putCopyData conn $ formatCopyRow params
+--
+-- as it does not allocate an intermediate 'B.ByteString'.
+putCopyRow :: Connection -> [Maybe (B.ByteString, Format)] -> IO CopyResult
+putCopyRow conn params = withFormatCopyRow params $ putCopyCString conn
+
+
-- | Escape a row of data for use with a COPY FROM statement.
-- Include a trailing newline at the end.
--
@@ -1519,6 +1574,7 @@ unescapeBytea bs =
formatCopyRow :: [Maybe (B.ByteString, Format)] -> IO B.ByteString
formatCopyRow params = withFormatCopyRow params B.packCStringLen
+
withFormatCopyRow :: [Maybe (B.ByteString, Format)]
-> (CStringLen -> IO a)
-> IO a
@@ -1536,6 +1592,7 @@ withFormatCopyRow params inner =
++ show bufsize ++ " bytes, but "
++ show len ++ " bytes were written into it)"
+
-- | Compute the maximum number of bytes the escaped datum may take up,
-- including the trailing tab or newline character.
paramSize :: Maybe (B.ByteString, Format) -> Int
@@ -1543,6 +1600,7 @@ paramSize Nothing = 3 -- Length of "\\N\t"
paramSize (Just (s, Text)) = B.length s * 2 + 1
paramSize (Just (s, Binary)) = B.length s * 5 + 1
+
emitParam :: Ptr CUChar -> Maybe (B.ByteString, Format) -> IO (Ptr CUChar)
emitParam out Nothing = do
pokeElemOff out 0 92 -- '\\'
@@ -1555,6 +1613,7 @@ emitParam out (Just (s, Binary)) =
B.unsafeUseAsCStringLen s $ \(ptr, len) ->
c_escape_copy_bytea (castPtr ptr) (fromIntegral len) out
+
emitParams :: Ptr CUChar -> [Maybe (B.ByteString, Format)] -> IO (Ptr CUChar)
emitParams out [] = do
poke out 10 -- newline
@@ -2358,6 +2417,12 @@ type PGVerbosity = CInt
foreign import ccall unsafe "libpq-fe.h PQsetErrorVerbosity"
c_PQsetErrorVerbosity :: Ptr PGconn -> PGVerbosity -> IO PGVerbosity
+foreign import ccall "libpq-fe.h PQputCopyData"
+ c_PQputCopyData :: Ptr PGconn -> Ptr CChar -> CInt -> IO CInt
+
+foreign import ccall "libpq-fe.h PQputCopyEnd"
+ c_PQputCopyEnd :: Ptr PGconn -> CString -> IO CInt
+
foreign import ccall "libpq-fe.h PQsendQuery"
c_PQsendQuery :: Ptr PGconn -> CString ->IO CInt
Please sign in to comment.
Something went wrong with that request. Please try again.