@@ -746,6 +746,70 @@ newtype Oid = Oid CUInt deriving (Eq, Ord, Read, Show, Storable, Typeable)
746
746
invalidOid :: Oid
747
747
invalidOid = Oid (# const InvalidOid )
748
748
749
+
750
+ -- | Prepare the given parameter bytestring for passing on to libpq,
751
+ -- without copying for binary parameters.
752
+ --
753
+ -- This safe to use to pass parameters to libpq considering:
754
+ -- * libpq treats the parameter data as read-only
755
+ -- * 'ByteString' uses pinned memory
756
+ -- * the reference to the 'CString' doesn't escape
757
+ unsafeUseParamAsCString :: (B. ByteString , Format ) -> (CString -> IO a ) -> IO a
758
+ unsafeUseParamAsCString (bs, format) =
759
+ case format of
760
+ Binary -> B. unsafeUseAsCString bs
761
+ Text -> B. useAsCString bs
762
+
763
+ -- | Convert a list of parameters to the format expected by libpq FFI calls.
764
+ withParams :: [Maybe (Oid , B. ByteString , Format )]
765
+ -> (CInt -> Ptr Oid -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
766
+ -> IO a
767
+ withParams params action =
768
+ withArray oids $ \ ts ->
769
+ withMany (maybeWith unsafeUseParamAsCString) values $ \ c_values ->
770
+ withArray c_values $ \ vs ->
771
+ withArray c_lengths $ \ ls ->
772
+ withArrayLen formats $ \ n fs ->
773
+ action (toEnum n) ts vs ls fs
774
+ where
775
+ (oids, values, c_lengths, formats) =
776
+ foldl' accum ([] ,[] ,[] ,[] ) $ reverse params
777
+
778
+ accum (! a,! b,! c,! d) Nothing = ( invalidOid: a
779
+ , Nothing : b
780
+ , 0 : c
781
+ , 0 : d
782
+ )
783
+ accum (! a,! b,! c,! d) (Just (t,v,f)) = ( t: a
784
+ , (Just (v,f)): b
785
+ , (toEnum $ B. length v): c
786
+ , (toEnum $ fromEnum f): d
787
+ )
788
+
789
+ -- | Convert a list of parameters to the format expected by libpq FFI calls,
790
+ -- prepared statement variant.
791
+ withParamsPrepared :: [Maybe (B. ByteString , Format )]
792
+ -> (CInt -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
793
+ -> IO a
794
+ withParamsPrepared params action =
795
+ withMany (maybeWith unsafeUseParamAsCString) values $ \ c_values ->
796
+ withArray c_values $ \ vs ->
797
+ withArray c_lengths $ \ ls ->
798
+ withArrayLen formats $ \ n fs ->
799
+ action (toEnum n) vs ls fs
800
+ where
801
+ (values, c_lengths, formats) = foldl' accum ([] ,[] ,[] ) $ reverse params
802
+
803
+ accum (! a,! b,! c) Nothing = ( Nothing : a
804
+ , 0 : b
805
+ , 0 : c
806
+ )
807
+ accum (! a,! b,! c) (Just (v, f)) = ( (Just (v,f)): a
808
+ , (toEnum $ B. length v): b
809
+ , (toEnum $ fromEnum f): c
810
+ )
811
+
812
+
749
813
-- | Submits a command to the server and waits for the result.
750
814
--
751
815
-- Returns a 'Result' or possibly 'Nothing'. A 'Result' will generally
@@ -812,31 +876,12 @@ execParams :: Connection -- ^ connection
812
876
-> Format -- ^ result format
813
877
-> IO (Maybe Result ) -- ^ result
814
878
execParams connection statement params rFmt =
815
- do let (oids, values, lengths, formats) =
816
- foldl' accum ([] ,[] ,[] ,[] ) $ reverse params
817
- ! c_lengths = map toEnum lengths :: [CInt ]
818
- ! n = toEnum $ length params
819
- ! f = toEnum $ fromEnum rFmt
820
- resultFromConn connection $ \ c ->
821
- B. useAsCString statement $ \ s ->
822
- withArray oids $ \ ts ->
823
- withMany (maybeWith B. useAsCString) values $ \ c_values ->
824
- withArray c_values $ \ vs ->
825
- withArray c_lengths $ \ ls ->
826
- withArray formats $ \ fs ->
827
- c_PQexecParams c s n ts vs ls fs f
828
-
829
- where
830
- accum (! a,! b,! c,! d) Nothing = ( invalidOid: a
831
- , Nothing : b
832
- , 0 : c
833
- , 0 : d
834
- )
835
- accum (! a,! b,! c,! d) (Just (t,v,f)) = ( t: a
836
- , (Just v): b
837
- , (B. length v): c
838
- , (toEnum $ fromEnum f): d
839
- )
879
+ resultFromConn connection $ \ c ->
880
+ B. useAsCString statement $ \ s ->
881
+ withParams params $ \ n ts vs ls fs ->
882
+ c_PQexecParams c s n ts vs ls fs f
883
+ where
884
+ ! f = toEnum $ fromEnum rFmt
840
885
841
886
842
887
-- | Submits a request to create a prepared statement with the given
@@ -911,28 +956,13 @@ execPrepared :: Connection -- ^ connection
911
956
-> [Maybe (B. ByteString , Format )] -- ^ parameters
912
957
-> Format -- ^ result format
913
958
-> IO (Maybe Result ) -- ^ result
914
- execPrepared connection stmtName mPairs rFmt =
915
- do let (values, lengths, formats) = foldl' accum ([] ,[] ,[] ) $ reverse mPairs
916
- ! c_lengths = map toEnum lengths :: [CInt ]
917
- ! n = toEnum $ length mPairs
918
- ! f = toEnum $ fromEnum rFmt
919
- resultFromConn connection $ \ c ->
920
- B. useAsCString stmtName $ \ s ->
921
- withMany (maybeWith B. useAsCString) values $ \ c_values ->
922
- withArray c_values $ \ vs ->
923
- withArray c_lengths $ \ ls ->
924
- withArray formats $ \ fs ->
925
- c_PQexecPrepared c s n vs ls fs f
926
-
959
+ execPrepared connection stmtName params rFmt =
960
+ resultFromConn connection $ \ c ->
961
+ B. useAsCString stmtName $ \ s ->
962
+ withParamsPrepared params $ \ n vs ls fs ->
963
+ c_PQexecPrepared c s n vs ls fs f
927
964
where
928
- accum (! a,! b,! c) Nothing = ( Nothing : a
929
- , 0 : b
930
- , 0 : c
931
- )
932
- accum (! a,! b,! c) (Just (v, f)) = ( (Just v): a
933
- , (B. length v): b
934
- , (toEnum $ fromEnum f): c
935
- )
965
+ ! f = toEnum $ fromEnum rFmt
936
966
937
967
938
968
-- | Submits a request to obtain information about the specified
@@ -1676,31 +1706,13 @@ sendQueryParams :: Connection
1676
1706
-> Format
1677
1707
-> IO Bool
1678
1708
sendQueryParams connection statement params rFmt =
1679
- do let (oids, values, lengths, formats) =
1680
- foldl' accum ([] ,[] ,[] ,[] ) $ reverse params
1681
- ! c_lengths = map toEnum lengths :: [CInt ]
1682
- ! n = toEnum $ length params
1683
- ! f = toEnum $ fromEnum rFmt
1684
- enumFromConn connection $ \ c ->
1685
- B. useAsCString statement $ \ s ->
1686
- withArray oids $ \ ts ->
1687
- withMany (maybeWith B. useAsCString) values $ \ c_values ->
1688
- withArray c_values $ \ vs ->
1689
- withArray c_lengths $ \ ls ->
1690
- withArray formats $ \ fs ->
1691
- c_PQsendQueryParams c s n ts vs ls fs f
1709
+ enumFromConn connection $ \ c ->
1710
+ B. useAsCString statement $ \ s ->
1711
+ withParams params $ \ n ts vs ls fs ->
1712
+ c_PQsendQueryParams c s n ts vs ls fs f
1692
1713
1693
1714
where
1694
- accum (! a,! b,! c,! d) Nothing = ( invalidOid: a
1695
- , Nothing : b
1696
- , 0 : c
1697
- , 0 : d
1698
- )
1699
- accum (! a,! b,! c,! d) (Just (t,v,f)) = ( t: a
1700
- , (Just v): b
1701
- , (B. length v): c
1702
- , (toEnum $ fromEnum f): d
1703
- )
1715
+ ! f = toEnum $ fromEnum rFmt
1704
1716
1705
1717
1706
1718
-- | Sends a request to create a prepared statement with the given
@@ -1726,28 +1738,14 @@ sendQueryPrepared :: Connection
1726
1738
-> [Maybe (B. ByteString , Format )]
1727
1739
-> Format
1728
1740
-> IO Bool
1729
- sendQueryPrepared connection stmtName mPairs rFmt =
1730
- do let (values, lengths, formats) = foldl' accum ([] ,[] ,[] ) $ reverse mPairs
1731
- ! c_lengths = map toEnum lengths :: [CInt ]
1732
- ! n = toEnum $ length mPairs
1733
- ! f = toEnum $ fromEnum rFmt
1734
- enumFromConn connection $ \ c ->
1735
- B. useAsCString stmtName $ \ s ->
1736
- withMany (maybeWith B. useAsCString) values $ \ c_values ->
1737
- withArray c_values $ \ vs ->
1738
- withArray c_lengths $ \ ls ->
1739
- withArray formats $ \ fs ->
1740
- c_PQsendQueryPrepared c s n vs ls fs f
1741
+ sendQueryPrepared connection stmtName params rFmt =
1742
+ enumFromConn connection $ \ c ->
1743
+ B. useAsCString stmtName $ \ s ->
1744
+ withParamsPrepared params $ \ n vs ls fs ->
1745
+ c_PQsendQueryPrepared c s n vs ls fs f
1741
1746
1742
1747
where
1743
- accum (! a,! b,! c) Nothing = ( Nothing : a
1744
- , 0 : b
1745
- , 0 : c
1746
- )
1747
- accum (! a,! b,! c) (Just (v, f)) = ( (Just v): a
1748
- , (B. length v): b
1749
- , (toEnum $ fromEnum f): c
1750
- )
1748
+ ! f = toEnum $ fromEnum rFmt
1751
1749
1752
1750
1753
1751
-- | Submits a request to obtain information about the specified
0 commit comments