packages feed

postgresql-simple 0.3.3.2 → 0.3.4.0

raw patch · 15 files changed

+244/−30 lines, 15 files

Files

CONTRIBUTORS view
@@ -10,3 +10,4 @@ Jeff Chu <jeff@kiteedu.com> Oliver Charles <oliver.g.charles@gmail.com> Simon Meier <iridcode@gmail.com>+Alexey Uimanov <s9gf4ult@gmail.com>
postgresql-simple.cabal view
@@ -1,5 +1,5 @@ Name:                postgresql-simple-Version:             0.3.3.2+Version:             0.3.4.0 Synopsis:            Mid-Level PostgreSQL client library Description:     Mid-Level PostgreSQL client library, forked from mysql-simple.@@ -23,6 +23,7 @@      Database.PostgreSQL.Simple      Database.PostgreSQL.Simple.Arrays      Database.PostgreSQL.Simple.BuiltinTypes+     Database.PostgreSQL.Simple.Copy      Database.PostgreSQL.Simple.FromField      Database.PostgreSQL.Simple.FromRow      Database.PostgreSQL.Simple.LargeObjects@@ -75,7 +76,7 @@ source-repository this   type:     git   location: http://github.com/lpsmith/postgresql-simple-  tag:      v0.3.3.2+  tag:      v0.3.4.0  test-suite test   type:           exitcode-stdio-1.0
src/Database/PostgreSQL/Simple.hs view
@@ -13,7 +13,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- -- A mid-level client library for the PostgreSQL database, aimed at ease of -- use and high performance.@@ -483,11 +482,11 @@   where     declare = do         name <- newTempName conn-        _ <- execute_ conn $ mconcat +        _ <- execute_ conn $ mconcat                  [ "DECLARE ", name, " NO SCROLL CURSOR FOR ", q ]         return name     fetch (Query name) = query_ conn $-        Query (toByteString (fromByteString "FETCH FORWARD " +        Query (toByteString (fromByteString "FETCH FORWARD "                              <> integral chunkSize                              <> fromByteString " FROM "                              <> fromByteString name@@ -696,7 +695,7 @@ -- -- The obvious approach would appear to be something like this: ----- > instance (Param a) => QueryParam a where+-- > instance (ToField a) => ToRow a where -- >     ... -- -- Unfortunately, this wreaks havoc with type inference, so we take a@@ -775,9 +774,10 @@  -- $returning ----- The 'returning' function is similar to 'executeMany' but is--- intended for use with multi-tuple @INSERT@ or @UPDATE@ statements--- that make use of @RETURNING@.+-- PostgreSQL supports returning values from data manipulation statements+-- such as @INSERT@ and @UPDATE@.   You can use these statements by+-- using 'query' instead of 'execute'.   For multi-tuple inserts,+-- use 'returning' instead of 'executeMany'. -- -- For example, were there an auto-incrementing @id@ column and -- timestamp column @t@ that defaulted to the present time for the@@ -785,7 +785,8 @@ -- sales records and also return their new @id@s and timestamps. -- -- > let q = "insert into sales (amount, label) values (?,?) returning id, t"--- > xs :: [(Int, UTCTime)] <- returning conn q [(20,"Chips"),(300,"Wood")]+-- > xs :: [(Int, UTCTime)] <- query conn q (15,"Sawdust")+-- > ys :: [(Int, UTCTime)] <- returning conn q [(20,"Chips"),(300,"Wood")]  -- $result --
src/Database/PostgreSQL/Simple/Arrays.hs view
@@ -7,7 +7,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- -- A Postgres array parser and pretty-printer. ------------------------------------------------------------------------------@@ -91,4 +90,3 @@     f '\\' = "\\\\"     f c    = B.singleton c   -- TODO: Implement easy performance improvements with unfoldr.-
+ src/Database/PostgreSQL/Simple/Copy.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE CPP, DeriveDataTypeable #-}++------------------------------------------------------------------------------+-- |+-- Module:      Database.PostgreSQL.Simple.Copy+-- Copyright:   (c) 2013 Leon P Smith+-- License:     BSD3+-- Maintainer:  Leon P Smith <leon@melding-monads.com>+-- Stability:   experimental+--+-- mid-level support for COPY IN and COPY OUT.   See+-- <http://www.postgresql.org/docs/9.2/static/sql-copy.html> for+-- more information.+--+-- To use this binding,  first call 'copy' with a @COPY FROM STDIN@+-- or @COPY TO STDOUT@ query as documented in the link above.  Then+-- call @getCopyData@ repeatedly until it returns 'CopyOutDone' in+-- the former case,  or in the latter, call @putCopyData@ repeatedly+-- and then finish by calling either @putCopyEnd@ to proceed or+-- @putCopyError@ to abort.+--+-- You cannot issue another query on the same connection while a copy+-- is ongoing; this will result in an exception.   It is harmless to+-- concurrently call @getNotification@ on a connection while it is in+-- a copy in or copy out state,  however be aware that current versions+-- of the PostgreSQL backend will not deliver notifications to a client+-- while a transaction is ongoing.+--+------------------------------------------------------------------------------++module Database.PostgreSQL.Simple.Copy+    ( copy+    , copy_+    , CopyOutResult(..)+    , getCopyData+    , putCopyData+    , putCopyEnd+    , putCopyError+    ) where++import           Control.Applicative+import           Control.Concurrent+import           Control.Exception  ( throwIO )+import qualified Data.Attoparsec.ByteString.Char8 as P+import           Data.Typeable(Typeable)+import           Data.Int(Int64)+import qualified Data.ByteString.Char8 as B+import qualified Database.PostgreSQL.LibPQ as PQ+import           Database.PostgreSQL.Simple+import           Database.PostgreSQL.Simple.Types+import           Database.PostgreSQL.Simple.Internal++-- | Issue a query that changes a connection's state to @CopyIn@+--   (via a @COPY FROM STDIN@ query) or @CopyOut@ (via @COPY TO STDOUT@)+--   query.  Performs parameter subsitution.++copy :: ( ToRow params ) => Connection -> Query -> params -> IO ()+copy conn template qs = do+    q <- formatQuery conn template qs+    doCopy "Database.PostgreSQL.Simple.Copy.copy" conn template q++-- | Issue a query that changes a connection's state to @CopyIn@+--   (via a @COPY FROM STDIN@ query) or @CopyOut@ (via @COPY TO STDOUT@)+--   query.  Does not perform parameter subsitution.++copy_ :: Connection -> Query -> IO ()+copy_ conn (Query q) = do+    doCopy "Database.PostgreSQL.Simple.Copy.copy_" conn (Query q) q++doCopy :: B.ByteString -> Connection -> Query -> B.ByteString -> IO ()+doCopy funcName conn template q = do+    result <- exec conn q+    status <- PQ.resultStatus result+    let err = throwIO $ QueryError+                  (B.unpack funcName ++ " " ++ show status)+                  template+    case status of+      PQ.EmptyQuery    -> err+      PQ.CommandOk     -> err+      PQ.TuplesOk      -> err+      PQ.CopyOut       -> return ()+      PQ.CopyIn        -> return ()+      PQ.BadResponse   -> throwResultError funcName result status+      PQ.NonfatalError -> throwResultError funcName result status+      PQ.FatalError    -> throwResultError funcName result status++data CopyOutResult+   = CopyOutRow  !B.ByteString         -- ^ Data representing either exactly+                                       --   one row of the result,  or header+                                       --   or footer data depending on format.+   | CopyOutDone {-# UNPACK #-} !Int64 -- ^ No more rows, and a count of the+                                       --   number of rows returned.+     deriving (Eq, Typeable, Show)++-- | A connection must be in the @CopyOut@ state in order to call this+--   function,  via a @COPY TO STDOUT@ query.  If this returns a 'CopyOutRow',+--   the connection remains in the @CopyOut@ state, if it returns 'CopyOutDone',+--   then the connection has reverted to the ready state.++getCopyData :: Connection -> IO CopyOutResult+getCopyData conn = withConnection conn loop+  where+    funcName = "Database.PostgreSQL.Simple.Copy.getCopyData"+    loop pqconn = do+#if defined(mingw32_HOST_OS)+      row <- PQ.getCopyData pqconn False+#else+      row <- PQ.getCopyData pqconn True+#endif+      case row of+        PQ.CopyOutRow rowdata -> return $! CopyOutRow rowdata+        PQ.CopyOutDone -> CopyOutDone <$> getCopyCommandTag funcName pqconn+#if defined(mingw32_HOST_OS)+        PQ.CopyOutWouldBlock -> do+            fail (B.unpack funcName ++ ": the impossible happened")+#else+        PQ.CopyOutWouldBlock -> do+            mfd <- PQ.socket pqconn+            case mfd of+              Nothing -> throwIO (fdError funcName)+              Just fd -> do+                  threadWaitRead fd+                  _ <- PQ.consumeInput pqconn+                  loop pqconn+#endif+        PQ.CopyOutError -> do+            mmsg <- PQ.errorMessage pqconn+            throwIO SqlError {+                          sqlState       = "",+                          sqlExecStatus  = FatalError,+                          sqlErrorMsg    = maybe "" id mmsg,+                          sqlErrorDetail = "",+                          sqlErrorHint   = funcName+                        }++-- | A connection must be in the @CopyIn@ state in order to call this+--   function,  via a @COPY FROM STDIN@ query.  The connection remains+--   in a @CopyIn@ state after this function is called.   Note that+--   the data does not need to represent a single row,  or even an+--   integral number of rows.  The net result of+--   @putCopyData conn a >> putCopyData conn b@+--   is the same as @putCopyData conn c@ whenever @c == BS.append a b@.++putCopyData :: Connection -> B.ByteString -> IO ()+putCopyData conn dat = withConnection conn $ \pqconn -> do+    doCopyIn funcName (\c -> PQ.putCopyData c dat) pqconn+  where+    funcName = "Database.PostgreSQL.Simple.Copy.putCopyData"+++-- | A connection must be in the @CopyIn@ state in order to call this+--   function,  via a @COPY FROM STDIN@ query.  Completes the COPY IN+--   operation,  changing the connection's state back to normal.+--   Returns the number of rows processed.++putCopyEnd :: Connection -> IO Int64+putCopyEnd conn = withConnection conn $ \pqconn -> do+    doCopyIn funcName (\c -> PQ.putCopyEnd c Nothing) pqconn+    getCopyCommandTag funcName pqconn+  where+    funcName = "Database.PostgreSQL.Simple.Copy.putCopyEnd"++-- | A connection must be in the @CopyIn@ state in order to call this+--   function,  via a @COPY FROM STDIN@ query.  Aborts the COPY IN+--   operation,  changing the connection's state back to normal.++putCopyError :: Connection -> B.ByteString -> IO ()+putCopyError conn err = withConnection conn $ \pqconn -> do+    doCopyIn funcName (\c -> PQ.putCopyEnd c (Just err)) pqconn+  where+    funcName = "Database.PostgreSQL.Simple.Copy.putCopyError"+++doCopyIn :: B.ByteString -> (PQ.Connection -> IO PQ.CopyInResult)+         -> PQ.Connection -> IO ()+doCopyIn funcName action = loop+  where+    loop pqconn = do+      stat <- action pqconn+      case stat of+        PQ.CopyInOk    -> return ()+        PQ.CopyInError -> do+            mmsg <- PQ.errorMessage pqconn+            throwIO SqlError {+                      sqlState = "",+                      sqlExecStatus  = FatalError,+                      sqlErrorMsg    = maybe "" id mmsg,+                      sqlErrorDetail = "",+                      sqlErrorHint   = funcName+                    }+        PQ.CopyInWouldBlock -> do+            mfd <- PQ.socket pqconn+            case mfd of+              Nothing -> throwIO (fdError funcName)+              Just fd -> do+                  threadWaitWrite fd+                  loop pqconn+{-# INLINE doCopyIn #-}++getCopyCommandTag :: B.ByteString -> PQ.Connection -> IO Int64+getCopyCommandTag funcName pqconn = do+    result  <- maybe (fail errCmdStatus) return =<< PQ.getResult pqconn+    cmdStat <- maybe (fail errCmdStatus) return =<< PQ.cmdStatus result+    let rowCount =   P.string "COPY " *> (P.decimal <* P.endOfInput)+    case P.parseOnly rowCount cmdStat of+      Left  _ -> fail errCmdStatusFmt+      Right n -> return $! n+  where+    errCmdStatus    = B.unpack funcName ++ ": failed to fetch command status"+    errCmdStatusFmt = B.unpack funcName ++ ": failed to parse command status"
src/Database/PostgreSQL/Simple/FromField.hs view
@@ -10,7 +10,6 @@ License:     BSD3 Maintainer:  Leon P Smith <leon@melding-monads.com> Stability:   experimental-Portability: portable  The 'FromField' typeclass, for converting a single value in a row returned by a SQL query into a more useful Haskell representation.
src/Database/PostgreSQL/Simple/FromRow.hs view
@@ -7,7 +7,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- -- The 'FromRow' typeclass, for converting a row of results -- returned by a SQL query into a more useful Haskell representation.@@ -71,7 +70,7 @@ nfields result = unsafeDupablePerformIO (PQ.nfields result)  getTypeInfoByCol :: Row -> PQ.Column -> Conversion TypeInfo-getTypeInfoByCol Row{..} col = +getTypeInfoByCol Row{..} col =     Conversion $ \conn -> do       oid <- PQ.ftype rowresult col       Ok <$> getTypeInfo conn oid
src/Database/PostgreSQL/Simple/HStore.hs view
@@ -5,7 +5,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- -- Parsers and printers for hstore,  a extended type bundled with -- PostgreSQL providing finite maps from text strings to text strings.
src/Database/PostgreSQL/Simple/HStore/Implementation.hs view
@@ -7,7 +7,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- -- This code has yet to be profiled and optimized. --
src/Database/PostgreSQL/Simple/HStore/Internal.hs view
@@ -7,7 +7,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- ------------------------------------------------------------------------------ 
src/Database/PostgreSQL/Simple/Internal.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RecordWildCards #-}+ ------------------------------------------------------------------------------ -- | -- Module:      Database.PostgreSQL.Simple.Internal@@ -9,7 +10,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- -- Internal bits.  This interface is less stable and can change at any time. -- In particular this means that while the rest of the postgresql-simple@@ -44,6 +44,7 @@ import           Database.PostgreSQL.Simple.TypeInfo.Types(TypeInfo) import           Control.Monad.Trans.State.Strict import           Control.Monad.Trans.Reader+import           GHC.IO.Exception  -- | A Field represents metadata about a particular field --@@ -54,8 +55,8 @@ data Field = Field {      result   :: !PQ.Result    , column   :: {-# UNPACK #-} !PQ.Column-   , typeOid  :: {-# UNPACK #-} !PQ.Oid  -     -- ^ This returns the type oid associated with the column.  Analogous +   , typeOid  :: {-# UNPACK #-} !PQ.Oid+     -- ^ This returns the type oid associated with the column.  Analogous      --   to libpq's @PQftype@.    } @@ -315,11 +316,11 @@                    case oka of                      Ok _     -> return oka                      Errors _ -> (oka <|>) <$> runConversion mb conn-                       + instance Monad Conversion where    return a = Conversion $ \_conn -> return (return a)    m >>= f = Conversion $ \conn -> do-                 oka <- runConversion m conn +                 oka <- runConversion m conn                  case oka of                    Ok a -> runConversion (f a) conn                    Errors err -> return (Errors err)@@ -339,3 +340,14 @@     !n <- atomicModifyIORef connectionTempNameCounter           (\n -> let !n' = n+1 in (n', n'))     return $! Query $ B8.pack $ "temp" ++ show n++-- FIXME?  What error should getNotification and getCopyData throw?+fdError :: ByteString -> IOError+fdError funcName = IOError {+                     ioe_handle      = Nothing,+                     ioe_type        = ResourceVanished,+                     ioe_location    = B8.unpack funcName,+                     ioe_description = "failed to fetch file descriptor",+                     ioe_errno       = Nothing,+                     ioe_filename    = Nothing+                   }
src/Database/PostgreSQL/Simple/Notification.hs view
@@ -36,6 +36,7 @@  import           Control.Concurrent import           Control.Monad ( when )+import           Control.Exception ( throwIO ) import qualified Data.ByteString as B import           Database.PostgreSQL.Simple.Internal import qualified Database.PostgreSQL.LibPQ as PQ@@ -47,9 +48,6 @@    , notificationData    :: !B.ByteString    } -errfd :: String-errfd = "Database.PostgreSQL.Simple.Notification.getNotification: failed to fetch file descriptor"- convertNotice :: PQ.Notify -> Notification convertNotice PQ.Notify{..}     = Notification { notificationPid     = notifyBePid@@ -62,6 +60,7 @@ getNotification :: Connection -> IO Notification getNotification conn = loop False   where+    funcName = "Database.PostgreSQL.Simple.Notification.getNotification"     loop doConsume = do         res <- withConnection conn $ \c -> do                          when doConsume (PQ.consumeInput c >> return ())@@ -70,7 +69,7 @@                            Nothing -> do                                          mfd <- PQ.socket c                                          case mfd of-                                           Nothing -> fail errfd+                                           Nothing -> throwIO $ fdError funcName                                            Just fd -> return (Left fd)                            Just msg -> return (Right msg)         -- FIXME? what happens if the connection is closed/reset right here?
src/Database/PostgreSQL/Simple/ToField.hs view
@@ -9,7 +9,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- -- The 'ToField' typeclass, for rendering a parameter to a SQL query. --
src/Database/PostgreSQL/Simple/ToRow.hs view
@@ -6,7 +6,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- -- The 'ToRow' typeclass, for rendering a collection of -- parameters to a SQL query.
src/Database/PostgreSQL/Simple/Types.hs view
@@ -8,7 +8,6 @@ -- License:     BSD3 -- Maintainer:  Leon P Smith <leon@melding-monads.com> -- Stability:   experimental--- Portability: portable -- -- Basic types. --