postgresql-libpq 0.10.2.0 → 0.11.0.0
raw patch · 6 files changed
+175/−16 lines, 6 filesdep ~basedep ~postgresql-libpq-configuredep ~postgresql-libpq-pkgconfig
Dependency ranges changed: base, postgresql-libpq-configure, postgresql-libpq-pkgconfig
Files
- CHANGELOG.md +9/−0
- postgresql-libpq.cabal +3/−3
- src/Database/PostgreSQL/LibPQ.hs +63/−0
- src/Database/PostgreSQL/LibPQ/Enums.hsc +52/−12
- src/Database/PostgreSQL/LibPQ/FFI.hs +15/−0
- test/Smoke.hs +33/−1
CHANGELOG.md view
@@ -1,3 +1,12 @@+0.11+----++- Add pipeline mode API+ https://www.postgresql.org/docs/current/libpq-pipeline-mode.html++ There are new values in `ExecStatus`, therefore the major version release.++ 0.10.2.0 --------
postgresql-libpq.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: postgresql-libpq-version: 0.10.2.0+version: 0.11.0.0 synopsis: low-level binding to libpq description: This is a binding to libpq: the C application@@ -81,10 +81,10 @@ build-depends: Win32 >=2.2.0.2 && <2.15 if flag(use-pkg-config)- build-depends: postgresql-libpq-pkgconfig ^>=0.10+ build-depends: postgresql-libpq-pkgconfig ^>=0.11 else- build-depends: postgresql-libpq-configure ^>=0.10+ build-depends: postgresql-libpq-configure ^>=0.11 build-tool-depends: hsc2hs:hsc2hs >=0.68.5
src/Database/PostgreSQL/LibPQ.hs view
@@ -171,6 +171,15 @@ , FlushStatus(..) , flush + -- * Pipeline Mode+ -- $pipelinemode+ , PipelineStatus(..)+ , pipelineStatus+ , enterPipelineMode+ , exitPipelineMode+ , pipelineSync+ , sendFlushRequest+ -- * Cancelling Queries in Progress -- $cancel , Cancel@@ -1639,6 +1648,60 @@ 0 -> return FlushOk 1 -> return FlushWriting _ -> return FlushFailed++-- $pipelinemode+-- These functions control behaviour in pipeline mode.+--+-- Pipeline mode allows applications to send a query+-- without having to read the result of the previously+-- sent query. Taking advantage of the pipeline mode,+-- a client will wait less for the server, since multiple+-- queries/results can be sent/received in+-- a single network transaction.++-- | Returns the current pipeline mode status of the libpq connection.+--+-- @since 0.11.0.0+pipelineStatus :: Connection+ -> IO PipelineStatus+pipelineStatus connection = do+ stat <- withConn connection c_PQpipelineStatus+ maybe+ (fail $ "Unknown pipeline status " ++ show stat)+ return+ (fromCInt stat)++-- | Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.+--+-- @since 0.11.0.0+enterPipelineMode :: Connection+ -> IO Bool+enterPipelineMode connection =+ enumFromConn connection c_PQenterPipelineMode++-- | Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.+--+-- @since 0.11.0.0+exitPipelineMode :: Connection+ -> IO Bool+exitPipelineMode connection =+ enumFromConn connection c_PQexitPipelineMode++-- | Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer. This serves as the delimiter of an implicit transaction and an error recovery point>+--+-- @since 0.11.0.0+pipelineSync :: Connection+ -> IO Bool+pipelineSync connection =+ enumFromConn connection c_PQpipelineSync++-- | Sends a request for the server to flush its output buffer.+--+-- @since 0.11.0.0+sendFlushRequest :: Connection+ -> IO Bool+sendFlushRequest connection =+ enumFromConn connection c_PQsendFlushRequest -- $cancel
src/Database/PostgreSQL/LibPQ/Enums.hsc view
@@ -37,23 +37,42 @@ | NonfatalError -- ^ A nonfatal error (a notice or -- warning) occurred. | FatalError -- ^ A fatal error occurred.- | SingleTuple -- ^ The PGresult contains a single result tuple+ | SingleTuple -- ^ The 'Result' contains a single result tuple -- from the current command. This status occurs -- only when single-row mode has been selected -- for the query.++ | PipelineSync -- ^ The 'Result' represents a synchronization+ -- point in pipeline mode, requested by+ -- 'pipelineSync'. This status occurs only+ -- when pipeline mode has been selected.+ --+ -- @since 0.11.0.0++ | PipelineAbort -- ^ The 'Result' represents a pipeline that+ -- has received an error from the server.+ -- 'getResult' must be called repeatedly,+ -- and each time it will return this status+ -- code until the end of the current pipeline,+ -- at which point it will return 'PipelineSync'+ -- and normal processing can resume.+ --+ -- @since 0.11.0.0 deriving (Eq, Show) instance FromCInt ExecStatus where- fromCInt (#const PGRES_EMPTY_QUERY) = Just EmptyQuery- fromCInt (#const PGRES_COMMAND_OK) = Just CommandOk- fromCInt (#const PGRES_TUPLES_OK) = Just TuplesOk- fromCInt (#const PGRES_COPY_OUT) = Just CopyOut- fromCInt (#const PGRES_COPY_IN) = Just CopyIn- fromCInt (#const PGRES_COPY_BOTH) = Just CopyBoth- fromCInt (#const PGRES_BAD_RESPONSE) = Just BadResponse- fromCInt (#const PGRES_NONFATAL_ERROR) = Just NonfatalError- fromCInt (#const PGRES_FATAL_ERROR) = Just FatalError- fromCInt (#const PGRES_SINGLE_TUPLE) = Just SingleTuple+ fromCInt (#const PGRES_EMPTY_QUERY) = Just EmptyQuery+ fromCInt (#const PGRES_COMMAND_OK) = Just CommandOk+ fromCInt (#const PGRES_TUPLES_OK) = Just TuplesOk+ fromCInt (#const PGRES_COPY_OUT) = Just CopyOut+ fromCInt (#const PGRES_COPY_IN) = Just CopyIn+ fromCInt (#const PGRES_COPY_BOTH) = Just CopyBoth+ fromCInt (#const PGRES_BAD_RESPONSE) = Just BadResponse+ fromCInt (#const PGRES_NONFATAL_ERROR) = Just NonfatalError+ fromCInt (#const PGRES_FATAL_ERROR) = Just FatalError+ fromCInt (#const PGRES_SINGLE_TUPLE) = Just SingleTuple+ fromCInt (#const PGRES_PIPELINE_SYNC) = Just PipelineSync+ fromCInt (#const PGRES_PIPELINE_ABORTED) = Just PipelineAbort fromCInt _ = Nothing instance ToCInt ExecStatus where@@ -67,6 +86,8 @@ toCInt NonfatalError = (#const PGRES_NONFATAL_ERROR) toCInt FatalError = (#const PGRES_FATAL_ERROR) toCInt SingleTuple = (#const PGRES_SINGLE_TUPLE)+ toCInt PipelineSync = (#const PGRES_PIPELINE_SYNC)+ toCInt PipelineAbort = (#const PGRES_PIPELINE_ABORTED) data FieldCode@@ -230,8 +251,8 @@ fromCInt (#const CONNECTION_SSL_STARTUP) = return ConnectionSSLStartup -- fromCInt (#const CONNECTION_NEEDED) = return ConnectionNeeded fromCInt _ = Nothing- + data TransactionStatus = TransIdle -- ^ currently idle | TransActive -- ^ a command is in progress@@ -261,6 +282,25 @@ instance FromCInt Format where fromCInt 0 = Just Text fromCInt 1 = Just Binary+ fromCInt _ = Nothing+++-- |+--+-- @since 0.11.0.0+data PipelineStatus+ = PipelineOn -- ^ The 'Connection' is in pipeline mode.+ | PipelineOff -- ^ The 'Connection' is /not/ in pipeline mode.+ | PipelineAborted -- ^ The 'Connection' is in pipeline mode and an error+ -- occurred while processing the current pipeline. The+ -- aborted flag is cleared when 'getResult' returns a+ -- result with status 'PipelineSync'.+ deriving (Eq, Show)++instance FromCInt PipelineStatus where+ fromCInt (#const PQ_PIPELINE_ON) = return PipelineOn+ fromCInt (#const PQ_PIPELINE_OFF) = return PipelineOff+ fromCInt (#const PQ_PIPELINE_ABORTED) = return PipelineAborted fromCInt _ = Nothing -------------------------------------------------------------------------------
src/Database/PostgreSQL/LibPQ/FFI.hs view
@@ -302,6 +302,21 @@ foreign import capi "hs-libpq.h PQfreemem" c_PQfreemem :: Ptr a -> IO () +foreign import capi "hs-libpq.h PQpipelineStatus"+ c_PQpipelineStatus :: Ptr PGconn -> IO CInt++foreign import capi "hs-libpq.h PQenterPipelineMode"+ c_PQenterPipelineMode :: Ptr PGconn -> IO CInt++foreign import capi "hs-libpq.h PQexitPipelineMode"+ c_PQexitPipelineMode :: Ptr PGconn -> IO CInt++foreign import capi "hs-libpq.h PQpipelineSync"+ c_PQpipelineSync :: Ptr PGconn -> IO CInt++foreign import capi "hs-libpq.h PQsendFlushRequest"+ c_PQsendFlushRequest :: Ptr PGconn -> IO CInt+ ------------------------------------------------------------------------------- -- FFI imports: noticebuffers -------------------------------------------------------------------------------
test/Smoke.hs view
@@ -5,7 +5,6 @@ import Data.Foldable (toList) import Database.PostgreSQL.LibPQ import System.Environment (getEnvironment)-import System.Exit (exitFailure) import Test.Tasty (defaultMain, testGroup) import Test.Tasty.HUnit (assertEqual, testCaseSteps) @@ -18,6 +17,7 @@ withConnstring $ \connString -> defaultMain $ testGroup "postgresql-libpq" [ testCaseSteps "smoke" $ smoke connString , testCaseSteps "issue54" $ issue54 connString+ , testCaseSteps "pipeline" $ testPipeline connString ] withConnstring :: (BS8.ByteString -> IO ()) -> IO ()@@ -57,6 +57,7 @@ transactionStatus conn >>= infoShow protocolVersion conn >>= infoShow serverVersion conn >>= infoShow+ pipelineStatus conn >>= infoShow s <- status conn assertEqual "connection not ok" ConnectionOk s@@ -87,3 +88,34 @@ assertEqual "fst not null" BS.empty val1 assertEqual "snd not null" BS.empty val2++testPipeline :: BS8.ByteString -> (String -> IO ()) -> IO ()+testPipeline connstring info = do+ conn <- connectdb connstring++ setnonblocking conn True `shouldReturn` True+ enterPipelineMode conn `shouldReturn` True+ pipelineStatus conn `shouldReturn` PipelineOn+ sendQueryParams conn (BS8.pack "select 1") [] Text `shouldReturn` True+ sendQueryParams conn (BS8.pack "select 2") [] Text `shouldReturn` True+ pipelineSync conn `shouldReturn` True++ Just r1 <- getResult conn+ resultStatus r1 `shouldReturn` TuplesOk+ getvalue r1 0 0 `shouldReturn` Just (BS8.pack "1")+ Nothing <- getResult conn++ Just r2 <- getResult conn+ getvalue r2 0 0 `shouldReturn` Just (BS8.pack "2")+ Nothing <- getResult conn++ Just r3 <- getResult conn+ resultStatus r3 `shouldReturn` PipelineSync++ finish conn+ where+ shouldBe r value = assertEqual "shouldBe" r value++ shouldReturn action value = do+ r <- action+ r `shouldBe` value