@@ -696,13 +696,26 @@ connectionUsedPassword connection =
696
696
newtype Result = Result (ForeignPtr PGresult ) deriving (Eq , Show )
697
697
data PGresult
698
698
699
+ -- | Prepare the given parameter bytestring for passing on to libpq,
700
+ -- without copying for binary parameters.
701
+ --
702
+ -- This is safe to use to pass parameters to libpq considering:
703
+ -- * libpq treats the parameter data as read-only
704
+ -- * 'ByteString' uses pinned memory
705
+ -- * the reference to the 'CString' doesn't escape
706
+ unsafeUseParamAsCString :: (B. ByteString , Format ) -> (CString -> IO a ) -> IO a
707
+ unsafeUseParamAsCString (bs, format) =
708
+ case format of
709
+ Binary -> B. unsafeUseAsCString bs
710
+ Text -> B. useAsCString bs
711
+
699
712
-- | Convert a list of parameters to the format expected by libpq FFI calls.
700
713
withParams :: [Maybe (Oid , B. ByteString , Format )]
701
714
-> (CInt -> Ptr Oid -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
702
715
-> IO a
703
716
withParams params action =
704
717
unsafeWithArray n oids $ \ ts ->
705
- withMany (maybeWith B. useAsCString ) values $ \ c_values ->
718
+ withMany (maybeWith unsafeUseParamAsCString ) values $ \ c_values ->
706
719
unsafeWithArray n c_values $ \ vs ->
707
720
unsafeWithArray n c_lengths $ \ ls ->
708
721
unsafeWithArray n formats $ \ fs ->
@@ -718,20 +731,20 @@ withParams params action =
718
731
accum (Just (t,v,f)) ~ (AccumParams i xs ys zs ws) =
719
732
let ! z = intToCInt (B. length v)
720
733
! w = toCInt f
721
- in AccumParams (i + 1 ) (t : xs) (Just v : ys) (z : zs) (w : ws)
734
+ in AccumParams (i + 1 ) (t : xs) (Just (v, f) : ys) (z : zs) (w : ws)
722
735
723
736
intToCInt :: Int -> CInt
724
737
intToCInt = toEnum
725
738
726
- data AccumParams = AccumParams ! Int ! [Oid ] ! [Maybe B. ByteString ] ! [CInt ] ! [CInt ]
739
+ data AccumParams = AccumParams ! Int ! [Oid ] ! [Maybe ( B. ByteString, Format ) ] ! [CInt ] ! [CInt ]
727
740
728
741
-- | Convert a list of parameters to the format expected by libpq FFI calls,
729
742
-- prepared statement variant.
730
743
withParamsPrepared :: [Maybe (B. ByteString , Format )]
731
744
-> (CInt -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
732
745
-> IO a
733
746
withParamsPrepared params action =
734
- withMany (maybeWith B. useAsCString ) values $ \ c_values ->
747
+ withMany (maybeWith unsafeUseParamAsCString ) values $ \ c_values ->
735
748
unsafeWithArray n c_values $ \ vs ->
736
749
unsafeWithArray n c_lengths $ \ ls ->
737
750
unsafeWithArray n formats $ \ fs ->
@@ -740,16 +753,16 @@ withParamsPrepared params action =
740
753
AccumPrepParams n values c_lengths formats =
741
754
foldr accum (AccumPrepParams 0 [] [] [] ) params
742
755
743
- accum :: Maybe (B. ByteString , Format ) -> AccumPrepParams -> AccumPrepParams
756
+ accum :: Maybe (B. ByteString, Format ) -> AccumPrepParams -> AccumPrepParams
744
757
accum Nothing ~ (AccumPrepParams i a b c) =
745
758
AccumPrepParams (i + 1 ) (Nothing : a) (0 : b) (0 : c)
746
759
747
760
accum (Just (v, f)) ~ (AccumPrepParams i xs ys zs) =
748
761
let ! y = intToCInt (B. length v)
749
762
! z = toCInt f
750
- in AccumPrepParams (i + 1 ) (Just v : xs) (y : ys) (z : zs)
763
+ in AccumPrepParams (i + 1 ) (Just (v, f) : xs) (y : ys) (z : zs)
751
764
752
- data AccumPrepParams = AccumPrepParams ! Int ! [Maybe B. ByteString ] ! [CInt ] ! [CInt ]
765
+ data AccumPrepParams = AccumPrepParams ! Int ! [Maybe ( B. ByteString, Format ) ] ! [CInt ] ! [CInt ]
753
766
754
767
-- | Submits a command to the server and waits for the result.
755
768
--
0 commit comments