mysql-haskell 0.8.3.0 → 0.8.4.0
raw patch · 5 files changed
+60/−16 lines, 5 filesdep ~tastyPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: tasty
API changes (from Hackage documentation)
+ Database.MySQL.Base: executeMany_ :: MySQLConn -> Query -> IO [OK]
+ Database.MySQL.Connection: waitCommandReplys :: InputStream Packet -> IO [OK]
+ Database.MySQL.Protocol.Packet: isThereMore :: OK -> Bool
- Database.MySQL.Base: skipToEof :: InputStream a -> IO ()
+ Database.MySQL.Base: skipToEof :: () => InputStream a -> IO ()
Files
- ChangeLog.md +5/−0
- Database/MySQL/Base.hs +14/−0
- Database/MySQL/Connection.hs +33/−15
- Database/MySQL/Protocol/Packet.hs +7/−0
- mysql-haskell.cabal +1/−1
ChangeLog.md view
@@ -1,5 +1,10 @@ # Revision history for mysql-haskell +## 0.8.4.0 -- 2018-10-23++* Add `executeMany_` to execute batch SQLs, [#26](https://github.com/winterland1989/mysql-haskell/issues/26).+* Optimize connection closing sequence, [#20](https://github.com/winterland1989/mysql-haskell/pull/20), [#25](https://github.com/winterland1989/mysql-haskell/pull/25).+ ## 0.8.3.0 -- 2017-10-09 * Remove unnecessary exports from `Database.MySQL.Base`.
Database/MySQL/Base.hs view
@@ -37,6 +37,7 @@ -- * Direct query , execute , executeMany+ , executeMany_ , execute_ , query_ , queryVector_@@ -121,6 +122,19 @@ {-# SPECIALIZE executeMany :: MySQLConn -> Query -> [[MySQLValue]] -> IO [OK] #-} {-# SPECIALIZE executeMany :: MySQLConn -> Query -> [[Param]] -> IO [OK] #-}++-- | Execute multiple querys (without param) which don't return result-set.+--+-- This's useful when your want to execute multiple SQLs without params, e.g. from a+-- SQL dump, or a table migration plan.+--+-- @since 0.8.4.0+--+executeMany_ :: MySQLConn -> Query -> IO [OK]+executeMany_ conn@(MySQLConn is os _ _) qry = do+ guardUnconsumed conn+ writeCommand (COM_QUERY (fromQuery qry)) os+ waitCommandReplys is -- | Execute a MySQL query which don't return a result-set. --
Database/MySQL/Connection.hs view
@@ -13,8 +13,9 @@ module Database.MySQL.Connection where +import Control.Applicative import Control.Exception (Exception, bracketOnError,- throwIO)+ throwIO, catch, SomeException) import Control.Monad import qualified Crypto.Hash as Crypto import qualified Data.Binary as Binary@@ -106,23 +107,29 @@ -- connectDetail :: ConnectInfo -> IO (Greeting, MySQLConn) connectDetail (ConnectInfo host port db user pass charset)- = bracketOnError open TCP.close go+ = bracketOnError open TCP.close go where open = connectWithBufferSize host port bUFSIZE go c = do- let is = TCP.source c- is' <- decodeInputStream is- p <- readPacket is'- greet <- decodeFromPacket p- let auth = mkAuth db user pass charset greet- write c $ encodeToPacket 1 auth- q <- readPacket is'- if isOK q- then do- consumed <- newIORef True- let conn = MySQLConn is' (write c) (TCP.close c) consumed- return (greet, conn)- else TCP.close c >> decodeFromPacket q >>= throwIO . ERRException+ let is = TCP.source c+ is' <- decodeInputStream is+ p <- readPacket is'+ greet <- decodeFromPacket p+ let auth = mkAuth db user pass charset greet+ write c $ encodeToPacket 1 auth+ q <- readPacket is'+ if isOK q+ then do+ consumed <- newIORef True+ let waitNotMandatoryOK = catch+ (void (waitCommandReply is')) -- server will either reply an OK packet+ ((\ _ -> return ()) :: SomeException -> IO ()) -- or directy close the connection+ conn = MySQLConn is'+ (write c)+ (writeCommand COM_QUIT (write c) >> waitNotMandatoryOK >> TCP.close c)+ consumed+ return (greet, conn)+ else TCP.close c >> decodeFromPacket q >>= throwIO . ERRException connectWithBufferSize h p bs = TCP.connectSocket h p >>= TCP.socketToConnection bs write c a = TCP.send c $ Binary.runPut . Binary.put $ a@@ -197,6 +204,17 @@ | isOK p -> decodeFromPacket p | otherwise -> throwIO (UnexpectedPacket p) {-# INLINE waitCommandReply #-}++waitCommandReplys :: InputStream Packet -> IO [OK]+waitCommandReplys is = do+ p <- readPacket is+ if | isERR p -> decodeFromPacket p >>= throwIO . ERRException+ | isOK p -> do ok <- decodeFromPacket p+ if isThereMore ok+ then (ok :) <$> waitCommandReplys is+ else return [ok]+ | otherwise -> throwIO (UnexpectedPacket p)+{-# INLINE waitCommandReplys #-} readPacket :: InputStream Packet -> IO Packet readPacket is = Stream.read is >>= maybe
Database/MySQL/Protocol/Packet.hs view
@@ -72,6 +72,13 @@ isEOF p = L.index (pBody p) 0 == 0xFE {-# INLINE isEOF #-} +-- | Is there more packet to be read?+--+-- https://dev.mysql.com/doc/internals/en/status-flags.html+isThereMore :: OK -> Bool+isThereMore p = okStatus p .&. 0x08 /= 0+{-# INLINE isThereMore #-}+ -- | Decoding packet inside IO, throw 'DecodePacketException' on fail parsing, -- here we choose stability over correctness by omit incomplete consumed case: -- if we successful parse a packet, then we don't care if there're bytes left.
mysql-haskell.cabal view
@@ -1,5 +1,5 @@ name: mysql-haskell-version: 0.8.3.0+version: 0.8.4.0 synopsis: pure haskell MySQL driver description: pure haskell MySQL driver license: BSD3