dsh-sql-0.2.0.0: src/Database/DSH/Backend/Sql/Opt/Properties/BottomUp.hs
{-# LANGUAGE TemplateHaskell #-}
module Database.DSH.Backend.Sql.Opt.Properties.BottomUp where
import qualified Data.Set.Monad as S
import Database.Algebra.Dag
import Database.Algebra.Dag.Common
import Database.Algebra.Table.Lang
import Database.DSH.Common.Impossible
import Database.DSH.Common.Opt
import Database.DSH.Backend.Sql.Opt.Properties.Card1
import Database.DSH.Backend.Sql.Opt.Properties.Cols
import Database.DSH.Backend.Sql.Opt.Properties.Const
import Database.DSH.Backend.Sql.Opt.Properties.Empty
import Database.DSH.Backend.Sql.Opt.Properties.FD
import Database.DSH.Backend.Sql.Opt.Properties.Keys
import Database.DSH.Backend.Sql.Opt.Properties.Nullable
import Database.DSH.Backend.Sql.Opt.Properties.Order
import Database.DSH.Backend.Sql.Opt.Properties.Types
-- FIXME this is (almost) identical to its X100 counterpart -> merge
inferWorker :: NodeMap TableAlgebra -> TableAlgebra -> AlgNode -> NodeMap BottomUpProps -> BottomUpProps
inferWorker _ op n pm =
let res =
case op of
TerOp _ _ _ _ -> $impossible
BinOp vl c1 c2 ->
let c1Props = lookupUnsafe pm "no children properties" c1
c2Props = lookupUnsafe pm "no children properties" c2
in inferBinOp vl c1Props c2Props
UnOp vl c ->
let cProps = lookupUnsafe pm "no children properties" c
in inferUnOp vl cProps
NullaryOp vl -> inferNullOp vl
in case res of
Left msg -> error $ "Inference failed at node " ++ (show n) ++ ": " ++ msg
Right props -> props
inferNullOp :: NullOp -> Either String BottomUpProps
inferNullOp op = do
let opCols = inferColsNullOp op
opKeys = inferKeysNullOp op
opEmpty = inferEmptyNullOp op
opCard1 = inferCard1NullOp op
-- We only care for rownum-generated columns. Therefore, For
-- nullary operators order is empty.
opOrder = []
opConst = inferConstNullOp op
opNullable = inferNullableNullOp op
opFDs = inferFDNullOp opCols opKeys op
return $ BUProps { pCols = opCols
, pKeys = opKeys
, pEmpty = opEmpty
, pCard1 = opCard1
, pOrder = opOrder
, pConst = opConst
, pNullable = opNullable
, pFunDeps = opFDs
}
inferUnOp :: UnOp -> BottomUpProps -> Either String BottomUpProps
inferUnOp op cProps = do
let opCols = inferColsUnOp (pCols cProps) op
opKeys = inferKeysUnOp (pKeys cProps) (pCard1 cProps) (S.map fst $ pCols cProps) op
opEmpty = inferEmptyUnOp (pEmpty cProps) op
opCard1 = inferCard1UnOp (pCard1 cProps) (pEmpty cProps) op
opOrder = inferOrderUnOp (pOrder cProps) op
opConst = inferConstUnOp (pConst cProps) op
opNullable = inferNullableUnOp (pNullable cProps) op
opFDs = inferFDUnOp cProps op
return $ BUProps { pCols = opCols
, pKeys = opKeys
, pEmpty = opEmpty
, pCard1 = opCard1
, pOrder = opOrder
, pConst = opConst
, pNullable = opNullable
, pFunDeps = opFDs
}
inferBinOp :: BinOp -> BottomUpProps -> BottomUpProps -> Either String BottomUpProps
inferBinOp op c1Props c2Props = do
let opCols = inferColsBinOp (pCols c1Props) (pCols c2Props) op
opKeys = inferKeysBinOp (pKeys c1Props) (pKeys c2Props) (pCard1 c1Props) (pCard1 c2Props) op
opEmpty = inferEmptyBinOp (pEmpty c1Props) (pEmpty c2Props) op
opCard1 = inferCard1BinOp (pCard1 c1Props) (pCard1 c2Props) op
opOrder = inferOrderBinOp (pOrder c1Props) (pOrder c2Props) op
opConst = inferConstBinOp (pConst c1Props) (pConst c2Props) op
opNullable = inferNullableBinOp c1Props c2Props op
opFDs = inferFDBinOp c1Props c2Props opKeys opCols op
return $ BUProps { pCols = opCols
, pKeys = opKeys
, pEmpty = opEmpty
, pCard1 = opCard1
, pOrder = opOrder
, pConst = opConst
, pNullable = opNullable
, pFunDeps = opFDs
}
inferBottomUpProperties :: AlgebraDag TableAlgebra -> NodeMap BottomUpProps
inferBottomUpProperties dag = inferBottomUpGeneral inferWorker dag