packages feed

ms-tds 0.2.0.0 → 0.3.0.0

raw patch · 6 files changed

+106/−121 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Database.Tds.Message: ServerMessage :: a -> ServerMessage a
- Database.Tds.Message: class Binary a => ServerMessageInstance a
- Database.Tds.Message: instance Data.Binary.Class.Binary Database.Tds.Message.ClientMessage
- Database.Tds.Message: instance Database.Tds.Message.ServerMessageInstance Database.Tds.Message.Prelogin.Prelogin
- Database.Tds.Message: instance Database.Tds.Message.ServerMessageInstance Database.Tds.Message.Server.TokenStreams
- Database.Tds.Message: instance Database.Tds.Message.ServerMessageInstance a => Data.Binary.Class.Binary (Database.Tds.Message.ServerMessage a)
- Database.Tds.Message: instance GHC.Show.Show a => GHC.Show.Show (Database.Tds.Message.ServerMessage a)
- Database.Tds.Message: newtype ServerMessage a
+ Database.Tds.Message: class Binary a => ServerMessage a
+ Database.Tds.Message: getClientMessage :: Get ClientMessage
+ Database.Tds.Message: getServerMessage :: ServerMessage a => Get a
+ Database.Tds.Message: instance Database.Tds.Message.ServerMessage Database.Tds.Message.Prelogin.Prelogin
+ Database.Tds.Message: instance Database.Tds.Message.ServerMessage Database.Tds.Message.Server.TokenStreams
+ Database.Tds.Message: l7ClientProgVer :: Login7 -> Word32
+ Database.Tds.Message: l7CltIntName :: Login7 -> Text
+ Database.Tds.Message: l7PacketSize :: Login7 -> Word32
+ Database.Tds.Message: putClientMessage :: Word32 -> ClientMessage -> Put
+ Database.Tds.Message: putServerMessage :: ServerMessage a => Word32 -> a -> Put

Files

README.md view
@@ -42,9 +42,6 @@   * Test legacy data types  -* Transaction support-- * Implement data types   * AltMetaData   * AltRow@@ -71,8 +68,6 @@   * Login7: client program version   * Login7: timezone   * Login7: language-  * Login7: collation-  * RpcReqBatchProcId: ProcID   * TSEnvChange: Type   * TSLoginAck: Interface   * TSReturnValue: Status@@ -80,7 +75,7 @@  * Implement Flag interfaces   * Header status-  * PLOEncription+  * PLOEncryption   * PLOMars   * Login7 flag1   * Login7 flag2@@ -102,7 +97,6 @@   * Mars support   * SSPI support   * FedAuth support-  * Variable PacketSize support   * TDS protocol versions other than 7.1    * Attention  
ms-tds.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 49394a8278191a141ae8a27d9e19f2c2d1bbab3d689aa2454d6b9b44ae2312e9+-- hash: efad0660f5cf0042c8ade6a168534cd8a14bd8d00708563ceeb560d6e059d864  name:           ms-tds-version:        0.2.0.0+version:        0.3.0.0 synopsis:       TDS Protocol implemented in Haskell description:    Please see the README on GitHub at <https://github.com/mitsuji/ms-tds#readme> category:       Database
src/Database/Tds/Message.hs view
@@ -1,9 +1,14 @@ module Database.Tds.Message ( -- * Client Message                               ClientMessage (..)+                            , getClientMessage+                            , putClientMessage                                                            -- ** Login                             , Login7+                            , tdsVersion                             , defaultLogin7+                            , l7PacketSize+                            , l7ClientProgVer                             , l7ConnectionID                             , l7OptionFlags1                             , l7OptionFlags2@@ -11,6 +16,7 @@                             , l7TypeFlags                             , l7TimeZone                             , l7Collation+                            , l7CltIntName                             , l7Language                             , l7ClientPID                             , l7ClientMacAddr@@ -20,7 +26,6 @@                             , l7UserName                             , l7Password                             , l7Database-                            , tdsVersion                                                          -- ** SQL Batch                             , SqlBatch (..)@@ -39,7 +44,8 @@                                                          -- * Server Message                             , ServerMessage (..)-                            , ServerMessageInstance (..)+                            , getServerMessage+                            , putServerMessage                                                          , TokenStreams (..)                             , TokenStream (..)@@ -152,6 +158,9 @@  import Control.Applicative((<$>)) +import qualified Data.ByteString.Lazy as LB+import qualified Data.ByteString.Builder as BB+ import Data.Word (Word8(..),Word16(..),Word32(..),Word64(..)) import Data.Int (Int8(..),Int16(..),Int32(..),Int64(..)) @@ -159,6 +168,9 @@ import qualified Data.Binary.Put as Put import qualified Data.Binary.Get as Get +import Control.Monad.Writer (WriterT(..),runWriterT,tell)+import Control.Monad.Trans (lift)+ import Database.Tds.Primitives.Null import Database.Tds.Primitives.Decimal import Database.Tds.Primitives.Money@@ -174,7 +186,41 @@   +putMessage :: Word32 -> Word8 -> LB.ByteString -> Put+putMessage ps pt bs = mapM_ f $ split (ps -headerLength) bs+  where+    f :: (Bool,LB.ByteString) -> Put+    f (isLast,bs) = do+      let+        len = (fromIntegral $ LB.length bs) + headerLength+        flg = if isLast then 0x01 else 0x00 -- last flag+      put $ Header pt flg len 0 0 0+      Put.putLazyByteString bs +  +    split :: Word32 -> LB.ByteString -> [(Bool,LB.ByteString)]+    split len lbs =+      let+        (lbs',rem) = LB.splitAt (fromIntegral len) lbs+      in if LB.null rem+         then [(True,lbs')]+         else (False,lbs'): split len rem+++getMessage :: Get (Word8,LB.ByteString)+getMessage = (\(pt,bs) -> (pt,BB.toLazyByteString bs)) <$> runWriterT f+  where+    f :: WriterT BB.Builder Get Word8+    f = do+      (Header pt flg len _ _ _) <- lift get+      tell =<< BB.byteString <$> (lift $ Get.getByteString (fromIntegral $ len -8))+      if flg == 0x01+        then return pt+        else f++++ -- | [\[MS-TDS\] 2.2.1 Client Messages](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/7ea9ee1a-b461-41f2-9004-141c0e712935) data ClientMessage = CMPrelogin !Prelogin                    | CMLogin7 !Login7@@ -182,14 +228,14 @@                    | CMRpcRequest !RpcRequest                    deriving (Show) -putClientMessage :: ClientMessage -> Put-putClientMessage x =+putClientMessage :: Word32 -> ClientMessage -> Put+putClientMessage ps x =   let (pt,bs) = case x of         CMPrelogin   pr -> (0x12,encode pr)         CMLogin7     l7 -> (0x10,encode l7)         CMSqlBatch   b  -> (0x01,encode b)         CMRpcRequest r  -> (0x03,encode r)-  in putMessage pt bs+  in putMessage ps pt bs  getClientMessage :: Get ClientMessage getClientMessage = do@@ -201,34 +247,23 @@     0x03 -> return $ CMRpcRequest $ decode bs     _ -> fail "getClientMessage: invalid packet type" -instance Binary ClientMessage where-  put = putClientMessage-  get = getClientMessage   -class Binary a => ServerMessageInstance a-instance ServerMessageInstance Prelogin-instance ServerMessageInstance TokenStreams+-- | [\[MS-TDS\] 2.2.2 Server Messages](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/342f4cbb-2b4b-489c-8b63-f99b12021a94)+class Binary a => ServerMessage a+instance ServerMessage Prelogin+instance ServerMessage TokenStreams -putServerMessageInstance :: ServerMessageInstance a => a -> Put-putServerMessageInstance x =-  putMessage 0x04 $ encode x+putServerMessage :: ServerMessage a => Word32 -> a -> Put+putServerMessage ps x =+  putMessage ps 0x04 $ encode x -getServerMessageInstance :: ServerMessageInstance a => Get a-getServerMessageInstance = do+getServerMessage :: ServerMessage a => Get a+getServerMessage = do   (pt,bs) <- getMessage   case pt of     0x04 -> return $ decode bs     _ -> fail "getServerMessageInstance: invalid packet type"----- | [\[MS-TDS\] 2.2.2 Server Messages](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/342f4cbb-2b4b-489c-8b63-f99b12021a94)-newtype ServerMessage a = ServerMessage a-                        deriving (Show)--instance (ServerMessageInstance a) => Binary (ServerMessage a) where-  put (ServerMessage x) = putServerMessageInstance x-  get = ServerMessage <$> getServerMessageInstance  
src/Database/Tds/Message/Client.hs view
@@ -6,7 +6,10 @@   module Database.Tds.Message.Client ( Login7+                                   , tdsVersion                                    , defaultLogin7+                                   , l7PacketSize+                                   , l7ClientProgVer                                    , l7ConnectionID                                    , l7OptionFlags1                                    , l7OptionFlags2@@ -14,6 +17,7 @@                                    , l7TypeFlags                                    , l7TimeZone                                    , l7Collation+                                   , l7CltIntName                                    , l7Language                                    , l7ClientPID                                    , l7ClientMacAddr@@ -58,7 +62,6 @@  import Control.Monad (foldM,foldM_) -import Database.Tds.Message.Header import Database.Tds.Message.Prelogin import Database.Tds.Message.DataStream import Database.Tds.Primitives.Collation@@ -90,20 +93,29 @@                      }             deriving (Show) ++tdsVersion :: Word32+tdsVersion = 0x71000001+-- [MEMO]+-- tds70Version = 0x70000000+-- tds71Version = 0x71000001+-- tds72Version = 0x72090002+-- tds73Version = 0x730B0003+-- tds74Version = 0x74000004++ defaultLogin7 :: Login7 defaultLogin7 = Login7 { l7TdsVersion = tdsVersion-                         , l7PacketSize = packetSize-                         , l7ClientProgVer = 0x0683f2f8  -- [MEMO] 0x00000007+                         , l7PacketSize = 4096+                         , l7ClientProgVer = 0 -- [MEMO] 0x0683f2f8, 0x00000007                          , l7ConnectionID = 0                          , l7OptionFlags1 = 0x80 + 0x40 + 0x20                          , l7OptionFlags2 = 0  -- [MEMO] 0x02 + 0x01--                          , l7OptionFlags3 = 0                          , l7TypeFlags = 0                          , l7TimeZone = 0  -- [MEMO] -120                          , l7Collation = 0x00000000  -- [MEMO] 0x36040000, 0x1104d000, 0x09040000-                         , l7CltIntName = T.pack "DB-Library" -- [MDMO] "OLEDB", "ODBC"+                         , l7CltIntName = mempty -- [MDMO] "DB-Library", "OLEDB", "ODBC"                          , l7Language = mempty -- [MEMO] "us_english"                          , l7ClientPID = 0                          , l7ClientMacAddr = mempty
src/Database/Tds/Message/DataStream.hs view
@@ -499,7 +499,7 @@   withValidIntegral :: String -> TypeInfo -> (TypeInfo -> a) -> a-withValidIntegral ht = f+withValidIntegral tn = f   where     f :: TypeInfo -> (TypeInfo -> a) -> a     f ti@TIBit g = g ti@@ -512,7 +512,7 @@     f ti@TIIntN2 g = g ti      f ti@TIIntN4 g = g ti     f ti@TIIntN8 g = g ti-    f ti _ = error $ "withValidIntegral: " <> (show ti) <> " is not convertible from/to " <> ht+    f ti _ = error $ "withValidIntegral: " <> (show ti) <> " is not convertible from/to " <> tn  withValidBool = withValidIntegral "Bool" withValidInt = withValidIntegral "Int"@@ -522,16 +522,12 @@ isIntegralN = f   where     f :: TypeInfo -> Bool-    f TIBit = False-    f TIInt1 = False-    f TIInt2 = False-    f TIInt4 = False-    f TIInt8 = False     f TIBitN = True     f TIIntN1 = True     f TIIntN2 = True     f TIIntN4 = True     f TIIntN8 = True+    f _ = False   getIntegral :: Integral a => TypeInfo -> Get a@@ -576,10 +572,9 @@ isMoneyN = f   where     f :: TypeInfo -> Bool-    f TIMoney4 = False-    f TIMoney8 = False     f TIMoneyN4 = True     f TIMoneyN8 = True+    f _ = False      getMoney :: TypeInfo -> Get Money getMoney TIMoney4 = bytesToMoney4 <$> Get.getInt32le@@ -613,10 +608,9 @@ isUTCTimeN = f   where     f :: TypeInfo -> Bool-    f TIDateTime4 = False-    f TIDateTime8 = False     f TIDateTimeN4 = True     f TIDateTimeN8 = True+    f _ = False      getUTCTime :: TypeInfo -> Get UTCTime getUTCTime TIDateTime4 = bytesToUtc4 <$> Get.getWord16le <*> Get.getWord16le@@ -640,14 +634,14 @@   withValidFloat' :: String -> TypeInfo -> (TypeInfo -> a) -> a-withValidFloat' hn = f+withValidFloat' tn = f   where     f :: TypeInfo -> (TypeInfo -> a) -> a     f ti@TIFlt4 g = g ti     f ti@TIFlt8 g = g ti     f ti@TIFltN4 g = g ti     f ti@TIFltN8 g = g ti-    f ti _ = error $ "withValidFloat': " <> (show ti) <> " is not convertible from/to " <> hn+    f ti _ = error $ "withValidFloat': " <> (show ti) <> " is not convertible from/to " <> tn  withValidFloat = withValidFloat' "Float" withValidDouble = withValidFloat' "Double"@@ -656,10 +650,9 @@ isFloatN = f   where     f :: TypeInfo -> Bool-    f TIFlt4 = False-    f TIFlt8 = False     f TIFltN4 = True     f TIFltN8 = True+    f _ = False      getFloat :: Fractional a => TypeInfo -> Get a getFloat TIFlt4 = realToFrac . wordToFloat <$> Get.getWord32le@@ -729,18 +722,20 @@   -withValidText :: TypeInfo -> (TypeInfo -> a) -> a-withValidText  = f+withValidText' :: String -> TypeInfo -> (TypeInfo -> a) -> a+withValidText' tn = f   where     f :: TypeInfo -> (TypeInfo -> a) -> a     f ti@(TINChar _ _) g = g ti     f ti@(TINVarChar _ _) g = g ti     f ti@(TINText _ _) g = g ti-    f ti _ = error $ "withValidText: " <> (show ti) <> " is not convertible from/to Text"-    +    f ti _ = error $ "withValidText: " <> (show ti) <> " is not convertible from/to " <> tn +withValidText = withValidText' "Text"+withValidString = withValidText' "String"  + runGet :: Get a -> LB.ByteString -> a runGet f bs = Get.runGet f bs @@ -843,8 +838,13 @@   fromRawBytes ti Nothing = withValidText ti $ \_ -> error "Text.fromRawBytes: Null value is not convertible to Text"   toRawBytes ti t = withValidText ti $ \_ -> Just $ LT.encodeUtf16LE t +instance Data String where+  fromRawBytes ti (Just bs) = withValidString ti $ \_ -> LT.unpack $ LT.decodeUtf16LE bs+  fromRawBytes ti Nothing = withValidString ti $ \_ -> error "String.fromRawBytes: Null value is not convertible to String"+  toRawBytes ti s = withValidString ti $ \_ -> Just $ LT.encodeUtf16LE $ LT.pack s  + instance Data (Maybe Bool) where   fromRawBytes ti rb = withValidBool ti $ \vt -> runGetBool vt <$> rb   toRawBytes ti b = withValidBool ti $ \vt ->@@ -927,5 +927,9 @@ instance Data (Maybe LT.Text) where   fromRawBytes ti rb = withValidText ti $ \_ -> LT.decodeUtf16LE <$> rb    toRawBytes ti t = withValidText ti $ \_ -> LT.encodeUtf16LE <$> t++instance Data (Maybe String) where+  fromRawBytes ti rb = withValidString ti $ \_ -> LT.unpack . LT.decodeUtf16LE <$> rb +  toRawBytes ti s = withValidString ti $ \_ -> LT.encodeUtf16LE . LT.pack <$> s  
src/Database/Tds/Message/Header.hs view
@@ -1,18 +1,10 @@ {-# OPTIONS_HADDOCK hide #-} -- Packet Header:   https://msdn.microsoft.com/en-us/library/dd340948.aspx -module Database.Tds.Message.Header ( packetSize-                                   , tdsVersion-                                   , Header (..)-                                   , putMessage-                                   , getMessage+module Database.Tds.Message.Header ( Header (..)+                                   , headerLength                                    ) where -import Control.Applicative((<$>))--import qualified Data.ByteString.Lazy as LB-import qualified Data.ByteString.Builder as BB- import Data.Word (Word8(..),Word16(..),Word32(..),Word64(..)) import Data.Int (Int8(..),Int16(..),Int32(..),Int64(..)) @@ -20,10 +12,7 @@ import qualified Data.Binary.Put as Put import qualified Data.Binary.Get as Get -import Control.Monad.Writer (WriterT(..),runWriterT,tell)-import Control.Monad.Trans (lift) - type Type = Word8 type Status = Word8 type Length = Word16@@ -37,21 +26,7 @@ headerLength :: Integral a => a headerLength = fromIntegral 8 -packetSize :: Integral a => a-packetSize = fromIntegral 4096 -tdsVersion :: Word32-tdsVersion = 0x71000001---- [MEMO]--- tds70Version = 0x70000000--- tds71Version = 0x71000001--- tds72Version = 0x72090002--- tds73Version = 0x730B0003--- tds74Version = 0x74000004--- -- https://msdn.microsoft.com/en-us/library/dd340948.aspx putHeader :: Header -> Put putHeader (Header pt st len spid pcid win) = do@@ -78,40 +53,5 @@   put = putHeader   get = getHeader ---putMessage :: Word8 -> LB.ByteString -> Put-putMessage pt bs = mapM_ f $ split (packetSize -headerLength) bs-  where-    f :: (Bool,LB.ByteString) -> Put-    f (isLast,bs) = do-      let-        len = (fromIntegral $ LB.length bs) + headerLength-        flg = if isLast then 0x01 else 0x00 -- last flag-      put $ Header pt flg len 0 0 0-      Put.putLazyByteString bs---    split :: Int64 -> LB.ByteString -> [(Bool,LB.ByteString)]-    split len lbs =-      let-        (lbs',rem) = LB.splitAt len lbs-      in if LB.null rem-         then [(True,lbs')]-         else (False,lbs'): split len rem-----getMessage :: Get (Word8,LB.ByteString)-getMessage = (\(pt,bs) -> (pt,BB.toLazyByteString bs)) <$> runWriterT f-  where-    f :: WriterT BB.Builder Get Word8-    f = do-      (Header pt flg len _ _ _) <- lift get-      tell =<< BB.byteString <$> (lift $ Get.getByteString (fromIntegral $ len -8))-      if flg == 0x01-        then return pt-        else f