@@ -3,7 +3,9 @@ import ProjectM36.Base
3import ProjectM36.GraphRefRelationalExpr
3import ProjectM36.GraphRefRelationalExpr
4import ProjectM36.Relation
4import ProjectM36.Relation
5import ProjectM36.RelationalExpression
5import ProjectM36.RelationalExpression
6+import ProjectM36.TransGraphRelationalExpression as TGRE
6import ProjectM36.Error
7import ProjectM36.Error
8+import ProjectM36.Transaction
7import qualified ProjectM36.Attribute as A
9import qualified ProjectM36.Attribute as A
8import qualified ProjectM36.AttributeNames as AS
10import qualified ProjectM36.AttributeNames as AS
9import ProjectM36.TupleSet
11import ProjectM36.TupleSet
@@ -11,8 +13,6 @@ import Control.Monad.State
11import Control.Monad.Trans.Reader
13import Control.Monad.Trans.Reader
12import Control.Monad.Trans.Except
14import Control.Monad.Trans.Except
13import Data.Functor.Identity
15import Data.Functor.Identity
14−import Data.Either (rights, lefts)
15−import Control.Monad.Trans.Reader
16import qualified Data.Map as M
16import qualified Data.Map as M
17import qualified Data.Set as S
17import qualified Data.Set as S
@@ -21,37 +21,52 @@ type StaticOptimizerEnv = RelationalExprEnv
21type StaticOptimizerMonad a = ReaderT StaticOptimizerEnv (ExceptT RelationalError Identity) a
21type StaticOptimizerMonad a = ReaderT StaticOptimizerEnv (ExceptT RelationalError Identity) a
22-- the static optimizer performs optimizations which need not take any specific-relation statistics into account
22-- the static optimizer performs optimizations which need not take any specific-relation statistics into account
24+type GraphRefStaticOptimizerMonad a = ReaderT TransactionGraph (ExceptT RelationalError Identity) a
24-- | A temporary function to be replaced by IO-based implementation.
26-- | A temporary function to be replaced by IO-based implementation.
25optimizeAndEvalRelationalExpr :: RelationalExprEnv -> RelationalExpr -> Either RelationalError Relation
27optimizeAndEvalRelationalExpr :: RelationalExprEnv -> RelationalExpr -> Either RelationalError Relation
26optimizeAndEvalRelationalExpr env expr = do
28optimizeAndEvalRelationalExpr env expr = do
27 let gfExpr = runReader (processRelationalExpr expr) env
29 let gfExpr = runReader (processRelationalExpr expr) env
28− optExpr <- runStaticOptimizerMonad env (fullOptimizeGraphRefRelationalExpr gfExpr)
30+ optExpr <- runGraphRefStaticOptimizerMonad (re_graph env) (fullOptimizeGraphRefRelationalExpr gfExpr)
29 evalGraphRefRelationalExpr optExpr (re_graph env)
31 evalGraphRefRelationalExpr optExpr (re_graph env)
31optimizeAndEvalDatabaseContextExpr :: DatabaseContextExpr -> DatabaseContextEvalMonad ()
33optimizeAndEvalDatabaseContextExpr :: DatabaseContextExpr -> DatabaseContextEvalMonad ()
32optimizeAndEvalDatabaseContextExpr expr = do
34optimizeAndEvalDatabaseContextExpr expr = do
33 env <- dbcRelationalExprEnv
35 env <- dbcRelationalExprEnv
34 let gfExpr = runReader (processDatabaseContextExpr expr) env
36 let gfExpr = runReader (processDatabaseContextExpr expr) env
35− eOptExpr = runStaticOptimizerMonad env (optimizeDatabaseContextExpr gfExpr)
37+ eOptExpr = runGraphRefStaticOptimizerMonad (re_graph env) (optimizeGraphRefDatabaseContextExpr gfExpr)
36 case eOptExpr of
38 case eOptExpr of
37 Left err -> lift (except (Left err))
39 Left err -> lift (except (Left err))
38 Right optExpr -> evalGraphRefDatabaseContextExpr optExpr
40 Right optExpr -> evalGraphRefDatabaseContextExpr optExpr
42+optimizeAndEvalTransGraphRelationalExpr :: TransactionGraph -> TransGraphRelationalExpr -> Either RelationalError Relation
43+optimizeAndEvalTransGraphRelationalExpr graph tgExpr = do
44+ gfExpr <- TGRE.process (TransGraphEvalEnv graph) tgExpr
45+ optExpr <- runGraphRefStaticOptimizerMonad graph (fullOptimizeGraphRefRelationalExpr gfExpr)
46+ evalGraphRefRelationalExpr optExpr graph
40optimizeAndEvalDatabaseContextIOExpr :: DatabaseContextIOExpr -> DatabaseContextIOEvalMonad (Either RelationalError ())
48optimizeAndEvalDatabaseContextIOExpr :: DatabaseContextIOExpr -> DatabaseContextIOEvalMonad (Either RelationalError ())
41optimizeAndEvalDatabaseContextIOExpr expr = do
49optimizeAndEvalDatabaseContextIOExpr expr = do
42 reEnv <- getDBCIORelationalExprEnv
50 reEnv <- getDBCIORelationalExprEnv
43 let gfExpr = runReader (processDatabaseContextIOExpr expr) reEnv
51 let gfExpr = runReader (processDatabaseContextIOExpr expr) reEnv
44− optExpr <- runStaticOptimizerMonad reEnv (optimizeDatbaseContextIOExpr gfExpr)
52+ eOptExpr = runStaticOptimizerMonad reEnv (optimizeDatabaseContextIOExpr gfExpr)
54+ Left err -> pure (Left err)
45− evalGraphRefDatabaseContextIOExpr optExpr
56+ evalGraphRefDatabaseContextIOExpr optExpr
48runStaticOptimizerMonad :: RelationalExprEnv -> StaticOptimizerMonad a -> Either RelationalError a
59runStaticOptimizerMonad :: RelationalExprEnv -> StaticOptimizerMonad a -> Either RelationalError a
49runStaticOptimizerMonad env m = runIdentity (runExceptT (runReaderT m env))
60runStaticOptimizerMonad env m = runIdentity (runExceptT (runReaderT m env))
51−optimizeRelationalExpr' :: RelationalExprEnv -> GraphRefRelationalExpr -> Either RelationalError GraphRefRelationalExpr
62+runGraphRefStaticOptimizerMonad :: TransactionGraph -> GraphRefStaticOptimizerMonad a -> Either RelationalError a
52−optimizeRelationalExpr' reEnv expr = runIdentity (runExceptT (runReaderT (optimizeGraphRefRelationalExpr expr) reEnv))
63+runGraphRefStaticOptimizerMonad graph m = runIdentity (runExceptT (runReaderT m graph))
65+--RelationalExprEnv should not be necessary for graph ref re optimization!
66+optimizeGraphRefRelationalExpr' :: TransactionGraph -> GraphRefRelationalExpr -> Either RelationalError GraphRefRelationalExpr
67+optimizeGraphRefRelationalExpr' graph expr = runIdentity (runExceptT (runReaderT (optimizeGraphRefRelationalExpr expr) graph))
54−fullOptimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> StaticOptimizerMonad GraphRefRelationalExpr
69+fullOptimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefStaticOptimizerMonad GraphRefRelationalExpr
55fullOptimizeGraphRefRelationalExpr expr = do
70fullOptimizeGraphRefRelationalExpr expr = do
56 optExpr <- optimizeGraphRefRelationalExpr expr
71 optExpr <- optimizeGraphRefRelationalExpr expr
57 let optExpr' = applyStaticRestrictionPushdown (applyStaticRestrictionCollapse optExpr)
72 let optExpr' = applyStaticRestrictionPushdown (applyStaticRestrictionCollapse optExpr)
@@ -60,7 +75,7 @@ fullOptimizeGraphRefRelationalExpr expr = do
60-- apply optimizations which merely remove steps to become no-ops: example: projection of a relation across all of its attributes => original relation
75-- apply optimizations which merely remove steps to become no-ops: example: projection of a relation across all of its attributes => original relation
62--should optimizations offer the possibility to pure errors? If they perform the up-front type-checking, maybe so
77--should optimizations offer the possibility to pure errors? If they perform the up-front type-checking, maybe so
63−optimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> StaticOptimizerMonad GraphRefRelationalExpr
78+optimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefStaticOptimizerMonad GraphRefRelationalExpr
64optimizeGraphRefRelationalExpr e@(MakeStaticRelation _ _) = pure e
79optimizeGraphRefRelationalExpr e@(MakeStaticRelation _ _) = pure e
66optimizeGraphRefRelationalExpr e@(MakeRelationFromExprs _ _) = pure e
81optimizeGraphRefRelationalExpr e@(MakeRelationFromExprs _ _) = pure e
@@ -130,12 +145,12 @@ optimizeGraphRefRelationalExpr (Ungroup attrName expr) =
131--remove restriction of nothing
146--remove restriction of nothing
132optimizeGraphRefRelationalExpr (Restrict predicate expr) = do
147optimizeGraphRefRelationalExpr (Restrict predicate expr) = do
133− env <- ask
148+ graph <- ask
134 optimizedPredicate <- applyStaticPredicateOptimization predicate
149 optimizedPredicate <- applyStaticPredicateOptimization predicate
135 case optimizedPredicate of
150 case optimizedPredicate of
136 optimizedPredicate' | isTrueExpr optimizedPredicate' -> optimizeGraphRefRelationalExpr expr -- remove predicate entirely
151 optimizedPredicate' | isTrueExpr optimizedPredicate' -> optimizeGraphRefRelationalExpr expr -- remove predicate entirely
137 optimizedPredicate' | isFalseExpr optimizedPredicate' -> do -- replace where false predicate with empty relation with attributes from relexpr
152 optimizedPredicate' | isFalseExpr optimizedPredicate' -> do -- replace where false predicate with empty relation with attributes from relexpr
138− let attributesRel = runReader (typeForGraphRefRelationalExpr expr) env
153+ let attributesRel = runReader (typeForGraphRefRelationalExpr expr) graph
139 case attributesRel of
154 case attributesRel of
140 Left err -> lift (except (Left err))
155 Left err -> lift (except (Left err))
141 Right attributesRelA -> pure $ MakeStaticRelation (attributes attributesRelA) emptyTupleSet
156 Right attributesRelA -> pure $ MakeStaticRelation (attributes attributesRelA) emptyTupleSet
@@ -152,17 +167,17 @@ optimizeGraphRefRelationalExpr e@(Extend _ _) = pure e
152optimizeGraphRefRelationalExpr e@(With _ _) = pure e
167optimizeGraphRefRelationalExpr e@(With _ _) = pure e
154-- database context expr
169-- database context expr
155−optimizeDatabaseContextExpr :: GraphRefDatabaseContextExpr -> StaticOptimizerMonad GraphRefDatabaseContextExpr
170+optimizeGraphRefDatabaseContextExpr :: GraphRefDatabaseContextExpr -> GraphRefStaticOptimizerMonad GraphRefDatabaseContextExpr
156−optimizeDatabaseContextExpr x@NoOperation = pure x
171+optimizeGraphRefDatabaseContextExpr x@NoOperation = pure x
157−optimizeDatabaseContextExpr x@(Define _ _) = pure x
172+optimizeGraphRefDatabaseContextExpr x@(Define _ _) = pure x
159−optimizeDatabaseContextExpr x@(Undefine _) = pure x
174+optimizeGraphRefDatabaseContextExpr x@(Undefine _) = pure x
161−optimizeDatabaseContextExpr (Assign name expr) = do
176+optimizeGraphRefDatabaseContextExpr (Assign name expr) = do
162 optExpr <- optimizeGraphRefRelationalExpr expr
177 optExpr <- optimizeGraphRefRelationalExpr expr
163 pure $ Assign name optExpr
178 pure $ Assign name optExpr
165−optimizeDatabaseContextExpr (Insert targetName expr) = do
180+optimizeGraphRefDatabaseContextExpr (Insert targetName expr) = do
166 optimizedExpr <- fullOptimizeGraphRefRelationalExpr expr
181 optimizedExpr <- fullOptimizeGraphRefRelationalExpr expr
167 if isEmptyRelationExpr optimizedExpr then -- if we are trying to insert an empty relation, do nothing
182 if isEmptyRelationExpr optimizedExpr then -- if we are trying to insert an empty relation, do nothing
168 pure NoOperation
183 pure NoOperation
@@ -173,39 +188,40 @@ optimizeDatabaseContextExpr (Insert targetName expr) = do
173 RelationVariable insName _ | insName == targetName -> pure NoOperation
188 RelationVariable insName _ | insName == targetName -> pure NoOperation
174 _ -> pure (Insert targetName optimizedExpr)
189 _ -> pure (Insert targetName optimizedExpr)
176−optimizeDatabaseContextExpr (Delete name predicate) =
191+optimizeGraphRefDatabaseContextExpr (Delete name predicate) =
177 Delete name <$> applyStaticPredicateOptimization predicate
192 Delete name <$> applyStaticPredicateOptimization predicate
179−optimizeDatabaseContextExpr (Update name upmap predicate) =
194+optimizeGraphRefDatabaseContextExpr (Update name upmap predicate) =
180 Update name upmap <$> applyStaticPredicateOptimization predicate
195 Update name upmap <$> applyStaticPredicateOptimization predicate
182−optimizeDatabaseContextExpr dep@(AddInclusionDependency _ _) = pure dep
197+optimizeGraphRefDatabaseContextExpr dep@(AddInclusionDependency _ _) = pure dep
184−optimizeDatabaseContextExpr (RemoveInclusionDependency name) = pure (RemoveInclusionDependency name)
199+optimizeGraphRefDatabaseContextExpr (RemoveInclusionDependency name) = pure (RemoveInclusionDependency name)
186−optimizeDatabaseContextExpr (AddNotification name triggerExpr resultOldExpr resultNewExpr) =
201+optimizeGraphRefDatabaseContextExpr (AddNotification name triggerExpr resultOldExpr resultNewExpr) =
187 --we can't optimize these expressions until they run
202 --we can't optimize these expressions until they run
188 pure (AddNotification name triggerExpr resultOldExpr resultNewExpr)
203 pure (AddNotification name triggerExpr resultOldExpr resultNewExpr)
190−optimizeDatabaseContextExpr notif@(RemoveNotification _) = pure notif
205+optimizeGraphRefDatabaseContextExpr notif@(RemoveNotification _) = pure notif
192−optimizeDatabaseContextExpr c@(AddTypeConstructor _ _) = pure c
207+optimizeGraphRefDatabaseContextExpr c@(AddTypeConstructor _ _) = pure c
193−optimizeDatabaseContextExpr c@(RemoveTypeConstructor _) = pure c
208+optimizeGraphRefDatabaseContextExpr c@(RemoveTypeConstructor _) = pure c
194−optimizeDatabaseContextExpr c@(RemoveAtomFunction _) = pure c
209+optimizeGraphRefDatabaseContextExpr c@(RemoveAtomFunction _) = pure c
195−optimizeDatabaseContextExpr c@(RemoveDatabaseContextFunction _) = pure c
210+optimizeGraphRefDatabaseContextExpr c@(RemoveDatabaseContextFunction _) = pure c
196−optimizeDatabaseContextExpr c@(ExecuteDatabaseContextFunction _ _) = pure c
211+optimizeGraphRefDatabaseContextExpr c@(ExecuteDatabaseContextFunction _ _) = pure c
198--optimization: from pgsql lists- check for join condition referencing foreign key- if join projection project away the referenced table, then it does not need to be scanned
213--optimization: from pgsql lists- check for join condition referencing foreign key- if join projection project away the referenced table, then it does not need to be scanned
200--applyStaticDatabaseOptimization (MultipleExpr exprs) = pure $ Right $ MultipleExpr exprs
215--applyStaticDatabaseOptimization (MultipleExpr exprs) = pure $ Right $ MultipleExpr exprs
201--for multiple expressions, we must evaluate
216--for multiple expressions, we must evaluate
202−applyStaticDatabaseOptimization (MultipleExpr exprs) = do
217+optimizeGraphRefDatabaseContextExpr (MultipleExpr _) = do
203 --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
218 --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
204− let processEmptyRelVars env = env { relationVariables = mkEmptyRelVars (relationVariables env) }
220+{- let processEmptyRelVars env = env { relationVariables = mkEmptyRelVars (relationVariables env) }
205− MultipleExpr <$> local processEmptyRelVars (mapM applyStaticDatabaseOptimization exprs)
221+ MultipleExpr <$> local processEmptyRelVars (mapM applyStaticDatabaseOptimization exprs)-}
208−applyStaticPredicateOptimization :: GraphRefRestrictionPredicateExpr -> StaticOptimizerMonad GraphRefRestrictionPredicateExpr
224+applyStaticPredicateOptimization :: GraphRefRestrictionPredicateExpr -> GraphRefStaticOptimizerMonad GraphRefRestrictionPredicateExpr
209applyStaticPredicateOptimization predi = do
225applyStaticPredicateOptimization predi = do
210 optPred <- case predi of
226 optPred <- case predi of
211-- where x and x => where x
227-- where x and x => where x
@@ -298,18 +314,22 @@ isStaticAtomExpr FunctionAtomExpr{} = False
298isStaticAtomExpr RelationAtomExpr{} = False
314isStaticAtomExpr RelationAtomExpr{} = False
300--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
316--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
301−applyStaticJoinElimination :: GraphRefRelationalExpr -> StaticOptimizerMonad GraphRefRelationalExpr
317+applyStaticJoinElimination :: GraphRefRelationalExpr -> GraphRefStaticOptimizerMonad GraphRefRelationalExpr
302applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
318applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
303− env <- ask
319+ graph <- ask
320+ case inSameTransaction exprA exprB of
321+ -- the sub exprs are in different transactions or none at all, so we cannot extract inclusion dependencies across transaction boundaries
322+ Nothing -> pure expr
323+ Just commonTransId -> do
304− let typeForExpr e = runReader (typeForGraphRefRelationalExpr e) env
324+ let typeForExpr e = runReader (typeForGraphRefRelationalExpr e) graph
305− eProjType = typeForExpr expr
325+ eProjType = typeForExpr expr
306− eTypeA = typeForExpr exprA
326+ eTypeA = typeForExpr exprA
307− eTypeB = typeForExpr exprB
327+ eTypeB = typeForExpr exprB
308− liftErr = lift . except . Left
328+ liftErr = lift . except . Left
309− case eProjType of
329+ case eProjType of
310− Left err -> liftErr err
330+ Left err -> liftErr err
311− Right projType ->
331+ Right projType ->
312− case eTypeA of
332+ case eTypeA of
313 Left err -> liftErr err
333 Left err -> liftErr err
314 Right typeA ->
334 Right typeA ->
315 case eTypeB of
335 case eTypeB of
@@ -327,16 +347,20 @@ applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
327 Nothing -> -- this optimization does not apply
347 Nothing -> -- this optimization does not apply
328 pure expr
348 pure expr
329 Just ((joinedExpr, joinedType), (unjoinedExpr, _)) -> do
349 Just ((joinedExpr, joinedType), (unjoinedExpr, _)) -> do
350+ --lookup transaction
351+ trans <- lift $ except (transactionForId commonTransId graph)
330 --scan inclusion dependencies for a foreign key relationship
352 --scan inclusion dependencies for a foreign key relationship
331− incDeps <- inclusionDependencies . re_context <$> ask
353+ let incDeps = inclusionDependencies commonContext
354+ commonContext = concreteDatabaseContext trans
355+ reEnv = mkRelationalExprEnv commonContext commonTransId graph
332− let fkConstraint = foldM isFkConstraint False incDeps
356+ fkConstraint = foldM isFkConstraint False incDeps
333 --search for matching fk constraint
357 --search for matching fk constraint
334 isFkConstraint acc (InclusionDependency (Project subAttrNames subrv) (Project _ superrv)) = do
358 isFkConstraint acc (InclusionDependency (Project subAttrNames subrv) (Project _ superrv)) = do
335− let gfSubAttrNames = runReader (processAttributeNames subAttrNames) env
359+ let gfSubAttrNames = runReader (processAttributeNames subAttrNames) reEnv
336− gfSubRv = runReader (processRelationalExpr subrv) env
360+ gfSubRv = runReader (processRelationalExpr subrv) reEnv
337− gfSuperRv = runReader (processRelationalExpr superrv) env
361+ gfSuperRv = runReader (processRelationalExpr superrv) reEnv
339− case runReader (evalGraphRefAttributeNames gfSubAttrNames expr) env of
363+ case runReader (evalGraphRefAttributeNames gfSubAttrNames expr) graph of
340 Left _ -> pure acc
364 Left _ -> pure acc
341 Right subAttrNameSet ->
365 Right subAttrNameSet ->
342 pure (acc || (joinedExpr == gfSubRv &&
366 pure (acc || (joinedExpr == gfSubRv &&
@@ -438,4 +462,6 @@ applyStaticRestrictionPushdown expr = case expr of
438 Extend n sub ->
462 Extend n sub ->
439 Extend n (applyStaticRestrictionPushdown sub)
463 Extend n (applyStaticRestrictionPushdown sub)
441−
465+-- no optimizations available
466+optimizeDatabaseContextIOExpr :: GraphRefDatabaseContextIOExpr -> StaticOptimizerMonad GraphRefDatabaseContextIOExpr
467+optimizeDatabaseContextIOExpr x = pure x