-- | API for building Selda backends and adding support for more types
--   in queries.
module Database.Selda.Backend
  ( MonadSelda (..), SeldaT, SeldaM, SeldaError (..)
  , StmtID, BackendID (..), QueryRunner, SeldaBackend (..), SeldaConnection
  , SqlValue (..)
  , IndexMethod (..)
  , Param (..), ColAttr (..), AutoIncType (..)
  , PPConfig (..), defPPConfig
  , TableName, ColName, TableInfo (..), ColumnInfo (..)
  , isAutoPrimary, isPrimary, isUnique
  , tableInfo, fromColInfo
  , mkTableName, mkColName, fromTableName, fromColName, rawTableName
  , newConnection, allStmts, withBackend
  , runSeldaT, seldaClose
  , module SqlType
  ) where
import Control.Monad ( unless )
import Control.Monad.Catch ( mask_ )
import Control.Monad.IO.Class ( MonadIO(..) )
import Data.IORef ( atomicModifyIORef' )
import Database.Selda.Backend.Internal
    ( Param(..),
      ColAttr(..),
      AutoIncType(..),
      isAutoPrimary,
      isPrimary,
      isUnique,
      PPConfig(..),
      defPPConfig,
      SeldaM,
      SeldaT,
      MonadSelda(..),
      SeldaBackend(..),
      ColumnInfo(..),
      TableInfo(..),
      SeldaConnection(connClosed, connBackend),
      QueryRunner,
      StmtID,
      SeldaError(..),
      BackendID(..),
      newConnection,
      allStmts,
      fromColInfo,
      tableInfo,
      withBackend,
      runSeldaT )
import Database.Selda.SqlType as SqlType
    ( UUID,
      UUID'(..),
      ID(..),
      RowID,
      SqlValue(..),
      Lit(..),
      SqlEnum(..),
      SqlType(..),
      SqlTypeRep(..),
      sqlDateTimeFormat,
      sqlDateFormat,
      sqlTimeFormat,
      litType,
      compLit,
      invalidRowId,
      isInvalidRowId,
      toRowId,
      fromRowId,
      typedUuid,
      toId,
      fromId,
      invalidId,
      isInvalidId )
import Database.Selda.Table.Type ( IndexMethod(..) )
import Database.Selda.Types
    ( TableName,
      ColName,
      fromColName,
      fromTableName,
      rawTableName,
      mkColName,
      mkTableName )

-- | Close a reusable Selda connection.
--   Closing a connection while in use is undefined.
--   Passing a closed connection to 'runSeldaT' results in a 'SeldaError'
--   being thrown. Closing a connection more than once is a no-op.
seldaClose :: MonadIO m => SeldaConnection b -> m ()
seldaClose :: forall (m :: * -> *) b. MonadIO m => SeldaConnection b -> m ()
seldaClose SeldaConnection b
c = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadMask m => m a -> m a
mask_ forall a b. (a -> b) -> a -> b
$ do
  Bool
closed <- forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' (forall b. SeldaConnection b -> IORef Bool
connClosed SeldaConnection b
c) forall a b. (a -> b) -> a -> b
$ \Bool
closed -> (Bool
True, Bool
closed)
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
closed forall a b. (a -> b) -> a -> b
$ forall b. SeldaBackend b -> SeldaConnection b -> IO ()
closeConnection (forall b. SeldaConnection b -> SeldaBackend b
connBackend SeldaConnection b
c) SeldaConnection b
c