-- |
-- Module      : Database.Relational.Monad.Trans.JoinState
-- Copyright   : 2013-2017 Kei Hibino
-- License     : BSD3
--
-- Maintainer  : ex8k.hibino@gmail.com
-- Stability   : experimental
-- Portability : unknown
--
-- This module provides state definition for
-- "Database.Relational.Monad.Trans.Join".
--
-- This is not public interface.
module Database.Relational.Monad.Trans.JoinState (
  -- * Join context
  JoinContext, primeJoinContext, updateProduct, joinProduct
  ) where

import Prelude hiding (product)
import Data.DList (DList, toList)

import Database.Relational.Internal.ContextType (Flat)
import Database.Relational.SqlSyntax (JoinProduct, Node, Predicate)
import qualified Database.Relational.SqlSyntax as Product


-- | JoinContext type for QueryJoin.
newtype JoinContext =
  JoinContext
  { JoinContext -> Maybe (Node (DList (Predicate Flat)))
product  :: Maybe (Node (DList (Predicate Flat)))
  }

-- | Initial 'JoinContext'.
primeJoinContext :: JoinContext
primeJoinContext :: JoinContext
primeJoinContext =  Maybe (Node (DList (Predicate Flat))) -> JoinContext
JoinContext Maybe (Node (DList (Predicate Flat)))
forall a. Maybe a
Nothing

-- | Update product of 'JoinContext'.
updateProduct :: (Maybe (Node (DList (Predicate Flat))) -> Node (DList (Predicate Flat)))
              -> JoinContext
              -> JoinContext
updateProduct :: (Maybe (Node (DList (Predicate Flat)))
 -> Node (DList (Predicate Flat)))
-> JoinContext -> JoinContext
updateProduct Maybe (Node (DList (Predicate Flat)))
-> Node (DList (Predicate Flat))
uf JoinContext
ctx = JoinContext
ctx { product :: Maybe (Node (DList (Predicate Flat)))
product = Node (DList (Predicate Flat))
-> Maybe (Node (DList (Predicate Flat)))
forall a. a -> Maybe a
Just (Node (DList (Predicate Flat))
 -> Maybe (Node (DList (Predicate Flat))))
-> (JoinContext -> Node (DList (Predicate Flat)))
-> JoinContext
-> Maybe (Node (DList (Predicate Flat)))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (Node (DList (Predicate Flat)))
-> Node (DList (Predicate Flat))
uf (Maybe (Node (DList (Predicate Flat)))
 -> Node (DList (Predicate Flat)))
-> (JoinContext -> Maybe (Node (DList (Predicate Flat))))
-> JoinContext
-> Node (DList (Predicate Flat))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JoinContext -> Maybe (Node (DList (Predicate Flat)))
product (JoinContext -> Maybe (Node (DList (Predicate Flat))))
-> JoinContext -> Maybe (Node (DList (Predicate Flat)))
forall a b. (a -> b) -> a -> b
$ JoinContext
ctx }

-- |  Finalize context to extract accumulated query product.
joinProduct :: JoinContext -> JoinProduct
joinProduct :: JoinContext -> JoinProduct
joinProduct =  (Node (DList (Predicate Flat)) -> ProductTree [Predicate Flat])
-> Maybe (Node (DList (Predicate Flat))) -> JoinProduct
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((DList (Predicate Flat) -> [Predicate Flat])
-> ProductTree (DList (Predicate Flat))
-> ProductTree [Predicate Flat]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap DList (Predicate Flat) -> [Predicate Flat]
forall a. DList a -> [a]
toList (ProductTree (DList (Predicate Flat))
 -> ProductTree [Predicate Flat])
-> (Node (DList (Predicate Flat))
    -> ProductTree (DList (Predicate Flat)))
-> Node (DList (Predicate Flat))
-> ProductTree [Predicate Flat]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node (DList (Predicate Flat))
-> ProductTree (DList (Predicate Flat))
forall rs. Node rs -> ProductTree rs
Product.nodeTree) (Maybe (Node (DList (Predicate Flat))) -> JoinProduct)
-> (JoinContext -> Maybe (Node (DList (Predicate Flat))))
-> JoinContext
-> JoinProduct
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JoinContext -> Maybe (Node (DList (Predicate Flat)))
product