hpgsql-simple-compat-0.1.0.0: src/Database/PostgreSQL/Simple/Copy.hs
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- |
-- Module: Database.PostgreSQL.Simple.Copy
-- Copyright: (c) 2013 Leon P Smith
-- License: BSD3
-- Maintainer: Leon P Smith <leon@melding-monads.com>
-- Stability: experimental
--
-- mid-level support for COPY IN and COPY OUT. See
-- <https://www.postgresql.org/docs/9.5/static/sql-copy.html> for
-- more information.
--
-- To use this binding, first call 'copy' with an appropriate
-- query as documented in the link above. Then, in the case of a
-- @COPY TO STDOUT@ query, call 'getCopyData' repeatedly until it
-- returns 'CopyOutDone'. In the case of a @COPY FROM STDIN@
-- query, call 'putCopyData' repeatedly and then finish by calling
-- either 'putCopyEnd' to proceed or 'putCopyError' to abort.
--
-- You cannot issue another query on the same connection while a copy
-- is ongoing; this will result in an exception. It is harmless to
-- concurrently call @getNotification@ on a connection while it is in
-- a @CopyIn@ or @CopyOut@ state, however be aware that current versions
-- of the PostgreSQL backend will not deliver notifications to a client
-- while a transaction is ongoing.
module Database.PostgreSQL.Simple.Copy
( copy,
copy_,
CopyOutResult (..),
-- foldCopyData,
-- getCopyData,
putCopyData,
putCopyEnd,
putCopyError,
)
where
import qualified Data.ByteString.Char8 as B
import Data.Int (Int64)
import qualified Data.Text as Text
import Data.Text.Encoding (decodeUtf8)
import Data.Typeable (Typeable)
import Database.PostgreSQL.Simple.HpgsqlUtils (toHpgsqlQuery)
import Database.PostgreSQL.Simple.Internal
import Database.PostgreSQL.Simple.ToRow (ToRow)
import Database.PostgreSQL.Simple.Types
import qualified Hpgsql.Copy
import qualified Hpgsql.Query
-- | Issue a @COPY FROM STDIN@ or @COPY TO STDOUT@ query. In the former
-- case, the connection's state will change to @CopyIn@; in the latter,
-- @CopyOut@. The connection must be in the ready state in order
-- to call this function. Performs parameter substitution.
copy :: (ToRow params) => Connection -> Query -> params -> IO ()
copy conn template qs = do
let qry = toHpgsqlQuery template qs
doCopy "Database.PostgreSQL.Simple.Copy.copy" conn qry
-- | Issue a @COPY FROM STDIN@ or @COPY TO STDOUT@ query. In the former
-- case, the connection's state will change to @CopyIn@; in the latter,
-- @CopyOut@. The connection must be in the ready state in order
-- to call this function. Does not perform parameter substitution.
copy_ :: Connection -> Query -> IO ()
copy_ conn template = do
let qry = toHpgsqlQuery template ()
doCopy "Database.PostgreSQL.Simple.Copy.copy_" conn qry
doCopy :: B.ByteString -> Connection -> Hpgsql.Query.Query -> IO ()
doCopy _funcName conn q = mapHpgsqlErrors $ do
Hpgsql.Copy.copyStart (hpgConn conn) q
data CopyOutResult
= -- | Data representing either exactly
-- one row of the result, or header
-- or footer data depending on format.
CopyOutRow !B.ByteString
| -- | No more rows, and a count of the
-- number of rows returned.
CopyOutDone {-# UNPACK #-} !Int64
deriving (Eq, Typeable, Show)
-- | Feed some data to a @COPY FROM STDIN@ query. Note that
-- the data does not need to represent a single row, or even an
-- integral number of rows. The net result of
-- @putCopyData conn a >> putCopyData conn b@
-- is the same as @putCopyData conn c@ whenever @c == BS.append a b@.
--
-- A connection must be in the @CopyIn@ state in order to call this
-- function, otherwise a 'SqlError' exception will result. The
-- connection remains in the @CopyIn@ state after this function
-- is called.
putCopyData :: Connection -> B.ByteString -> IO ()
putCopyData conn dat = mapHpgsqlErrors $ Hpgsql.Copy.putCopyData (hpgConn conn) dat
-- | Completes a @COPY FROM STDIN@ query. Returns the number of rows
-- processed.
--
-- A connection must be in the @CopyIn@ state in order to call this
-- function, otherwise a 'SqlError' exception will result. The
-- connection's state changes back to ready after this function
-- is called.
putCopyEnd :: Connection -> IO Int64
putCopyEnd conn = mapHpgsqlErrors $ Hpgsql.Copy.copyEnd (hpgConn conn)
-- | Aborts a @COPY FROM STDIN@ query. The string parameter is simply
-- an arbitrary error message that may show up in the PostgreSQL
-- server's log.
--
-- A connection must be in the @CopyIn@ state in order to call this
-- function, otherwise a 'SqlError' exception will result. The
-- connection's state changes back to ready after this function
-- is called.
putCopyError :: Connection -> B.ByteString -> IO ()
putCopyError conn err = mapHpgsqlErrors $ Hpgsql.Copy.putCopyError (hpgConn conn) (Text.unpack $ decodeUtf8 err)