content: {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  
  -- |
  -- Module      : Database.Relational.Monad.Trans.Qualify
  -- Copyright   : 2013-2019 Kei Hibino
  -- License     : BSD3
  --
  -- Maintainer  : ex8k.hibino@gmail.com
  -- Stability   : experimental
  -- Portability : unknown
  --
  -- This module defines monad transformer which qualify uniquely SQL table forms.
  --
  -- This is not public interface.
  module Database.Relational.Monad.Trans.Qualify (
    -- * Qualify monad
    Qualify, qualify,
    evalQualifyPrime, qualifyQuery
    ) where
  
  import Control.Monad.Trans.Class (lift)
  import Control.Monad.Trans.State (StateT, runStateT, get, modify)
  import Control.Applicative (Applicative)
  import Control.Monad (liftM, ap)
  
  import qualified Database.Relational.SqlSyntax as Syntax
  
  
  -- | Monad type to qualify SQL table forms.
  newtype Qualify m a =
    Qualify (StateT Int m a)
    deriving (Monad, Functor, Applicative)
  
  -- | Run qualify monad with initial state to get only result.
  evalQualifyPrime :: Monad m => Qualify m a -> m a
  evalQualifyPrime (Qualify s) = fst `liftM` runStateT s 0 {- primary alias id -}
  
  -- | Generated new qualifier on internal state.
  newAlias :: Monad m => Qualify m Syntax.Qualifier
  newAlias =  Qualify $ do
    ai <- Syntax.Qualifier `liftM` get
    modify (+ 1)
    return ai
  
  -- | Lift to 'Qualify'
  qualify :: Monad m => m a -> Qualify m a
  qualify =  Qualify . lift
  
  -- | Get qualifyed table form query.
  qualifyQuery :: Monad m
               => query                              -- ^ Query to qualify
               -> Qualify m (Syntax.Qualified query) -- ^ Result with updated state
  qualifyQuery query =
    Syntax.qualify `liftM` newAlias `ap` return query
  