@@ -1,3 +1,6 @@
1+{-# LANGUAGE TypeSynonymInstances #-}
2+{-# LANGUAGE FlexibleInstances #-}
3+{-# LANGUAGE FlexibleContexts #-}
1module ProjectM36.StaticOptimizer where
4module ProjectM36.StaticOptimizer where
2import ProjectM36.Base
5import ProjectM36.Base
3import ProjectM36.GraphRefRelationalExpr
6import ProjectM36.GraphRefRelationalExpr
@@ -18,12 +21,26 @@ import Data.Functor.Identity
18import qualified Data.Map as M
21import qualified Data.Map as M
19import qualified Data.Set as S
22import qualified Data.Set as S
21−type StaticOptimizerEnv = RelationalExprEnv
23−type StaticOptimizerMonad a = ReaderT StaticOptimizerEnv (ExceptT RelationalError Identity) a
24-- the static optimizer performs optimizations which need not take any specific-relation statistics into account
24-- the static optimizer performs optimizations which need not take any specific-relation statistics into account
26−type GraphRefStaticOptimizerMonad a = ReaderT (Maybe DatabaseContext, TransactionGraph) (ExceptT RelationalError Identity) a
26+data GraphRefSOptRelationalExprEnv =
27+ GraphRefSOptRelationalExprEnv
29+ ore_graph :: TransactionGraph,
30+ ore_mcontext :: Maybe DatabaseContext
33+type GraphRefSOptRelationalExprM a = ReaderT GraphRefSOptRelationalExprEnv (ExceptT RelationalError Identity) a
35+data GraphRefSOptDatabaseContextExprEnv =
36+ GraphRefSOptDatabaseContextExprEnv
38+ odce_graph :: TransactionGraph,
39+ odce_context :: DatabaseContext, --not optional for DatabaseContextExpr evaluation
40+ odce_transId :: TransactionId -- parent if context is committed- needed because MultipleExpr optimization requires running the DatabaseContextExprs (with empty relvars)
43+type GraphRefSOptDatabaseContextExprM a = ReaderT GraphRefSOptDatabaseContextExprEnv (ExceptT RelationalError Identity) a
28-- | A temporary function to be replaced by IO-based implementation.
45-- | A temporary function to be replaced by IO-based implementation.
29optimizeAndEvalRelationalExpr :: RelationalExprEnv -> RelationalExpr -> Either RelationalError Relation
46optimizeAndEvalRelationalExpr :: RelationalExprEnv -> RelationalExpr -> Either RelationalError Relation
@@ -32,28 +49,44 @@ optimizeAndEvalRelationalExpr env expr = do
32 graph = re_graph env
49 graph = re_graph env
33 ctx = re_context env
50 ctx = re_context env
34 gfEnv = freshGraphRefRelationalExprEnv (Just ctx) graph
51 gfEnv = freshGraphRefRelationalExprEnv (Just ctx) graph
35− optExpr <- runGraphRefStaticOptimizerMonad (Just ctx) (re_graph env) (fullOptimizeGraphRefRelationalExpr gfExpr)
52+ optExpr <- runGraphRefSOptRelationalExprM (Just ctx) (re_graph env) (fullOptimizeGraphRefRelationalExpr gfExpr)
36 runGraphRefRelationalExprM gfEnv (evalGraphRefRelationalExpr optExpr)
53 runGraphRefRelationalExprM gfEnv (evalGraphRefRelationalExpr optExpr)
55+class Monad m => AskGraphContext m where
38−askGraph :: GraphRefStaticOptimizerMonad TransactionGraph
56+ askGraph :: m TransactionGraph
57+ askContext :: m DatabaseContext
59+instance AskGraphContext (ReaderT GraphRefSOptDatabaseContextExprEnv (ExceptT RelationalError Identity)) where
39−askGraph = snd <$> ask
60+ askGraph = odce_graph <$> ask
61+ askContext = odce_context <$> ask
41−askContext :: GraphRefStaticOptimizerMonad DatabaseContext
63+instance AskGraphContext (ReaderT GraphRefSOptRelationalExprEnv (ExceptT RelationalError Identity)) where
64+ askGraph = ore_graph <$> ask
42−askContext = do
65+ askContext = do
43− mctx <- fst <$> ask
66+ mctx <- ore_mcontext <$> ask
44− case mctx of
67+ case mctx of
45− Nothing -> throwError NoUncommittedContextInEvalError
68+ Nothing -> throwError NoUncommittedContextInEvalError
46− Just ctx -> pure ctx
69+ Just ctx -> pure ctx
48−askMaybeContext :: GraphRefStaticOptimizerMonad (Maybe DatabaseContext)
71+askTransId :: GraphRefSOptDatabaseContextExprM TransactionId
49−askMaybeContext = fst <$> ask
72+askTransId = odce_transId <$> ask
74+askMaybeContext :: GraphRefSOptRelationalExprM (Maybe DatabaseContext)
75+askMaybeContext = ore_mcontext <$> ask
77+optimizeDatabaseContextExpr :: DatabaseContextExpr -> GraphRefSOptDatabaseContextExprM GraphRefDatabaseContextExpr
78+optimizeDatabaseContextExpr expr = do
79+ let gfExpr = runProcessExprM UncommittedContextMarker (processDatabaseContextExpr expr)
80+ optimizeGraphRefDatabaseContextExpr gfExpr
51optimizeAndEvalDatabaseContextExpr :: Bool -> DatabaseContextExpr -> DatabaseContextEvalMonad ()
82optimizeAndEvalDatabaseContextExpr :: Bool -> DatabaseContextExpr -> DatabaseContextEvalMonad ()
52optimizeAndEvalDatabaseContextExpr optimize expr = do
83optimizeAndEvalDatabaseContextExpr optimize expr = do
53 graph <- dce_graph <$> ask
84 graph <- dce_graph <$> ask
85+ transId <- dce_transId <$> ask
86+ context <- getStateContext
54 let gfExpr = runProcessExprM UncommittedContextMarker (processDatabaseContextExpr expr)
87 let gfExpr = runProcessExprM UncommittedContextMarker (processDatabaseContextExpr expr)
55 eOptExpr = if optimize then
88 eOptExpr = if optimize then
56− runGraphRefStaticOptimizerMonad Nothing graph (optimizeGraphRefDatabaseContextExpr gfExpr)
89+ runGraphRefSOptDatabaseContextExprM transId context graph (optimizeGraphRefDatabaseContextExpr gfExpr)
58 pure gfExpr
91 pure gfExpr
59 case eOptExpr of
92 case eOptExpr of
@@ -64,31 +97,76 @@ optimizeAndEvalDatabaseContextExpr optimize expr = do
64optimizeAndEvalTransGraphRelationalExpr :: TransactionGraph -> TransGraphRelationalExpr -> Either RelationalError Relation
97optimizeAndEvalTransGraphRelationalExpr :: TransactionGraph -> TransGraphRelationalExpr -> Either RelationalError Relation
65optimizeAndEvalTransGraphRelationalExpr graph tgExpr = do
98optimizeAndEvalTransGraphRelationalExpr graph tgExpr = do
66 gfExpr <- TGRE.process (TransGraphEvalEnv graph) tgExpr
99 gfExpr <- TGRE.process (TransGraphEvalEnv graph) tgExpr
67− optExpr <- runGraphRefStaticOptimizerMonad Nothing graph (fullOptimizeGraphRefRelationalExpr gfExpr)
100+ optExpr <- runGraphRefSOptRelationalExprM Nothing graph (fullOptimizeGraphRefRelationalExpr gfExpr)
68 let gfEnv = freshGraphRefRelationalExprEnv Nothing graph
101 let gfEnv = freshGraphRefRelationalExprEnv Nothing graph
69 runGraphRefRelationalExprM gfEnv (evalGraphRefRelationalExpr optExpr)
102 runGraphRefRelationalExprM gfEnv (evalGraphRefRelationalExpr optExpr)
71optimizeAndEvalDatabaseContextIOExpr :: DatabaseContextIOExpr -> DatabaseContextIOEvalMonad (Either RelationalError ())
104optimizeAndEvalDatabaseContextIOExpr :: DatabaseContextIOExpr -> DatabaseContextIOEvalMonad (Either RelationalError ())
72optimizeAndEvalDatabaseContextIOExpr expr = do
105optimizeAndEvalDatabaseContextIOExpr expr = do
73− env <- getDBCIORelationalExprEnv
106+ transId <- dbcio_transId <$> ask
107+ ctx <- getDBCIOContext
108+ graph <- dbcio_graph <$> ask
74 let gfExpr = runProcessExprM UncommittedContextMarker (processDatabaseContextIOExpr expr)
109 let gfExpr = runProcessExprM UncommittedContextMarker (processDatabaseContextIOExpr expr)
75− eOptExpr = runStaticOptimizerMonad env (optimizeDatabaseContextIOExpr gfExpr)
110+ eOptExpr = runGraphRefSOptDatabaseContextExprM transId ctx graph (optimizeDatabaseContextIOExpr gfExpr)
76 case eOptExpr of
111 case eOptExpr of
77 Left err -> pure (Left err)
112 Left err -> pure (Left err)
78 Right optExpr ->
113 Right optExpr ->
79 evalGraphRefDatabaseContextIOExpr optExpr
114 evalGraphRefDatabaseContextIOExpr optExpr
82runStaticOptimizerMonad :: RelationalExprEnv -> StaticOptimizerMonad a -> Either RelationalError a
117runStaticOptimizerMonad :: RelationalExprEnv -> StaticOptimizerMonad a -> Either RelationalError a
83runStaticOptimizerMonad env m = runIdentity (runExceptT (runReaderT m env))
118runStaticOptimizerMonad env m = runIdentity (runExceptT (runReaderT m env))
121+runGraphRefSOptRelationalExprM ::
122+ Maybe DatabaseContext ->
124+ GraphRefSOptRelationalExprM a ->
125+ Either RelationalError a
126+runGraphRefSOptRelationalExprM mctx graph m = runIdentity (runExceptT (runReaderT m env))
128+ env = GraphRefSOptRelationalExprEnv {
85−runGraphRefStaticOptimizerMonad :: Maybe DatabaseContext -> TransactionGraph -> GraphRefStaticOptimizerMonad a -> Either RelationalError a
134+runGraphRefSOptDatabaseContextExprM ::
138+ GraphRefSOptDatabaseContextExprM a ->
139+ Either RelationalError a
140+runGraphRefSOptDatabaseContextExprM tid ctx graph m =
86−runGraphRefStaticOptimizerMonad ctx graph m = runIdentity (runExceptT (runReaderT m (ctx, graph)))
141+ runIdentity (runExceptT (runReaderT m env))
143+ env = GraphRefSOptDatabaseContextExprEnv {
149+optimizeGraphRefRelationalExpr' ::
150+ Maybe DatabaseContext ->
152+ GraphRefRelationalExpr ->
88−optimizeGraphRefRelationalExpr' :: Maybe DatabaseContext -> TransactionGraph -> GraphRefRelationalExpr -> Either RelationalError GraphRefRelationalExpr
153+ Either RelationalError GraphRefRelationalExpr
154+optimizeGraphRefRelationalExpr' mctx graph expr =
89−optimizeGraphRefRelationalExpr' mctx graph expr = runIdentity (runExceptT (runReaderT (optimizeGraphRefRelationalExpr expr) (mctx,graph)))
155+ runIdentity (runExceptT (runReaderT (optimizeGraphRefRelationalExpr expr) env))
157+ env = GraphRefSOptRelationalExprEnv {
162+-- | optimize relational expression within database context expr monad
163+liftGraphRefRelExpr :: GraphRefSOptRelationalExprM a -> GraphRefSOptDatabaseContextExprM a
164+liftGraphRefRelExpr m = do
165+ context <- odce_context <$> ask
166+ graph <- odce_graph <$> ask
167+ lift $ except $ runGraphRefSOptRelationalExprM (Just context) graph m
91−fullOptimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefStaticOptimizerMonad GraphRefRelationalExpr
169+fullOptimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefSOptRelationalExprM GraphRefRelationalExpr
92fullOptimizeGraphRefRelationalExpr expr = do
170fullOptimizeGraphRefRelationalExpr expr = do
93 optExpr <- optimizeGraphRefRelationalExpr expr
171 optExpr <- optimizeGraphRefRelationalExpr expr
94 let optExpr' = applyStaticRestrictionPushdown (applyStaticRestrictionCollapse optExpr)
172 let optExpr' = applyStaticRestrictionPushdown (applyStaticRestrictionCollapse optExpr)
@@ -97,7 +175,7 @@ fullOptimizeGraphRefRelationalExpr expr = do
97-- apply optimizations which merely remove steps to become no-ops: example: projection of a relation across all of its attributes => original relation
175-- apply optimizations which merely remove steps to become no-ops: example: projection of a relation across all of its attributes => original relation
99--should optimizations offer the possibility to pure errors? If they perform the up-front type-checking, maybe so
177--should optimizations offer the possibility to pure errors? If they perform the up-front type-checking, maybe so
100−optimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefStaticOptimizerMonad GraphRefRelationalExpr
178+optimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefSOptRelationalExprM GraphRefRelationalExpr
101optimizeGraphRefRelationalExpr e@(MakeStaticRelation _ _) = pure e
179optimizeGraphRefRelationalExpr e@(MakeStaticRelation _ _) = pure e
103optimizeGraphRefRelationalExpr e@(MakeRelationFromExprs _ _) = pure e
181optimizeGraphRefRelationalExpr e@(MakeRelationFromExprs _ _) = pure e
@@ -109,8 +187,9 @@ optimizeGraphRefRelationalExpr e@(RelationVariable _ _) = pure e
109--remove project of attributes which removes no attributes
187--remove project of attributes which removes no attributes
110optimizeGraphRefRelationalExpr (Project attrNameSet expr) = do
188optimizeGraphRefRelationalExpr (Project attrNameSet expr) = do
111 graph <- askGraph
189 graph <- askGraph
190+ mctx <- askMaybeContext
112 let relType = runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr expr)
191 let relType = runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr expr)
113− gfEnv = freshGraphRefRelationalExprEnv Nothing graph
192+ gfEnv = freshGraphRefRelationalExprEnv mctx graph
114 case relType of
193 case relType of
115 Left err -> throwError err
194 Left err -> throwError err
116 Right relType2
195 Right relType2
@@ -171,12 +250,13 @@ optimizeGraphRefRelationalExpr (Ungroup attrName expr) =
171--remove restriction of nothing
250--remove restriction of nothing
172optimizeGraphRefRelationalExpr (Restrict predicate expr) = do
251optimizeGraphRefRelationalExpr (Restrict predicate expr) = do
173 graph <- askGraph
252 graph <- askGraph
253+ mctx <- askMaybeContext
174 optimizedPredicate <- applyStaticPredicateOptimization predicate
254 optimizedPredicate <- applyStaticPredicateOptimization predicate
175 case optimizedPredicate of
255 case optimizedPredicate of
176 optimizedPredicate' | isTrueExpr optimizedPredicate' -> optimizeGraphRefRelationalExpr expr -- remove predicate entirely
256 optimizedPredicate' | isTrueExpr optimizedPredicate' -> optimizeGraphRefRelationalExpr expr -- remove predicate entirely
177 optimizedPredicate' | isFalseExpr optimizedPredicate' -> do -- replace where false predicate with empty relation with attributes from relexpr
257 optimizedPredicate' | isFalseExpr optimizedPredicate' -> do -- replace where false predicate with empty relation with attributes from relexpr
178 let attributesRel = runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr expr)
258 let attributesRel = runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr expr)
179− gfEnv = freshGraphRefRelationalExprEnv Nothing graph
259+ gfEnv = freshGraphRefRelationalExprEnv mctx graph
180 case attributesRel of
260 case attributesRel of
181 Left err -> throwError err
261 Left err -> throwError err
182 Right attributesRelA -> pure $ MakeStaticRelation (attributes attributesRelA) emptyTupleSet
262 Right attributesRelA -> pure $ MakeStaticRelation (attributes attributesRelA) emptyTupleSet
@@ -193,18 +273,18 @@ optimizeGraphRefRelationalExpr e@(Extend _ _) = pure e
193optimizeGraphRefRelationalExpr e@(With _ _) = pure e
273optimizeGraphRefRelationalExpr e@(With _ _) = pure e
195-- database context expr
275-- database context expr
196−optimizeGraphRefDatabaseContextExpr :: GraphRefDatabaseContextExpr -> GraphRefStaticOptimizerMonad GraphRefDatabaseContextExpr
276+optimizeGraphRefDatabaseContextExpr :: GraphRefDatabaseContextExpr -> GraphRefSOptDatabaseContextExprM GraphRefDatabaseContextExpr
197optimizeGraphRefDatabaseContextExpr x@NoOperation = pure x
277optimizeGraphRefDatabaseContextExpr x@NoOperation = pure x
198optimizeGraphRefDatabaseContextExpr x@(Define _ _) = pure x
278optimizeGraphRefDatabaseContextExpr x@(Define _ _) = pure x
200optimizeGraphRefDatabaseContextExpr x@(Undefine _) = pure x
280optimizeGraphRefDatabaseContextExpr x@(Undefine _) = pure x
202optimizeGraphRefDatabaseContextExpr (Assign name expr) = do
282optimizeGraphRefDatabaseContextExpr (Assign name expr) = do
203− optExpr <- optimizeGraphRefRelationalExpr expr
283+ optExpr <- liftGraphRefRelExpr (fullOptimizeGraphRefRelationalExpr expr)
204 pure $ Assign name optExpr
284 pure $ Assign name optExpr
206optimizeGraphRefDatabaseContextExpr (Insert targetName expr) = do
286optimizeGraphRefDatabaseContextExpr (Insert targetName expr) = do
207− optimizedExpr <- fullOptimizeGraphRefRelationalExpr expr
287+ optimizedExpr <- liftGraphRefRelExpr (fullOptimizeGraphRefRelationalExpr expr)
208 if isEmptyRelationExpr optimizedExpr then -- if we are trying to insert an empty relation, do nothing
288 if isEmptyRelationExpr optimizedExpr then -- if we are trying to insert an empty relation, do nothing
209 pure NoOperation
289 pure NoOperation
@@ -215,10 +295,10 @@ optimizeGraphRefDatabaseContextExpr (Insert targetName expr) = do
215 _ -> pure (Insert targetName optimizedExpr)
295 _ -> pure (Insert targetName optimizedExpr)
217optimizeGraphRefDatabaseContextExpr (Delete name predicate) =
297optimizeGraphRefDatabaseContextExpr (Delete name predicate) =
218− Delete name <$> applyStaticPredicateOptimization predicate
298+ Delete name <$> liftGraphRefRelExpr (applyStaticPredicateOptimization predicate)
220optimizeGraphRefDatabaseContextExpr (Update name upmap predicate) =
300optimizeGraphRefDatabaseContextExpr (Update name upmap predicate) =
221− Update name upmap <$> applyStaticPredicateOptimization predicate
301+ Update name upmap <$> liftGraphRefRelExpr (applyStaticPredicateOptimization predicate)
223optimizeGraphRefDatabaseContextExpr dep@(AddInclusionDependency _ _) = pure dep
303optimizeGraphRefDatabaseContextExpr dep@(AddInclusionDependency _ _) = pure dep
@@ -240,14 +320,28 @@ optimizeGraphRefDatabaseContextExpr c@(ExecuteDatabaseContextFunction _ _) = pur
241--applyStaticDatabaseOptimization (MultipleExpr exprs) = pure $ Right $ MultipleExpr exprs
321--applyStaticDatabaseOptimization (MultipleExpr exprs) = pure $ Right $ MultipleExpr exprs
242--for multiple expressions, we must evaluate
322--for multiple expressions, we must evaluate
243−optimizeGraphRefDatabaseContextExpr x@(MultipleExpr _) = pure x
323+optimizeGraphRefDatabaseContextExpr (MultipleExpr exprs) = do
244 --a previous expression in the exprs list could create a relvar; we don't want to miss it, so we clear the tuples and execute the expression to get an empty relation in the relvar
324 --a previous expression in the exprs list could create a relvar; we don't want to miss it, so we clear the tuples and execute the expression to get an empty relation in the relvar
245−-- unimplemented
325+ context <- askContext
327+ parentId <- askTransId
246−{- let processEmptyRelVars env = env { relationVariables = mkEmptyRelVars (relationVariables env) }
329+ let emptyRvs ctx = ctx { relationVariables = mkEmptyRelVars (relationVariables ctx) }
247− MultipleExpr <$> local processEmptyRelVars (mapM applyStaticDatabaseOptimization exprs)-}
330+ dbcEnv = mkDatabaseContextEvalEnv parentId graph
331+ folder (ctx, expracc) expr = do
332+ --optimize the expr and run it against empty relvars to add it to the context
333+ case runGraphRefSOptDatabaseContextExprM parentId ctx graph (optimizeGraphRefDatabaseContextExpr expr) of
334+ Left err -> throwError err
336+ case runDatabaseContextEvalMonad ctx dbcEnv (evalGraphRefDatabaseContextExpr optExpr) of
337+ Left err -> throwError err
339+ pure (emptyRvs $ dbc_context dbcState, expracc ++ [optExpr])
341+ (_, exprs') <- foldM folder (context,[]) exprs
342+ pure (MultipleExpr exprs')
250−applyStaticPredicateOptimization :: GraphRefRestrictionPredicateExpr -> GraphRefStaticOptimizerMonad GraphRefRestrictionPredicateExpr
344+applyStaticPredicateOptimization :: GraphRefRestrictionPredicateExpr -> GraphRefSOptRelationalExprM GraphRefRestrictionPredicateExpr
251applyStaticPredicateOptimization predi = do
345applyStaticPredicateOptimization predi = do
252 optPred <- case predi of
346 optPred <- case predi of
253-- where x and x => where x
347-- where x and x => where x
@@ -340,7 +434,7 @@ isStaticAtomExpr FunctionAtomExpr{} = False
340isStaticAtomExpr RelationAtomExpr{} = False
434isStaticAtomExpr RelationAtomExpr{} = False
342--if the projection of a join only uses the attributes from one of the expressions and there is a foreign key relationship between the expressions, we know that the join is inconsequential and can be removed
436--if the projection of a join only uses the attributes from one of the expressions and there is a foreign key relationship between the expressions, we know that the join is inconsequential and can be removed
343−applyStaticJoinElimination :: GraphRefRelationalExpr -> GraphRefStaticOptimizerMonad GraphRefRelationalExpr
437+applyStaticJoinElimination :: GraphRefRelationalExpr -> GraphRefSOptRelationalExprM GraphRefRelationalExpr
344applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
438applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
345 graph <- askGraph
439 graph <- askGraph
346 case inSameTransaction exprA exprB of
440 case inSameTransaction exprA exprB of
@@ -480,5 +574,5 @@ applyStaticRestrictionPushdown expr = case expr of
480 Extend n (applyStaticRestrictionPushdown sub)
574 Extend n (applyStaticRestrictionPushdown sub)
482-- no optimizations available
576-- no optimizations available
483−optimizeDatabaseContextIOExpr :: GraphRefDatabaseContextIOExpr -> StaticOptimizerMonad GraphRefDatabaseContextIOExpr
577+optimizeDatabaseContextIOExpr :: GraphRefDatabaseContextIOExpr -> GraphRefSOptDatabaseContextExprM GraphRefDatabaseContextIOExpr
484optimizeDatabaseContextIOExpr x = pure x
578optimizeDatabaseContextIOExpr x = pure x