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