@@ -225,7 +225,6 @@ import qualified Foreign.ForeignPtr.Unsafe as Unsafe
225
225
#endif
226
226
import qualified Foreign.Concurrent as FC
227
227
import System.Posix.Types ( Fd (.. ) )
228
- import Data.List ( foldl' )
229
228
import System.IO ( IOMode (.. ), SeekMode (.. ) )
230
229
231
230
#if __GLASGOW_HASKELL__ >= 700
@@ -746,6 +745,71 @@ newtype Oid = Oid CUInt deriving (Eq, Ord, Read, Show, Storable, Typeable)
746
745
invalidOid :: Oid
747
746
invalidOid = Oid (# const InvalidOid )
748
747
748
+ -- | Convert a list of parameters to the format expected by libpq FFI calls.
749
+ withParams :: [Maybe (Oid , B. ByteString , Format )]
750
+ -> (CInt -> Ptr Oid -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
751
+ -> IO a
752
+ withParams params action =
753
+ withArray oids $ \ ts ->
754
+ withMany (maybeWith B. useAsCString) values $ \ c_values ->
755
+ withArray c_values $ \ vs ->
756
+ withArray c_lengths $ \ ls ->
757
+ withArray formats $ \ fs ->
758
+ action n ts vs ls fs
759
+ where
760
+ AccumParams oids values c_lengths formats =
761
+ foldr accum (AccumParams [] [] [] [] ) params
762
+
763
+ n :: CInt
764
+ ! n = intToCInt $ length params
765
+
766
+ accum :: Maybe (Oid , B. ByteString , Format ) -> AccumParams -> AccumParams
767
+ accum Nothing ~ (AccumParams a b c d) =
768
+ AccumParams (invalidOid : a) (Nothing : b) (0 : c) (0 : d)
769
+
770
+ accum (Just (t,v,f)) ~ (AccumParams xs ys zs ws) =
771
+ let z = intToCInt (B. length v)
772
+ w = formatToCInt f
773
+ in z `seq` w `seq` AccumParams (t : xs) (Just v : ys) (z : zs) (w : ws)
774
+
775
+ formatToCInt :: Format -> CInt
776
+ formatToCInt Text = 0
777
+ formatToCInt Binary = 1
778
+
779
+ intToCInt :: Int -> CInt
780
+ intToCInt = toEnum
781
+
782
+ data AccumParams = AccumParams ! [Oid ] ! [Maybe B. ByteString ] ! [CInt ] ! [CInt ]
783
+
784
+ -- | Convert a list of parameters to the format expected by libpq FFI calls,
785
+ -- prepared statement variant.
786
+ withParamsPrepared :: [Maybe (B. ByteString , Format )]
787
+ -> (CInt -> Ptr CString -> Ptr CInt -> Ptr CInt -> IO a )
788
+ -> IO a
789
+ withParamsPrepared params action =
790
+ withMany (maybeWith B. useAsCString) values $ \ c_values ->
791
+ withArray c_values $ \ vs ->
792
+ withArray c_lengths $ \ ls ->
793
+ withArray formats $ \ fs ->
794
+ action n vs ls fs
795
+ where
796
+ AccumPrepParams values c_lengths formats =
797
+ foldr accum (AccumPrepParams [] [] [] ) params
798
+
799
+ n :: CInt
800
+ n = intToCInt $ length params
801
+
802
+ accum :: Maybe (B. ByteString ,Format ) -> AccumPrepParams -> AccumPrepParams
803
+ accum Nothing ~ (AccumPrepParams a b c) =
804
+ AccumPrepParams (Nothing : a) (0 : b) (0 : c)
805
+
806
+ accum (Just (v, f)) ~ (AccumPrepParams xs ys zs) =
807
+ let y = intToCInt (B. length v)
808
+ z = formatToCInt f
809
+ in y `seq` z `seq` AccumPrepParams (Just v : xs) (y : ys) (z : zs)
810
+
811
+ data AccumPrepParams = AccumPrepParams ! [Maybe B. ByteString ] ! [CInt ] ! [CInt ]
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 = formatToCInt rFmt
840
885
841
886
842
887
-- | Submits a request to create a prepared statement with the given
@@ -885,7 +930,7 @@ prepare connection stmtName query mParamTypes =
885
930
B. useAsCString stmtName $ \ s ->
886
931
B. useAsCString query $ \ q ->
887
932
maybeWith withArray mParamTypes $ \ o ->
888
- let l = maybe 0 (toEnum . length ) mParamTypes
933
+ let l = maybe 0 (intToCInt . length ) mParamTypes
889
934
in c_PQprepare c s q l o
890
935
891
936
@@ -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 = formatToCInt 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 = formatToCInt rFmt
1704
1716
1705
1717
1706
1718
-- | Sends a request to create a prepared statement with the given
@@ -1715,7 +1727,7 @@ sendPrepare connection stmtName query mParamTypes =
1715
1727
B. useAsCString stmtName $ \ s ->
1716
1728
B. useAsCString query $ \ q ->
1717
1729
maybeWith withArray mParamTypes $ \ o ->
1718
- let l = maybe 0 (toEnum . length ) mParamTypes
1730
+ let l = maybe 0 (intToCInt . length ) mParamTypes
1719
1731
in c_PQsendPrepare c s q l o
1720
1732
1721
1733
@@ -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 = formatToCInt rFmt
1751
1749
1752
1750
1753
1751
-- | Submits a request to obtain information about the specified
0 commit comments