postgresql-libpq 0.9.5.0 → 0.10.0.0
raw patch · 4 files changed
+88/−62 lines, 4 filesdep ~basedep ~bytestringPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, bytestring
API changes (from Hackage documentation)
Files
- CHANGELOG.md +13/−0
- postgresql-libpq.cabal +5/−5
- src/Database/PostgreSQL/LibPQ.hs +20/−7
- src/Database/PostgreSQL/LibPQ/FFI.hs +50/−50
CHANGELOG.md view
@@ -1,3 +1,16 @@+0.10.0.0+--------++There are technicallly two breaking changes in this release,+but they shouldn't affect anyone not doing anything weird.++- Binary parameters are passed without copying.+- FFI functions are imported without `unsafe`. Most uses were incorrect.+ We make all calls "safe", as checking whether libpq functions do IO+ or may call a notifier (potentially calling back into Haskell),+ is virtually impossible for all versions of libpq.+ (The above properties are not specified in the documentation).+ 0.9.5.0 -------
postgresql-libpq.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: postgresql-libpq-version: 0.9.5.0+version: 0.10.0.0 synopsis: low-level binding to libpq description: This is a binding to libpq: the C application@@ -24,14 +24,14 @@ build-type: Custom extra-source-files: cbits/hs-libpq.h tested-with:- GHC ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.4 || ==9.4.2+ GHC ==8.6.5 || ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.7 || ==9.4.4 || ==9.6.1 extra-source-files: CHANGELOG.md custom-setup setup-depends: , base >=4.12.0.0 && <5- , Cabal >=2.4 && <3.9+ , Cabal >=2.4 && <3.11 -- If true, use pkg-config, otherwise use the pg_config based build -- configuration@@ -67,11 +67,11 @@ Database.PostgreSQL.LibPQ.Oid build-depends:- , base >=4.12.0.0 && <4.18+ , base >=4.12.0.0 && <4.19 , bytestring >=0.10.8.2 && <0.12 if !os(windows)- build-depends: unix >=2.7.2.2 && <2.8+ build-depends: unix >=2.7.2.2 && <2.9 if os(windows) build-depends: Win32 >=2.2.0.2 && <2.14
src/Database/PostgreSQL/LibPQ.hs view
@@ -654,13 +654,26 @@ -- 'Result'. newtype Result = Result (ForeignPtr PGresult) deriving (Eq, Show) +-- | Prepare the given parameter bytestring for passing on to libpq,+-- without copying for binary parameters.+--+-- This is safe to use to pass parameters to libpq considering:+-- * libpq treats the parameter data as read-only+-- * 'ByteString' uses pinned memory+-- * the reference to the 'CString' doesn't escape+unsafeUseParamAsCString :: (B.ByteString, Format) -> (CString -> IO a) -> IO a+unsafeUseParamAsCString (bs, format) =+ case format of+ Binary -> B.unsafeUseAsCString bs+ Text -> B.useAsCString bs+ -- | Convert a list of parameters to the format expected by libpq FFI calls. withParams :: [Maybe (Oid, B.ByteString, Format)] -> (CInt -> Ptr Oid -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a) -> IO a withParams params action = unsafeWithArray n oids $ \ts ->- withMany (maybeWith B.useAsCString) values $ \c_values ->+ withMany (maybeWith unsafeUseParamAsCString) values $ \c_values -> unsafeWithArray n c_values $ \vs -> unsafeWithArray n c_lengths $ \ls -> unsafeWithArray n formats $ \fs ->@@ -676,12 +689,12 @@ accum (Just (t,v,f)) ~(AccumParams i xs ys zs ws) = let !z = intToCInt (B.length v) !w = toCInt f- in AccumParams (i + 1) (t : xs) (Just v : ys) (z : zs) (w : ws)+ in AccumParams (i + 1) (t : xs) (Just (v, f) : ys) (z : zs) (w : ws) intToCInt :: Int -> CInt intToCInt = toEnum -data AccumParams = AccumParams !Int ![Oid] ![Maybe B.ByteString] ![CInt] ![CInt]+data AccumParams = AccumParams !Int ![Oid] ![Maybe (B.ByteString, Format)] ![CInt] ![CInt] -- | Convert a list of parameters to the format expected by libpq FFI calls, -- prepared statement variant.@@ -689,7 +702,7 @@ -> (CInt -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a) -> IO a withParamsPrepared params action =- withMany (maybeWith B.useAsCString) values $ \c_values ->+ withMany (maybeWith unsafeUseParamAsCString) values $ \c_values -> unsafeWithArray n c_values $ \vs -> unsafeWithArray n c_lengths $ \ls -> unsafeWithArray n formats $ \fs ->@@ -698,16 +711,16 @@ AccumPrepParams n values c_lengths formats = foldr accum (AccumPrepParams 0 [] [] []) params - accum :: Maybe (B.ByteString ,Format) -> AccumPrepParams -> AccumPrepParams+ accum :: Maybe (B.ByteString, Format) -> AccumPrepParams -> AccumPrepParams accum Nothing ~(AccumPrepParams i a b c) = AccumPrepParams (i + 1) (Nothing : a) (0 : b) (0 : c) accum (Just (v, f)) ~(AccumPrepParams i xs ys zs) = let !y = intToCInt (B.length v) !z = toCInt f- in AccumPrepParams (i + 1) (Just v : xs) (y : ys) (z : zs)+ in AccumPrepParams (i + 1) (Just (v, f) : xs) (y : ys) (z : zs) -data AccumPrepParams = AccumPrepParams !Int ![Maybe B.ByteString] ![CInt] ![CInt]+data AccumPrepParams = AccumPrepParams !Int ![Maybe (B.ByteString, Format)] ![CInt] ![CInt] -- | Submits a command to the server and waits for the result. --
src/Database/PostgreSQL/LibPQ/FFI.hs view
@@ -35,53 +35,53 @@ foreign import capi "hs-libpq.h PQconnectPoll" c_PQconnectPoll :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQdb"+foreign import capi "hs-libpq.h PQdb" c_PQdb :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQuser"+foreign import capi "hs-libpq.h PQuser" c_PQuser :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQpass"+foreign import capi "hs-libpq.h PQpass" c_PQpass :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQhost"+foreign import capi "hs-libpq.h PQhost" c_PQhost :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQport"+foreign import capi "hs-libpq.h PQport" c_PQport :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQoptions"+foreign import capi "hs-libpq.h PQoptions" c_PQoptions :: Ptr PGconn -> IO CString -foreign import capi unsafe "hs-libpq.h PQbackendPID"+foreign import capi "hs-libpq.h PQbackendPID" c_PQbackendPID :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQconnectionNeedsPassword"+foreign import capi "hs-libpq.h PQconnectionNeedsPassword" c_PQconnectionNeedsPassword :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQconnectionUsedPassword"+foreign import capi "hs-libpq.h PQconnectionUsedPassword" c_PQconnectionUsedPassword :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQstatus"+foreign import capi "hs-libpq.h PQstatus" c_PQstatus :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQtransactionStatus"+foreign import capi "hs-libpq.h PQtransactionStatus" c_PQtransactionStatus :: Ptr PGconn -> IO CInt -- TODO: GHC #22043 foreign import ccall "hs-libpq.h PQparameterStatus" c_PQparameterStatus :: Ptr PGconn -> CString -> IO CString -foreign import capi unsafe "hs-libpq.h PQprotocolVersion"+foreign import capi "hs-libpq.h PQprotocolVersion" c_PQprotocolVersion :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQserverVersion"+foreign import capi "hs-libpq.h PQserverVersion" c_PQserverVersion :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQlibVersion"+foreign import capi "hs-libpq.h PQlibVersion" c_PQlibVersion :: IO CInt -foreign import capi unsafe "hs-libpq.h PQsocket"+foreign import capi "hs-libpq.h PQsocket" c_PQsocket :: Ptr PGconn -> IO CInt foreign import capi "hs-libpq.h PQerrorMessage"@@ -99,7 +99,7 @@ foreign import capi "hs-libpq.h PQresetPoll" c_PQresetPoll :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQclientEncoding"+foreign import capi "hs-libpq.h PQclientEncoding" c_PQclientEncoding :: Ptr PGconn -> IO CInt -- TODO: GHC #22043@@ -110,7 +110,7 @@ c_PQsetClientEncoding :: Ptr PGconn -> CString -> IO CInt type PGVerbosity = CInt-foreign import capi unsafe "hs-libpq.h PQsetErrorVerbosity"+foreign import capi "hs-libpq.h PQsetErrorVerbosity" c_PQsetErrorVerbosity :: Ptr PGconn -> PGVerbosity -> IO PGVerbosity foreign import capi "hs-libpq.h PQputCopyData"@@ -159,22 +159,22 @@ foreign import capi "hs-libpq.h PQcancel" c_PQcancel :: Ptr PGcancel -> CString -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQnotifies"+foreign import capi "hs-libpq.h PQnotifies" c_PQnotifies :: Ptr PGconn -> IO (Ptr Notify) foreign import capi "hs-libpq.h PQconsumeInput" c_PQconsumeInput :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQisBusy"+foreign import capi "hs-libpq.h PQisBusy" c_PQisBusy :: Ptr PGconn -> IO CInt foreign import capi "hs-libpq.h PQsetnonblocking" c_PQsetnonblocking :: Ptr PGconn -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQisnonblocking"+foreign import capi "hs-libpq.h PQisnonblocking" c_PQisnonblocking :: Ptr PGconn -> IO CInt -foreign import capi unsafe "hs-libpq.h PQsetSingleRowMode"+foreign import capi "hs-libpq.h PQsetSingleRowMode" c_PQsetSingleRowMode :: Ptr PGconn -> IO CInt foreign import capi "hs-libpq.h PQgetResult"@@ -207,67 +207,67 @@ foreign import capi "hs-libpq.h &PQclear" p_PQclear :: FunPtr (Ptr PGresult -> IO ()) -foreign import capi unsafe "hs-libpq.h PQresultStatus"+foreign import capi "hs-libpq.h PQresultStatus" c_PQresultStatus :: Ptr PGresult -> IO CInt -foreign import capi unsafe "hs-libpq.h PQresStatus"+foreign import capi "hs-libpq.h PQresStatus" c_PQresStatus :: CInt -> IO CString -foreign import capi unsafe "hs-libpq.h PQresultErrorMessage"+foreign import capi "hs-libpq.h PQresultErrorMessage" c_PQresultErrorMessage :: Ptr PGresult -> IO CString foreign import capi "hs-libpq.h PQresultErrorField" c_PQresultErrorField :: Ptr PGresult -> CInt -> IO CString -foreign import capi unsafe "hs-libpq.h PQntuples"+foreign import capi "hs-libpq.h PQntuples" c_PQntuples :: Ptr PGresult -> CInt -foreign import capi unsafe "hs-libpq.h PQnfields"+foreign import capi "hs-libpq.h PQnfields" c_PQnfields :: Ptr PGresult -> CInt -foreign import capi unsafe "hs-libpq.h PQfname"+foreign import capi "hs-libpq.h PQfname" c_PQfname :: Ptr PGresult -> CInt -> IO CString -foreign import capi unsafe "hs-libpq.h PQfnumber"+foreign import capi "hs-libpq.h PQfnumber" c_PQfnumber :: Ptr PGresult -> CString -> IO CInt -foreign import capi unsafe "hs-libpq.h PQftable"+foreign import capi "hs-libpq.h PQftable" c_PQftable :: Ptr PGresult -> CInt -> IO Oid -foreign import capi unsafe "hs-libpq.h PQftablecol"+foreign import capi "hs-libpq.h PQftablecol" c_PQftablecol :: Ptr PGresult -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQfformat"+foreign import capi "hs-libpq.h PQfformat" c_PQfformat :: Ptr PGresult -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQftype"+foreign import capi "hs-libpq.h PQftype" c_PQftype :: Ptr PGresult -> CInt -> IO Oid -foreign import capi unsafe "hs-libpq.h PQfmod"+foreign import capi "hs-libpq.h PQfmod" c_PQfmod :: Ptr PGresult -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQfsize"+foreign import capi "hs-libpq.h PQfsize" c_PQfsize :: Ptr PGresult -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQgetvalue"+foreign import capi "hs-libpq.h PQgetvalue" c_PQgetvalue :: Ptr PGresult -> CInt -> CInt -> IO CString -foreign import capi unsafe "hs-libpq.h PQgetisnull"+foreign import capi "hs-libpq.h PQgetisnull" c_PQgetisnull :: Ptr PGresult -> CInt -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQgetlength"+foreign import capi "hs-libpq.h PQgetlength" c_PQgetlength :: Ptr PGresult -> CInt -> CInt -> IO CInt -foreign import capi unsafe "hs-libpq.h PQnparams"+foreign import capi "hs-libpq.h PQnparams" c_PQnparams :: Ptr PGresult -> IO CInt -foreign import capi unsafe "hs-libpq.h PQparamtype"+foreign import capi "hs-libpq.h PQparamtype" c_PQparamtype :: Ptr PGresult -> CInt -> IO Oid -foreign import capi unsafe "hs-libpq.h PQcmdStatus"+foreign import capi "hs-libpq.h PQcmdStatus" c_PQcmdStatus :: Ptr PGresult -> IO CString -foreign import capi unsafe "hs-libpq.h PQcmdTuples"+foreign import capi "hs-libpq.h PQcmdTuples" c_PQcmdTuples :: Ptr PGresult -> IO CString foreign import capi "hs-libpq.h PQescapeStringConn"@@ -290,38 +290,38 @@ -> Ptr CSize -> IO (Ptr Word8) -- Actually (IO (Ptr CUChar)) -foreign import capi unsafe "hs-libpq.h PQescapeIdentifier"+foreign import capi "hs-libpq.h PQescapeIdentifier" c_PQescapeIdentifier :: Ptr PGconn -> CString -> CSize -> IO CString -foreign import capi unsafe "hs-libpq.h &PQfreemem"+foreign import capi "hs-libpq.h &PQfreemem" p_PQfreemem :: FunPtr (Ptr a -> IO ()) -foreign import capi unsafe "hs-libpq.h PQfreemem"+foreign import capi "hs-libpq.h PQfreemem" c_PQfreemem :: Ptr a -> IO () ------------------------------------------------------------------------------- -- FFI imports: noticebuffers ------------------------------------------------------------------------------- -foreign import capi unsafe "hs-libpq.h hs_postgresql_libpq_malloc_noticebuffer"+foreign import capi "hs-libpq.h hs_postgresql_libpq_malloc_noticebuffer" c_malloc_noticebuffer :: IO (Ptr CNoticeBuffer) -foreign import capi unsafe "hs-libpq.h hs_postgresql_libpq_free_noticebuffer"+foreign import capi "hs-libpq.h hs_postgresql_libpq_free_noticebuffer" c_free_noticebuffer :: Ptr CNoticeBuffer -> IO () -foreign import capi unsafe "hs-libpq.h hs_postgresql_libpq_get_notice"+foreign import capi "hs-libpq.h hs_postgresql_libpq_get_notice" c_get_notice :: Ptr CNoticeBuffer -> IO (Ptr PGnotice) -foreign import capi unsafe "hs-libpq.h &hs_postgresql_libpq_discard_notices"+foreign import capi "hs-libpq.h &hs_postgresql_libpq_discard_notices" p_discard_notices :: FunPtr NoticeReceiver -foreign import capi unsafe "hs-libpq.h &hs_postgresql_libpq_store_notices"+foreign import capi "hs-libpq.h &hs_postgresql_libpq_store_notices" p_store_notices :: FunPtr NoticeReceiver -foreign import capi unsafe "hs-libpq.h PQsetNoticeReceiver"+foreign import capi "hs-libpq.h PQsetNoticeReceiver" c_PQsetNoticeReceiver :: Ptr PGconn -> FunPtr NoticeReceiver -> Ptr CNoticeBuffer -> IO (FunPtr NoticeReceiver) -------------------------------------------------------------------------------