diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
 -------
 
diff --git a/postgresql-libpq.cabal b/postgresql-libpq.cabal
--- a/postgresql-libpq.cabal
+++ b/postgresql-libpq.cabal
@@ -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
diff --git a/src/Database/PostgreSQL/LibPQ.hs b/src/Database/PostgreSQL/LibPQ.hs
--- a/src/Database/PostgreSQL/LibPQ.hs
+++ b/src/Database/PostgreSQL/LibPQ.hs
@@ -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.
 --
diff --git a/src/Database/PostgreSQL/LibPQ/FFI.hs b/src/Database/PostgreSQL/LibPQ/FFI.hs
--- a/src/Database/PostgreSQL/LibPQ/FFI.hs
+++ b/src/Database/PostgreSQL/LibPQ/FFI.hs
@@ -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)
 
 -------------------------------------------------------------------------------
