-- | -- Backend-aware parsed results' handlers. module Hasql.Postgres.ResultHandler where import Hasql.Postgres.Prelude import qualified Hasql.Backend as Backend import qualified Hasql.Postgres.ResultParser as Result import qualified Hasql.Postgres.ErrorCode as ErrorCode type ResultHandler a = Result.Result -> IO a {-# INLINE unit #-} unit :: ResultHandler () unit = resultHandler $ \case Result.CommandOK _ -> Right $ return () _ -> Left "Not a unit" {-# INLINE rowsStream #-} rowsStream :: ResultHandler Result.RowsStream rowsStream = resultHandler $ \case Result.Rows s _ _ -> Right s _ -> Left "Not a rows result" {-# INLINE rowsVector #-} rowsVector :: ResultHandler Result.RowsVector rowsVector = resultHandler $ \case Result.Rows _ v _ -> Right v _ -> Left "Not a rows result" {-# INLINE rowsList #-} rowsList :: ResultHandler Result.RowsList rowsList = resultHandler $ \case Result.Rows _ _ l -> Right l _ -> Left "Not a rows result" {-# INLINE rowsAffected #-} rowsAffected :: ResultHandler ByteString rowsAffected = resultHandler $ \case Result.CommandOK (Just v) -> Right $ return v _ -> Left "Not a number of affected rows" {-# INLINE resultHandler #-} resultHandler :: (Result.Result -> Either Text (IO a)) -> ResultHandler a resultHandler partial result = case partial result of Right io -> io Left text -> -- Handle erroneous results with unexpected result as a fallback. case result of Result.StatusError _ c _ _ _ | elem c codes -> throwIO Backend.TransactionConflict where codes = [ ErrorCode.transaction_rollback, ErrorCode.transaction_integrity_constraint_violation, ErrorCode.serialization_failure, ErrorCode.statement_completion_unknown, ErrorCode.deadlock_detected ] _ -> maybe (throwIO $ Backend.UnexpectedResult text) (throwIO . Backend.ErroneousResult) (Result.erroneousResultText result)