hasql-0.20.1: library/Hasql/Core/Protocol/Parse/Responses.hs
module Hasql.Core.Protocol.Parse.Responses where
import Hasql.Prelude hiding (fail)
import Hasql.Core.Protocol.Parse.Primitives
import Hasql.Core.Model
import Ptr.Parse
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as A
import qualified Data.Vector as D
import qualified Hasql.Core.MessageTypePredicates as C
import qualified Hasql.Core.NoticeFieldTypes as E
import qualified Hasql.Core.ParseDataRow as F
{-# INLINE responseBody #-}
responseBody :: Word8 -> Parse (Maybe Response)
responseBody type_ =
{-# SCC "responseBody" #-}
if
| C.dataRow type_ -> (Just . DataRowResponse) <$> allBytes
| C.commandComplete type_ -> Just . CommandCompleteResponse <$> commandCompleteBody
| C.readyForQuery type_ -> fmap (Just . ReadyForQueryResponse) readyForQueryBody
| C.parseComplete type_ -> pure (Just ParseCompleteResponse)
| C.bindComplete type_ -> pure (Just BindCompleteResponse)
| C.emptyQuery type_ -> pure (Just EmptyQueryResponse)
| C.notification type_ -> Just <$> notificationBody NotificationResponse
| C.error type_ -> Just <$> errorResponseBody ErrorResponse
| C.authentication type_ -> fmap (Just . AuthenticationResponse) authenticationBody
| C.parameterStatus type_ -> Just <$> parameterStatusBody ParameterStatusResponse
| True -> pure Nothing
{-# INLINE unparsedFieldsOfDataRowBody #-}
unparsedFieldsOfDataRowBody :: Parse (Vector (Maybe ByteString))
unparsedFieldsOfDataRowBody =
{-# SCC "unparsedFieldsOfDataRowBody" #-}
do
amountOfColumns <- beWord16
D.replicateM (fromIntegral amountOfColumns) sizedBytes
{-# INLINE dataRowBody #-}
dataRowBody :: F.ParseDataRow row -> Parse row
dataRowBody (F.ParseDataRow rowLength parse) =
do
amountOfColumns <- beWord16
if fromIntegral amountOfColumns == rowLength
then parse
else fail (fromString
(showString "Invalid amount of columns: "
(shows amountOfColumns
(showString ", expecting "
(show rowLength)))))
{-# INLINE commandCompleteBody #-}
commandCompleteBody :: Parse Int
commandCompleteBody =
{-# SCC "commandCompleteBody" #-}
do
header <- bytesWhile byteIsUpperLetter
word8
case header of
"INSERT" -> skipWhile byteIsDigit *> word8 *> unsignedASCIIIntegral <* word8
_ -> unsignedASCIIIntegral <* word8
where
byteIsUpperLetter byte =
byte - 65 <= 25
byteIsDigit byte =
byte - 48 <= 9
{-# INLINE readyForQueryBody #-}
readyForQueryBody :: Parse TransactionStatus
readyForQueryBody =
{-# SCC "readyForQueryBody" #-}
do
statusByte <- word8
case statusByte of
73 -> return IdleTransactionStatus
84 -> return ActiveTransactionStatus
69 -> return FailedTransactionStatus
_ -> fail ("Unexpected transaction status byte: " <> (fromString . show) statusByte)
{-# INLINE notificationBody #-}
notificationBody :: (Word32 -> ByteString -> ByteString -> result) -> Parse result
notificationBody result =
{-# SCC "notificationBody" #-}
result <$> beWord32 <*> nullTerminatedBytes <*> nullTerminatedBytes
{-# INLINE errorResponseBody #-}
errorResponseBody :: (ByteString -> ByteString -> result) -> Parse result
errorResponseBody result =
{-# SCC "errorResponseBody" #-}
iterate Nothing Nothing
where
iterate code message =
element <|> end
where
element =
join (noticeField (\type_ payload ->
if
| type_ == E.code -> iterate (Just payload) message
| type_ == E.message -> iterate code (Just payload)
| True -> iterate code message))
end =
do
word8
case code of
Just code -> case message of
Just message -> return (result code message)
_ -> fail "The \"message\" field is missing"
_ -> fail "The \"code\" field is missing"
{-# INLINE noticeField #-}
noticeField :: (Word8 -> ByteString -> result) -> Parse result
noticeField result =
{-# SCC "noticeField" #-}
result <$> word8 <*> nullTerminatedBytes
{-# INLINE authenticationBody #-}
authenticationBody :: Parse AuthenticationStatus
authenticationBody =
{-# SCC "authenticationBody" #-}
do
status <- beWord32
case status of
0 -> return OkAuthenticationStatus
3 -> return NeedClearTextPasswordAuthenticationStatus
5 -> do
salt <- bytes 4
return (NeedMD5PasswordAuthenticationStatus salt)
_ -> fail ("Unsupported authentication status: " <> (fromString . show) status)
{-# INLINE parameterStatusBody #-}
parameterStatusBody :: (ByteString -> ByteString -> result) -> Parse result
parameterStatusBody result =
{-# SCC "parameterStatusBody" #-}
result <$> nullTerminatedBytes <*> nullTerminatedBytes