|
| 1 | +{-# language ForeignFunctionInterface #-} |
1 | 2 | module Database.PostgreSQL.Protocol.DataRows
|
2 | 3 | ( loopExtractDataRows
|
3 | 4 | , countDataRows
|
@@ -6,22 +7,24 @@ module Database.PostgreSQL.Protocol.DataRows
|
6 | 7 | , decodeOneRow
|
7 | 8 | ) where
|
8 | 9 |
|
9 |
| -import Data.Monoid ((<>)) |
10 |
| -import Data.Word (Word8, byteSwap32) |
11 |
| -import Foreign (peek, peekByteOff, castPtr) |
| 10 | +import Data.Foldable (traverse_) |
| 11 | +import Data.Monoid ((<>)) |
| 12 | +import Data.Word (Word8, byteSwap32) |
| 13 | +import Foreign (Ptr, alloca, peek, peekByteOff, castPtr) |
| 14 | +import Foreign.C.Types (CInt, CSize(..), CChar, CULong) |
| 15 | +import Foreign (Ptr, peek, alloca) |
| 16 | +import System.IO.Unsafe (unsafePerformIO) |
| 17 | + |
12 | 18 | import qualified Data.ByteString as B
|
13 | 19 | import qualified Data.ByteString.Unsafe as B
|
14 | 20 | import qualified Data.Vector as V
|
15 | 21 | import qualified Data.Vector.Mutable as MV
|
16 | 22 | import qualified Data.List as L
|
17 |
| -import Data.Foldable |
18 |
| -import System.IO.Unsafe |
19 | 23 |
|
20 | 24 | import Database.PostgreSQL.Driver.Error
|
21 | 25 | import Database.PostgreSQL.Protocol.Types
|
22 | 26 | import Database.PostgreSQL.Protocol.Parsers
|
23 | 27 | import Database.PostgreSQL.Protocol.Store.Decode
|
24 |
| -import Database.PostgreSQL.Protocol.Utils |
25 | 28 |
|
26 | 29 | -- Optimized loop for extracting chunks of DataRows.
|
27 | 30 | -- Ignores all messages from database that do not relate to data.
|
@@ -188,3 +191,29 @@ countDataRows = foldlDataRows (\acc (DataChunk c _) -> acc + c) 0
|
188 | 191 | {-# INLINE flattenDataRows #-}
|
189 | 192 | flattenDataRows :: DataRows -> B.ByteString
|
190 | 193 | flattenDataRows = foldlDataRows (\acc (DataChunk _ bs) -> acc <> bs) ""
|
| 194 | + |
| 195 | +-- |
| 196 | +-- C utils |
| 197 | +-- |
| 198 | + |
| 199 | +data ScanRowResult = ScanRowResult |
| 200 | +{-# UNPACK #-} !DataChunk -- chunk of datarows, may be empty |
| 201 | +{-# UNPACK #-} !B.ByteString -- the rest of string |
| 202 | +{-# UNPACK #-} !Int -- reason code |
| 203 | + |
| 204 | +-- | Scans `ByteString` for a chunk of `DataRow`s. |
| 205 | +{-# INLINE scanDataRows #-} |
| 206 | +scanDataRows :: B.ByteString -> IO ScanRowResult |
| 207 | +scanDataRows bs = |
| 208 | +alloca $ \countPtr -> |
| 209 | +alloca $ \reasonPtr -> |
| 210 | +B.unsafeUseAsCStringLen bs $ \(ptr, len) -> do |
| 211 | +offset <- fromIntegral <$> |
| 212 | +c_scan_datarows ptr (fromIntegral len) countPtr reasonPtr |
| 213 | +reason <- fromIntegral <$> peek reasonPtr |
| 214 | +count <- fromIntegral <$> peek countPtr |
| 215 | +let (ch, rest) = B.splitAt offset bs |
| 216 | +pure $ ScanRowResult (DataChunk count ch) rest reason |
| 217 | + |
| 218 | +foreign import ccall unsafe "static pw_utils.h scan_datarows" c_scan_datarows |
| 219 | +:: Ptr CChar -> CSize -> Ptr CULong -> Ptr CInt -> IO CSize |
0 commit comments