@@ -3,7 +3,9 @@ import ProjectM36.Base
33import ProjectM36.GraphRefRelationalExpr
44import ProjectM36.Relation
55import ProjectM36.RelationalExpression
6+import ProjectM36.TransGraphRelationalExpression as TGRE
67import ProjectM36.Error
8+import ProjectM36.Transaction
79import qualified ProjectM36.Attribute as A
810import qualified ProjectM36.AttributeNames as AS
911import ProjectM36.TupleSet
@@ -11,8 +13,6 @@ import Control.Monad.State
1113import Control.Monad.Trans.Reader
1214import Control.Monad.Trans.Except
1315import Data.Functor.Identity
14−import Data.Either (rights, lefts)
15−import Control.Monad.Trans.Reader
1616import qualified Data.Map as M
1717import qualified Data.Set as S
1818
@@ -21,37 +21,52 @@ type StaticOptimizerEnv = RelationalExprEnv
2121type StaticOptimizerMonad a = ReaderT StaticOptimizerEnv (ExceptT RelationalError Identity) a
2222-- the static optimizer performs optimizations which need not take any specific-relation statistics into account
2323
24+type GraphRefStaticOptimizerMonad a = ReaderT TransactionGraph (ExceptT RelationalError Identity) a
25+
2426-- | A temporary function to be replaced by IO-based implementation.
2527optimizeAndEvalRelationalExpr :: RelationalExprEnv -> RelationalExpr -> Either RelationalError Relation
2628optimizeAndEvalRelationalExpr env expr = do
2729 let gfExpr = runReader (processRelationalExpr expr) env
28− optExpr <- runStaticOptimizerMonad env (fullOptimizeGraphRefRelationalExpr gfExpr)
30+ optExpr <- runGraphRefStaticOptimizerMonad (re_graph env) (fullOptimizeGraphRefRelationalExpr gfExpr)
2931 evalGraphRefRelationalExpr optExpr (re_graph env)
3032
3133optimizeAndEvalDatabaseContextExpr :: DatabaseContextExpr -> DatabaseContextEvalMonad ()
3234optimizeAndEvalDatabaseContextExpr expr = do
3335 env <- dbcRelationalExprEnv
3436 let gfExpr = runReader (processDatabaseContextExpr expr) env
35− eOptExpr = runStaticOptimizerMonad env (optimizeDatabaseContextExpr gfExpr)
37+ eOptExpr = runGraphRefStaticOptimizerMonad (re_graph env) (optimizeGraphRefDatabaseContextExpr gfExpr)
3638 case eOptExpr of
3739 Left err -> lift (except (Left err))
3840 Right optExpr -> evalGraphRefDatabaseContextExpr optExpr
3941
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
47+
4048optimizeAndEvalDatabaseContextIOExpr :: DatabaseContextIOExpr -> DatabaseContextIOEvalMonad (Either RelationalError ())
4149optimizeAndEvalDatabaseContextIOExpr expr = do
4250 reEnv <- getDBCIORelationalExprEnv
4351 let gfExpr = runReader (processDatabaseContextIOExpr expr) reEnv
44− optExpr <- runStaticOptimizerMonad reEnv (optimizeDatbaseContextIOExpr gfExpr)
45− evalGraphRefDatabaseContextIOExpr optExpr
52+ eOptExpr = runStaticOptimizerMonad reEnv (optimizeDatabaseContextIOExpr gfExpr)
53+ case eOptExpr of
54+ Left err -> pure (Left err)
55+ Right optExpr ->
56+ evalGraphRefDatabaseContextIOExpr optExpr
4657
4758
4859runStaticOptimizerMonad :: RelationalExprEnv -> StaticOptimizerMonad a -> Either RelationalError a
4960runStaticOptimizerMonad env m = runIdentity (runExceptT (runReaderT m env))
5061
51−optimizeRelationalExpr' :: RelationalExprEnv -> GraphRefRelationalExpr -> Either RelationalError GraphRefRelationalExpr
52−optimizeRelationalExpr' reEnv expr = runIdentity (runExceptT (runReaderT (optimizeGraphRefRelationalExpr expr) reEnv))
62+runGraphRefStaticOptimizerMonad :: TransactionGraph -> GraphRefStaticOptimizerMonad a -> Either RelationalError a
63+runGraphRefStaticOptimizerMonad graph m = runIdentity (runExceptT (runReaderT m graph))
5364
54−fullOptimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> StaticOptimizerMonad GraphRefRelationalExpr
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))
68+
69+fullOptimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefStaticOptimizerMonad GraphRefRelationalExpr
5570fullOptimizeGraphRefRelationalExpr expr = do
5671 optExpr <- optimizeGraphRefRelationalExpr expr
5772 let optExpr' = applyStaticRestrictionPushdown (applyStaticRestrictionCollapse optExpr)
@@ -60,7 +75,7 @@ fullOptimizeGraphRefRelationalExpr expr = do
6075-- apply optimizations which merely remove steps to become no-ops: example: projection of a relation across all of its attributes => original relation
6176
6277--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
6479optimizeGraphRefRelationalExpr e@(MakeStaticRelation _ _) = pure e
6580
6681optimizeGraphRefRelationalExpr e@(MakeRelationFromExprs _ _) = pure e
@@ -130,12 +145,12 @@ optimizeGraphRefRelationalExpr (Ungroup attrName expr) =
130145
131146--remove restriction of nothing
132147optimizeGraphRefRelationalExpr (Restrict predicate expr) = do
133− env <- ask
148+ graph <- ask
134149 optimizedPredicate <- applyStaticPredicateOptimization predicate
135150 case optimizedPredicate of
136151 optimizedPredicate' | isTrueExpr optimizedPredicate' -> optimizeGraphRefRelationalExpr expr -- remove predicate entirely
137152 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
139154 case attributesRel of
140155 Left err -> lift (except (Left err))
141156 Right attributesRelA -> pure $ MakeStaticRelation (attributes attributesRelA) emptyTupleSet
@@ -152,17 +167,17 @@ optimizeGraphRefRelationalExpr e@(Extend _ _) = pure e
152167optimizeGraphRefRelationalExpr e@(With _ _) = pure e
153168
154169-- database context expr
155−optimizeDatabaseContextExpr :: GraphRefDatabaseContextExpr -> StaticOptimizerMonad GraphRefDatabaseContextExpr
156−optimizeDatabaseContextExpr x@NoOperation = pure x
157−optimizeDatabaseContextExpr x@(Define _ _) = pure x
170+optimizeGraphRefDatabaseContextExpr :: GraphRefDatabaseContextExpr -> GraphRefStaticOptimizerMonad GraphRefDatabaseContextExpr
171+optimizeGraphRefDatabaseContextExpr x@NoOperation = pure x
172+optimizeGraphRefDatabaseContextExpr x@(Define _ _) = pure x
158173
159−optimizeDatabaseContextExpr x@(Undefine _) = pure x
174+optimizeGraphRefDatabaseContextExpr x@(Undefine _) = pure x
160175
161−optimizeDatabaseContextExpr (Assign name expr) = do
176+optimizeGraphRefDatabaseContextExpr (Assign name expr) = do
162177 optExpr <- optimizeGraphRefRelationalExpr expr
163178 pure $ Assign name optExpr
164179
165−optimizeDatabaseContextExpr (Insert targetName expr) = do
180+optimizeGraphRefDatabaseContextExpr (Insert targetName expr) = do
166181 optimizedExpr <- fullOptimizeGraphRefRelationalExpr expr
167182 if isEmptyRelationExpr optimizedExpr then -- if we are trying to insert an empty relation, do nothing
168183 pure NoOperation
@@ -173,39 +188,40 @@ optimizeDatabaseContextExpr (Insert targetName expr) = do
173188 RelationVariable insName _ | insName == targetName -> pure NoOperation
174189 _ -> pure (Insert targetName optimizedExpr)
175190
176−optimizeDatabaseContextExpr (Delete name predicate) =
191+optimizeGraphRefDatabaseContextExpr (Delete name predicate) =
177192 Delete name <$> applyStaticPredicateOptimization predicate
178193
179−optimizeDatabaseContextExpr (Update name upmap predicate) =
194+optimizeGraphRefDatabaseContextExpr (Update name upmap predicate) =
180195 Update name upmap <$> applyStaticPredicateOptimization predicate
181196
182−optimizeDatabaseContextExpr dep@(AddInclusionDependency _ _) = pure dep
197+optimizeGraphRefDatabaseContextExpr dep@(AddInclusionDependency _ _) = pure dep
183198
184−optimizeDatabaseContextExpr (RemoveInclusionDependency name) = pure (RemoveInclusionDependency name)
199+optimizeGraphRefDatabaseContextExpr (RemoveInclusionDependency name) = pure (RemoveInclusionDependency name)
185200
186−optimizeDatabaseContextExpr (AddNotification name triggerExpr resultOldExpr resultNewExpr) =
201+optimizeGraphRefDatabaseContextExpr (AddNotification name triggerExpr resultOldExpr resultNewExpr) =
187202 --we can't optimize these expressions until they run
188203 pure (AddNotification name triggerExpr resultOldExpr resultNewExpr)
189204
190−optimizeDatabaseContextExpr notif@(RemoveNotification _) = pure notif
205+optimizeGraphRefDatabaseContextExpr notif@(RemoveNotification _) = pure notif
191206
192−optimizeDatabaseContextExpr c@(AddTypeConstructor _ _) = pure c
193−optimizeDatabaseContextExpr c@(RemoveTypeConstructor _) = pure c
194−optimizeDatabaseContextExpr c@(RemoveAtomFunction _) = pure c
195−optimizeDatabaseContextExpr c@(RemoveDatabaseContextFunction _) = pure c
196−optimizeDatabaseContextExpr c@(ExecuteDatabaseContextFunction _ _) = pure c
207+optimizeGraphRefDatabaseContextExpr c@(AddTypeConstructor _ _) = pure c
208+optimizeGraphRefDatabaseContextExpr c@(RemoveTypeConstructor _) = pure c
209+optimizeGraphRefDatabaseContextExpr c@(RemoveAtomFunction _) = pure c
210+optimizeGraphRefDatabaseContextExpr c@(RemoveDatabaseContextFunction _) = pure c
211+optimizeGraphRefDatabaseContextExpr c@(ExecuteDatabaseContextFunction _ _) = pure c
197212
198213--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
199214
200215--applyStaticDatabaseOptimization (MultipleExpr exprs) = pure $ Right $ MultipleExpr exprs
201216--for multiple expressions, we must evaluate
202−applyStaticDatabaseOptimization (MultipleExpr exprs) = do
217+optimizeGraphRefDatabaseContextExpr (MultipleExpr _) = do
203218 --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) }
205− MultipleExpr <$> local processEmptyRelVars (mapM applyStaticDatabaseOptimization exprs)
219+ unimplemented
220+{- let processEmptyRelVars env = env { relationVariables = mkEmptyRelVars (relationVariables env) }
221+ MultipleExpr <$> local processEmptyRelVars (mapM applyStaticDatabaseOptimization exprs)-}
206222
207223
208−applyStaticPredicateOptimization :: GraphRefRestrictionPredicateExpr -> StaticOptimizerMonad GraphRefRestrictionPredicateExpr
224+applyStaticPredicateOptimization :: GraphRefRestrictionPredicateExpr -> GraphRefStaticOptimizerMonad GraphRefRestrictionPredicateExpr
209225applyStaticPredicateOptimization predi = do
210226 optPred <- case predi of
211227-- where x and x => where x
@@ -298,18 +314,22 @@ isStaticAtomExpr FunctionAtomExpr{} = False
298314isStaticAtomExpr RelationAtomExpr{} = False
299315
300316--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
302318applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
303− env <- ask
304− let typeForExpr e = runReader (typeForGraphRefRelationalExpr e) env
305− eProjType = typeForExpr expr
306− eTypeA = typeForExpr exprA
307− eTypeB = typeForExpr exprB
308− liftErr = lift . except . Left
309− case eProjType of
310− Left err -> liftErr err
311− Right projType ->
312− case eTypeA of
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
324+ let typeForExpr e = runReader (typeForGraphRefRelationalExpr e) graph
325+ eProjType = typeForExpr expr
326+ eTypeA = typeForExpr exprA
327+ eTypeB = typeForExpr exprB
328+ liftErr = lift . except . Left
329+ case eProjType of
330+ Left err -> liftErr err
331+ Right projType ->
332+ case eTypeA of
313333 Left err -> liftErr err
314334 Right typeA ->
315335 case eTypeB of
@@ -327,16 +347,20 @@ applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
327347 Nothing -> -- this optimization does not apply
328348 pure expr
329349 Just ((joinedExpr, joinedType), (unjoinedExpr, _)) -> do
350+ --lookup transaction
351+ trans <- lift $ except (transactionForId commonTransId graph)
330352 --scan inclusion dependencies for a foreign key relationship
331− incDeps <- inclusionDependencies . re_context <$> ask
332− let fkConstraint = foldM isFkConstraint False incDeps
353+ let incDeps = inclusionDependencies commonContext
354+ commonContext = concreteDatabaseContext trans
355+ reEnv = mkRelationalExprEnv commonContext commonTransId graph
356+ fkConstraint = foldM isFkConstraint False incDeps
333357 --search for matching fk constraint
334358 isFkConstraint acc (InclusionDependency (Project subAttrNames subrv) (Project _ superrv)) = do
335− let gfSubAttrNames = runReader (processAttributeNames subAttrNames) env
336− gfSubRv = runReader (processRelationalExpr subrv) env
337− gfSuperRv = runReader (processRelationalExpr superrv) env
359+ let gfSubAttrNames = runReader (processAttributeNames subAttrNames) reEnv
360+ gfSubRv = runReader (processRelationalExpr subrv) reEnv
361+ gfSuperRv = runReader (processRelationalExpr superrv) reEnv
338362
339− case runReader (evalGraphRefAttributeNames gfSubAttrNames expr) env of
363+ case runReader (evalGraphRefAttributeNames gfSubAttrNames expr) graph of
340364 Left _ -> pure acc
341365 Right subAttrNameSet ->
342366 pure (acc || (joinedExpr == gfSubRv &&
@@ -438,4 +462,6 @@ applyStaticRestrictionPushdown expr = case expr of
438462 Extend n sub ->
439463 Extend n (applyStaticRestrictionPushdown sub)
440464
441−
465+-- no optimizations available
466+optimizeDatabaseContextIOExpr :: GraphRefDatabaseContextIOExpr -> StaticOptimizerMonad GraphRefDatabaseContextIOExpr
467+optimizeDatabaseContextIOExpr x = pure x