packages feed

postgresql-lo-stream 0.1.0.0 → 0.1.1.0

raw patch · 3 files changed

+118/−118 lines, 3 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Database.PostgreSQL.LargeObjects.Stream: newLargeObjectBS :: Connection -> ByteString -> IO Oid
- Database.PostgreSQL.LargeObjects.Stream: newLargeObjectLBS :: Connection -> ByteString -> IO (Oid, Int)
- Database.PostgreSQL.LargeObjects.Stream: newLargeObjectStream :: Connection -> InputStream ByteString -> IO (Oid, Int)
- Database.PostgreSQL.LargeObjects.Stream: streamLargeObject :: Connection -> Oid -> OutputStream Builder -> IO ()
- Database.PostgreSQL.LargeObjects.Stream: streamLargeObjectRange :: Connection -> Oid -> Int -> Int -> OutputStream Builder -> IO ()
- Database.PostgreSQL.LargeObjects.Stream: withLargeObject :: Connection -> Oid -> IOMode -> (LoFd -> IO a) -> IO a
- Database.PostgreSQL.LargeObjects.Stream: withLargeObjectLBS :: Connection -> Oid -> (ByteString -> IO ()) -> IO ()
+ Database.PostgreSQL.Simple.LargeObjects.Stream: newLargeObjectBS :: Connection -> ByteString -> IO Oid
+ Database.PostgreSQL.Simple.LargeObjects.Stream: newLargeObjectLBS :: Connection -> ByteString -> IO (Oid, Int)
+ Database.PostgreSQL.Simple.LargeObjects.Stream: newLargeObjectStream :: Connection -> InputStream ByteString -> IO (Oid, Int)
+ Database.PostgreSQL.Simple.LargeObjects.Stream: streamLargeObject :: Connection -> Oid -> OutputStream Builder -> IO ()
+ Database.PostgreSQL.Simple.LargeObjects.Stream: streamLargeObjectRange :: Connection -> Oid -> Int -> Int -> OutputStream Builder -> IO ()
+ Database.PostgreSQL.Simple.LargeObjects.Stream: withLargeObject :: Connection -> Oid -> IOMode -> (LoFd -> IO a) -> IO a
+ Database.PostgreSQL.Simple.LargeObjects.Stream: withLargeObjectLBS :: Connection -> Oid -> (ByteString -> IO ()) -> IO ()

Files

postgresql-lo-stream.cabal view
@@ -1,6 +1,6 @@ cabal-version:       >=1.10 name:                postgresql-lo-stream-version:             0.1.0.0+version:             0.1.1.0 synopsis:            Utilities for streaming PostgreSQL LargeObjects description:         Functions for streaming large objects to and from PostgreSQL homepage:            https://github.com/obsidiansystems/posgresql-lo-stream@@ -15,7 +15,7 @@ extra-source-files:  README.md  library-  exposed-modules:     Database.PostgreSQL.LargeObjects.Stream+  exposed-modules:     Database.PostgreSQL.Simple.LargeObjects.Stream   other-extensions:    LambdaCase   build-depends:       base >=4.11 && <4.12                      , bytestring >=0.10 && <0.11
− src/Database/PostgreSQL/LargeObjects/Stream.hs
@@ -1,116 +0,0 @@-{-# LANGUAGE LambdaCase #-}-module Database.PostgreSQL.LargeObjects.Stream where--import Control.Exception.Lifted (AssertionFailed (..), bracket, throwIO)-import Control.Monad.Loops (whileJust_)-import Control.Monad.State as State-import qualified Data.ByteString as BS-import Data.ByteString.Builder (byteString)-import qualified Data.ByteString.Builder as BS-import qualified Data.ByteString.Lazy as LBS-import Data.IORef (modifyIORef, newIORef, readIORef)-import Data.Semigroup ((<>))-import Database.PostgreSQL.Simple-import Database.PostgreSQL.Simple.LargeObjects (LoFd, Oid (..))-import qualified Database.PostgreSQL.Simple.LargeObjects as Sql-import System.IO (IOMode (ReadMode, WriteMode))-import System.IO.Streams (makeOutputStream)-import qualified System.IO.Streams as Streams---- | Given a strict ByteString, create a postgres large object and fill it with those contents.-newLargeObjectBS-  :: Connection-  -> BS.ByteString-  -> IO Oid-newLargeObjectBS conn contents = do-  oid <- Sql.loCreat conn-  n <- withLargeObject conn oid WriteMode $ \lofd -> Sql.loWrite conn lofd contents-  let l = BS.length contents-  when (n /= l) . throwIO . AssertionFailed $-    "newLargeObjectBS: loWrite reported writing " <> show n <> " bytes, expected " <> show l <> "."-  return oid---- | Given a lazy ByteString, create a postgres large object and fill it with those contents.--- Also returns the total length of the data written.-newLargeObjectLBS-  :: Connection-  -> LBS.ByteString-  -> IO (Oid, Int)-newLargeObjectLBS conn = newLargeObjectStream conn <=< Streams.fromLazyByteString---- | Create a new large object from an input stream, returning its object id and overall size.-newLargeObjectStream-  :: Connection-  -> Streams.InputStream BS.ByteString-  -> IO (Oid, Int)-newLargeObjectStream conn s = do-  oid <- Sql.loCreat conn-  t <- withLargeObject conn oid WriteMode $ \lofd -> do-    whileJust_ (Streams.read s) $ \chunk -> do-      n <- Sql.loWrite conn lofd chunk-      let l = BS.length chunk-      when (n /= l) . throwIO . AssertionFailed $-        "newLargeObjectStream: loWrite reported writing " <> show n <> " bytes, expected " <> show l <> "."-    Sql.loTell conn lofd-  return (oid, t)---- | Act on a large object given by id, opening and closing the file descriptor appropriately.-withLargeObject-  :: Connection-  -> Oid-  -> IOMode-  -> (LoFd -> IO a)-  -> IO a-withLargeObject conn oid mode f =-  bracket (Sql.loOpen conn oid mode)-          (\lofd -> Sql.loClose conn lofd)-          f---- | Stream the contents of a database large object to the given output stream. Useful with Snap's 'addToOutput'.-streamLargeObject-  :: Connection-  -> Oid-  -> Streams.OutputStream BS.Builder-  -> IO ()-streamLargeObject conn oid os =-  withLargeObject conn oid ReadMode $ \lofd ->-    fix $ \again -> do-      chunk <- Sql.loRead conn lofd 8192 -- somewhat arbitrary-      case BS.length chunk of-        0 -> return ()-        _ -> do-          Streams.write (Just $ byteString chunk) os-          again---- | Stream the contents of a database large object to the given output stream. Useful with Snap's 'addToOutput'.-streamLargeObjectRange-  :: Connection-  -> Oid-  -> Int-  -> Int-  -> Streams.OutputStream BS.Builder-  -> IO ()-streamLargeObjectRange conn oid start end os =-  withLargeObject conn oid ReadMode $ \lofd -> do-    _ <- Sql.loSeek conn lofd Sql.AbsoluteSeek start-    let again n = do-          let nextChunkSize = min 8192 (end - n)-          chunk <- Sql.loRead conn lofd nextChunkSize-          case BS.length chunk of-            0 -> return ()-            k -> do-              Streams.write (Just $ byteString chunk) os-              again (n + k)-    again start---- | Act on the contents of a LargeObject as a Lazy ByteString-withLargeObjectLBS :: Connection -> Oid -> (LBS.ByteString -> IO ()) -> IO ()-withLargeObjectLBS conn oid f = do-  lo <- newIORef mempty-  cb <- makeOutputStream $ \case-    Just chunk -> modifyIORef lo $ \chunks -> chunks <> chunk-    Nothing -> do-      payload <- readIORef lo-      f $ BS.toLazyByteString payload-  streamLargeObject conn oid cb-  Streams.write Nothing cb
+ src/Database/PostgreSQL/Simple/LargeObjects/Stream.hs view
@@ -0,0 +1,116 @@+{-# LANGUAGE LambdaCase #-}+module Database.PostgreSQL.Simple.LargeObjects.Stream where++import Control.Exception.Lifted (AssertionFailed (..), bracket, throwIO)+import Control.Monad.Loops (whileJust_)+import Control.Monad.State as State+import qualified Data.ByteString as BS+import Data.ByteString.Builder (byteString)+import qualified Data.ByteString.Builder as BS+import qualified Data.ByteString.Lazy as LBS+import Data.IORef (modifyIORef, newIORef, readIORef)+import Data.Semigroup ((<>))+import Database.PostgreSQL.Simple+import Database.PostgreSQL.Simple.LargeObjects (LoFd, Oid (..))+import qualified Database.PostgreSQL.Simple.LargeObjects as Sql+import System.IO (IOMode (ReadMode, WriteMode))+import System.IO.Streams (makeOutputStream)+import qualified System.IO.Streams as Streams++-- | Given a strict ByteString, create a postgres large object and fill it with those contents.+newLargeObjectBS+  :: Connection+  -> BS.ByteString+  -> IO Oid+newLargeObjectBS conn contents = do+  oid <- Sql.loCreat conn+  n <- withLargeObject conn oid WriteMode $ \lofd -> Sql.loWrite conn lofd contents+  let l = BS.length contents+  when (n /= l) . throwIO . AssertionFailed $+    "newLargeObjectBS: loWrite reported writing " <> show n <> " bytes, expected " <> show l <> "."+  return oid++-- | Given a lazy ByteString, create a postgres large object and fill it with those contents.+-- Also returns the total length of the data written.+newLargeObjectLBS+  :: Connection+  -> LBS.ByteString+  -> IO (Oid, Int)+newLargeObjectLBS conn = newLargeObjectStream conn <=< Streams.fromLazyByteString++-- | Create a new large object from an input stream, returning its object id and overall size.+newLargeObjectStream+  :: Connection+  -> Streams.InputStream BS.ByteString+  -> IO (Oid, Int)+newLargeObjectStream conn s = do+  oid <- Sql.loCreat conn+  t <- withLargeObject conn oid WriteMode $ \lofd -> do+    whileJust_ (Streams.read s) $ \chunk -> do+      n <- Sql.loWrite conn lofd chunk+      let l = BS.length chunk+      when (n /= l) . throwIO . AssertionFailed $+        "newLargeObjectStream: loWrite reported writing " <> show n <> " bytes, expected " <> show l <> "."+    Sql.loTell conn lofd+  return (oid, t)++-- | Act on a large object given by id, opening and closing the file descriptor appropriately.+withLargeObject+  :: Connection+  -> Oid+  -> IOMode+  -> (LoFd -> IO a)+  -> IO a+withLargeObject conn oid mode f =+  bracket (Sql.loOpen conn oid mode)+          (\lofd -> Sql.loClose conn lofd)+          f++-- | Stream the contents of a database large object to the given output stream. Useful with Snap's 'addToOutput'.+streamLargeObject+  :: Connection+  -> Oid+  -> Streams.OutputStream BS.Builder+  -> IO ()+streamLargeObject conn oid os =+  withLargeObject conn oid ReadMode $ \lofd ->+    fix $ \again -> do+      chunk <- Sql.loRead conn lofd 8192 -- somewhat arbitrary+      case BS.length chunk of+        0 -> return ()+        _ -> do+          Streams.write (Just $ byteString chunk) os+          again++-- | Stream the contents of a database large object to the given output stream. Useful with Snap's 'addToOutput'.+streamLargeObjectRange+  :: Connection+  -> Oid+  -> Int+  -> Int+  -> Streams.OutputStream BS.Builder+  -> IO ()+streamLargeObjectRange conn oid start end os =+  withLargeObject conn oid ReadMode $ \lofd -> do+    _ <- Sql.loSeek conn lofd Sql.AbsoluteSeek start+    let again n = do+          let nextChunkSize = min 8192 (end - n)+          chunk <- Sql.loRead conn lofd nextChunkSize+          case BS.length chunk of+            0 -> return ()+            k -> do+              Streams.write (Just $ byteString chunk) os+              again (n + k)+    again start++-- | Act on the contents of a LargeObject as a Lazy ByteString+withLargeObjectLBS :: Connection -> Oid -> (LBS.ByteString -> IO ()) -> IO ()+withLargeObjectLBS conn oid f = do+  lo <- newIORef mempty+  cb <- makeOutputStream $ \case+    Just chunk -> modifyIORef lo $ \chunks -> chunks <> chunk+    Nothing -> do+      payload <- readIORef lo+      f $ BS.toLazyByteString payload+  streamLargeObject conn oid cb+  Streams.write Nothing cb