packages feed

polysemy-hasql-0.0.1.0: lib/Polysemy/Hasql/Statement/Transaction.hs

module Polysemy.Hasql.Statement.Transaction where

import Exon (exon)
import Hasql.Decoders (noResult)
import Hasql.Encoders (noParams)
import Hasql.Statement (Statement (Statement))

data AccessMode =
  Read
  |
  Write
  deriving stock (Show, Eq, Ord, Enum, Bounded)

data IsolationLevel =
  ReadCommitted
  |
  RepeatableRead
  |
  Serializable
  deriving stock (Show, Eq, Ord, Enum, Bounded)

data TransactionConfig =
  TransactionConfig {
    isolationLevel :: IsolationLevel,
    accessMode :: AccessMode,
    deferrable :: Bool
  }
  deriving stock (Eq, Show, Generic)

instance Default TransactionConfig where
  def =
    TransactionConfig {
      isolationLevel = ReadCommitted,
      accessMode = Write,
      deferrable = False
    }

beginTransactionSql :: TransactionConfig -> ByteString
beginTransactionSql TransactionConfig {..} =
  [exon|start transaction #{isolation isolationLevel} #{mode accessMode} #{defer}|]
  where
    isolation = \case
      ReadCommitted -> "isolation level read committed"
      RepeatableRead -> "isolation level repeatable read"
      Serializable -> "isolation level serializable"
    mode = \case
      Write -> "read write"
      Read -> "read only"
    defer | deferrable = "deferrable"
          | otherwise = ""

beginTransaction :: TransactionConfig -> Bool -> Statement () ()
beginTransaction conf preparable =
  Statement (beginTransactionSql conf) noParams noResult preparable

commitTransaction :: Bool -> Statement () ()
commitTransaction preparable =
  Statement "commit" noParams noResult preparable

rollbackTransaction :: Bool -> Statement () ()
rollbackTransaction preparable =
  Statement "rollback" noParams noResult preparable