{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Database.Relational.Monad.Class
       ( 
         MonadQualify (..), MonadRestrict (..),
         MonadQuery (..), MonadAggregate (..), MonadPartition (..),
         all', distinct,
         on, wheres, having,
       ) where
import Database.Relational.Internal.ContextType (Flat, Aggregated)
import Database.Relational.SqlSyntax
  (Duplication (..), Predicate, Record, AggregateKey)
import Database.Relational.Projectable (PlaceHolders)
import Database.Relational.Monad.BaseType (ConfigureQuery, Relation)
class (Functor m, Monad m) => MonadRestrict c m where
  
  restrict :: Predicate c 
           -> m ()        
class (Functor m, Monad m, MonadQualify ConfigureQuery m) => MonadQuery m where
  
  setDuplication :: Duplication -> m ()
  
  restrictJoin :: Predicate Flat 
               -> m ()           
  
  
  query' :: Relation p r
         -> m (PlaceHolders p, Record Flat r)
  
  queryMaybe' :: Relation p r
              -> m (PlaceHolders p, Record Flat (Maybe r))
class (Functor q, Monad q, Functor m, Monad m) => MonadQualify q m where
  
  
  liftQualify :: q a -> m a
instance (Functor q, Monad q) => MonadQualify q q where
  liftQualify = id
class MonadQuery m => MonadAggregate m where
  
  groupBy :: Record Flat r           
          -> m (Record Aggregated r) 
  
  groupBy' :: AggregateKey (Record Aggregated r)  
           -> m (Record Aggregated r)             
class Monad m => MonadPartition c m where
  
  partitionBy :: Record c r -> m ()
all' :: MonadQuery m => m ()
all' =  setDuplication All
distinct :: MonadQuery m => m ()
distinct =  setDuplication Distinct
on :: MonadQuery m => Predicate Flat -> m ()
on =  restrictJoin
wheres :: MonadRestrict Flat m => Predicate Flat -> m ()
wheres =  restrict
having :: MonadRestrict Aggregated m => Predicate Aggregated -> m ()
having =  restrict