module Database.Ferry.Common.Data.Plans where
import Database.Ferry.Algebra(Columns, AlgNode)
import qualified Data.Map as M
import Text.PrettyPrint.HughesPJ
import Database.Ferry.Algebra(AlgPlan, Column(..))
import Database.Ferry.Algebra.Render.XML
newtype SubPlan = SubPlan (M.Map Int AlgRes)
instance Show SubPlan where
show (SubPlan p) = "SubPlans " ++ (show $ map (\(_,y,z) -> show (y, z)) $ M.elems p)
emptyPlan :: SubPlan
emptyPlan = SubPlan M.empty
subPlan :: Int -> AlgRes -> SubPlan
subPlan i p = SubPlan $ M.singleton i p
getPlan :: Int -> SubPlan -> AlgRes
getPlan i (SubPlan p) = p M.! i
type AlgRes = (AlgNode, Columns, SubPlan)
transform :: (Bool, Bool, AlgPlan AlgRes) -> Doc
transform (isList, debug, p) = let plans = runXML False M.empty M.empty $ planBuilder debug (mkProperty isList) p
planBundle = mkPlanBundle plans
in (document $ mkXMLDocument planBundle)
planBuilder :: Bool -> Element () -> AlgPlan AlgRes -> XML ()
planBuilder debug prop (nodes, (top, cols, subs), tags) = buildPlan Nothing (Just prop) (top, cols, subs)
where
buildPlan :: Maybe (Int, Int) -> Maybe (Element ()) -> AlgRes -> XML ()
buildPlan parent props (top', cols', subs') =
do
let colProp = cssToProp cols'
let planProp = case props of
Nothing -> [colProp] `childsOf` xmlElem "properties"
Just p -> [colProp, p] `childsOf` xmlElem "properties"
let plan = runXML debug nodeTable tags $ serializeAlgebra ((:) iterCol $ (:) posCol $ fst $ colsToNodes 1 cols') top'
pId <- mkQueryPlan parent planProp plan
buildSubPlans pId subs'
buildSubPlans :: Int -> SubPlan -> XML ()
buildSubPlans parent (SubPlan m) = let subPlans = M.toList m
in mapM_ (\(cId, res) -> buildPlan (Just (parent, cId)) Nothing res) subPlans
nodeTable = M.fromList $ map (\(a, b) -> (b, a)) $ M.toList nodes
mkProperty :: Bool -> Element ()
mkProperty isList = [attr "name" "overallResultType", attr "value" result] `attrsOf` xmlElem "property"
where
result = case isList of
True -> "LIST"
False -> "TUPLE"
cssToProp :: Columns -> Element ()
cssToProp cols = map csToProp cols `childsOf` [attr "name" "cs"] `attrsOf` xmlElem "property"
csToProp :: Column -> Element ()
csToProp (Col i ty) = [[attr "name" "type", attr "value" $ show ty] `attrsOf` xmlElem "property"] `childsOf` [attr "name" "offset", attr "value" $ show i] `attrsOf` xmlElem "property"
csToProp (NCol x css) = [cssToProp css] `childsOf` [attr "name" "mapping", attr "value" x] `attrsOf` xmlElem "property"
colsToNodes :: Int -> Columns -> ([Element ()], Int)
colsToNodes i ((Col n _):cs) = let col = [attr "name" $ "item" ++ (show n), attr "new" "false", attr "function" "item", attr "position" $ show i] `attrsOf` xmlElem "column"
(els, i') = colsToNodes (i+1) cs
in (col:els, i')
colsToNodes i ((NCol _ cs):cs') = let (els, i') = colsToNodes i cs
(els', i'') = colsToNodes i' cs'
in (els ++ els', i'')
colsToNodes i [] = ([], i)