@@ -745,13 +745,26 @@ newtype Oid = Oid CUInt deriving (Eq, Ord, Read, Show, Storable, Typeable)
745
745
invalidOid :: Oid
746
746
invalidOid = Oid (# const InvalidOid )
747
747
748
+ -- | Prepare the given parameter bytestring for passing on to libpq,
749
+ -- without copying for binary parameters.
750
+ --
751
+ -- This is safe to use to pass parameters to libpq considering:
752
+ -- * libpq treats the parameter data as read-only
753
+ -- * 'ByteString' uses pinned memory
754
+ -- * the reference to the 'CString' doesn't escape
755
+ unsafeUseParamAsCString :: (B. ByteString , Format ) -> (CString -> IO a ) -> IO a
756
+ unsafeUseParamAsCString (bs, format) =
757
+ case format of
758
+ Binary -> B. unsafeUseAsCString bs
759
+ Text -> B. useAsCString bs
760
+
748
761
-- | Convert a list of parameters to the format expected by libpq FFI calls.
749
762
withParams :: [Maybe (Oid , B. ByteString , Format )]
750
763
-> (CInt -> Ptr Oid -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
751
764
-> IO a
752
765
withParams params action =
753
766
withArray oids $ \ ts ->
754
- withMany (maybeWith B. useAsCString ) values $ \ c_values ->
767
+ withMany (maybeWith unsafeUseParamAsCString ) values $ \ c_values ->
755
768
withArray c_values $ \ vs ->
756
769
withArray c_lengths $ \ ls ->
757
770
withArray formats $ \ fs ->
@@ -770,7 +783,7 @@ withParams params action =
770
783
accum (Just (t,v,f)) ~ (AccumParams xs ys zs ws) =
771
784
let z = intToCInt (B. length v)
772
785
w = formatToCInt f
773
- in z `seq` w `seq` AccumParams (t : xs) (Just v : ys) (z : zs) (w : ws)
786
+ in z `seq` w `seq` AccumParams (t : xs) (Just (v, f) : ys) (z : zs) (w : ws)
774
787
775
788
formatToCInt :: Format -> CInt
776
789
formatToCInt Text = 0
@@ -779,15 +792,15 @@ formatToCInt Binary = 1
779
792
intToCInt :: Int -> CInt
780
793
intToCInt = toEnum
781
794
782
- data AccumParams = AccumParams ! [Oid ] ! [Maybe B. ByteString ] ! [CInt ] ! [CInt ]
795
+ data AccumParams = AccumParams ! [Oid ] ! [Maybe ( B. ByteString, Format ) ] ! [CInt ] ! [CInt ]
783
796
784
797
-- | Convert a list of parameters to the format expected by libpq FFI calls,
785
798
-- prepared statement variant.
786
799
withParamsPrepared :: [Maybe (B. ByteString , Format )]
787
800
-> (CInt -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
788
801
-> IO a
789
802
withParamsPrepared params action =
790
- withMany (maybeWith B. useAsCString ) values $ \ c_values ->
803
+ withMany (maybeWith unsafeUseParamAsCString ) values $ \ c_values ->
791
804
withArray c_values $ \ vs ->
792
805
withArray c_lengths $ \ ls ->
793
806
withArray formats $ \ fs ->
@@ -806,9 +819,9 @@ withParamsPrepared params action =
806
819
accum (Just (v, f)) ~ (AccumPrepParams xs ys zs) =
807
820
let y = intToCInt (B. length v)
808
821
z = formatToCInt f
809
- in y `seq` z `seq` AccumPrepParams (Just v : xs) (y : ys) (z : zs)
822
+ in y `seq` z `seq` AccumPrepParams (Just (v, f) : xs) (y : ys) (z : zs)
810
823
811
- data AccumPrepParams = AccumPrepParams ! [Maybe B. ByteString ] ! [CInt ] ! [CInt ]
824
+ data AccumPrepParams = AccumPrepParams ! [Maybe ( B. ByteString, Format ) ] ! [CInt ] ! [CInt ]
812
825
813
826
-- | Submits a command to the server and waits for the result.
814
827
--
0 commit comments