@@ -654,13 +654,26 @@ connectionUsedPassword connection =
654
654
-- 'Result'.
655
655
newtype Result = Result (ForeignPtr PGresult ) deriving (Eq , Show )
656
656
657
+ -- | Prepare the given parameter bytestring for passing on to libpq,
658
+ -- without copying for binary parameters.
659
+ --
660
+ -- This is safe to use to pass parameters to libpq considering:
661
+ -- * libpq treats the parameter data as read-only
662
+ -- * 'ByteString' uses pinned memory
663
+ -- * the reference to the 'CString' doesn't escape
664
+ unsafeUseParamAsCString :: (B. ByteString , Format ) -> (CString -> IO a ) -> IO a
665
+ unsafeUseParamAsCString (bs, format) =
666
+ case format of
667
+ Binary -> B. unsafeUseAsCString bs
668
+ Text -> B. useAsCString bs
669
+
657
670
-- | Convert a list of parameters to the format expected by libpq FFI calls.
658
671
withParams :: [Maybe (Oid , B. ByteString , Format )]
659
672
-> (CInt -> Ptr Oid -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
660
673
-> IO a
661
674
withParams params action =
662
675
unsafeWithArray n oids $ \ ts ->
663
- withMany (maybeWith B. useAsCString ) values $ \ c_values ->
676
+ withMany (maybeWith unsafeUseParamAsCString ) values $ \ c_values ->
664
677
unsafeWithArray n c_values $ \ vs ->
665
678
unsafeWithArray n c_lengths $ \ ls ->
666
679
unsafeWithArray n formats $ \ fs ->
@@ -676,20 +689,20 @@ withParams params action =
676
689
accum (Just (t,v,f)) ~ (AccumParams i xs ys zs ws) =
677
690
let ! z = intToCInt (B. length v)
678
691
! w = toCInt f
679
- in AccumParams (i + 1 ) (t : xs) (Just v : ys) (z : zs) (w : ws)
692
+ in AccumParams (i + 1 ) (t : xs) (Just (v, f) : ys) (z : zs) (w : ws)
680
693
681
694
intToCInt :: Int -> CInt
682
695
intToCInt = toEnum
683
696
684
- data AccumParams = AccumParams ! Int ! [Oid ] ! [Maybe B. ByteString ] ! [CInt ] ! [CInt ]
697
+ data AccumParams = AccumParams ! Int ! [Oid ] ! [Maybe ( B. ByteString, Format ) ] ! [CInt ] ! [CInt ]
685
698
686
699
-- | Convert a list of parameters to the format expected by libpq FFI calls,
687
700
-- prepared statement variant.
688
701
withParamsPrepared :: [Maybe (B. ByteString , Format )]
689
702
-> (CInt -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
690
703
-> IO a
691
704
withParamsPrepared params action =
692
- withMany (maybeWith B. useAsCString ) values $ \ c_values ->
705
+ withMany (maybeWith unsafeUseParamAsCString ) values $ \ c_values ->
693
706
unsafeWithArray n c_values $ \ vs ->
694
707
unsafeWithArray n c_lengths $ \ ls ->
695
708
unsafeWithArray n formats $ \ fs ->
@@ -698,16 +711,16 @@ withParamsPrepared params action =
698
711
AccumPrepParams n values c_lengths formats =
699
712
foldr accum (AccumPrepParams 0 [] [] [] ) params
700
713
701
- accum :: Maybe (B. ByteString , Format ) -> AccumPrepParams -> AccumPrepParams
714
+ accum :: Maybe (B. ByteString, Format ) -> AccumPrepParams -> AccumPrepParams
702
715
accum Nothing ~ (AccumPrepParams i a b c) =
703
716
AccumPrepParams (i + 1 ) (Nothing : a) (0 : b) (0 : c)
704
717
705
718
accum (Just (v, f)) ~ (AccumPrepParams i xs ys zs) =
706
719
let ! y = intToCInt (B. length v)
707
720
! z = toCInt f
708
- in AccumPrepParams (i + 1 ) (Just v : xs) (y : ys) (z : zs)
721
+ in AccumPrepParams (i + 1 ) (Just (v, f) : xs) (y : ys) (z : zs)
709
722
710
- data AccumPrepParams = AccumPrepParams ! Int ! [Maybe B. ByteString ] ! [CInt ] ! [CInt ]
723
+ data AccumPrepParams = AccumPrepParams ! Int ! [Maybe ( B. ByteString, Format ) ] ! [CInt ] ! [CInt ]
711
724
712
725
-- | Submits a command to the server and waits for the result.
713
726
--
0 commit comments