content: {-# LANGUAGE GADTs #-}
  module OptimizeAlgebra where
  
  -- based on Haskell module generated by the BNF converter
  
  import Algebra
  import Relation
  import AbsRelAlgebra
  import ErrM
  import qualified Data.Map as M
  
  pushSelect :: Env -> Tree a -> Tree a
  pushSelect env t = case t of
    RSelect c (RCartesian r s) -> let (cr,cs,crs) = decomposeCond env r s c
                                  in rSelect crs (RCartesian (rSelect cr r) (rSelect cs s))
    _ -> composOp (pushSelect env) t
  
  decomposeCond :: Env -> Rel -> Rel -> Cond -> ([Cond],[Cond],[Cond])
  decomposeCond env r s c = (cr,cs,crs) where
    cc  = unfoldAnd c
    cr  = [c | c <- cc, all (flip elem (attributesIn env r)) (attributesIn env c)]
    cs  = [c | c <- cc, all (flip elem (attributesIn env s)) (attributesIn env c)]
    crs = [c | c <- cc, notElem c (cr ++ cs)]
  
  unfoldAnd :: Cond -> [Cond]
  unfoldAnd c = case c of
    CAnd a b -> unfoldAnd a ++ unfoldAnd b
    _ -> [c]
  
  rSelect :: [Cond] -> Rel -> Rel
  rSelect cs rel = if null cs then rel else RSelect (foldl1 CAnd cs) rel
  
  attributesIn :: Env -> Tree a -> [Ident]
  attributesIn env t = case t of
    RTable t -> maybe [] (map Ident . tlabels) $ M.lookup (ident2id t) (tables env)
    EIdent i -> [i]
    EQIdent _ i -> [i] ----
    _ -> composOpMPlus (attributesIn env) t
  
  