@@ -1,289 +1,242 @@
11module ProjectM36.StaticOptimizer where
22import ProjectM36.Base
3−import ProjectM36.RelationalExpression
3+import ProjectM36.GraphRefRelationalExpr
44import ProjectM36.Relation
5+import ProjectM36.RelationalExpression
56import ProjectM36.Error
67import qualified ProjectM36.Attribute as A
78import qualified ProjectM36.AttributeNames as AS
89import ProjectM36.TupleSet
910import Control.Monad.State
11+import Control.Monad.Trans.Reader
12+import Control.Monad.Trans.Except
13+import Data.Functor.Identity
1014import Data.Either (rights, lefts)
1115import Control.Monad.Trans.Reader
1216import qualified Data.Map as M
1317import qualified Data.Set as S
1418
19+
20+type StaticOptimizerEnv = RelationalExprEnv
21+
22+type StaticOptimizerMonad a = ReaderT StaticOptimizerEnv (ExceptT RelationalError Identity) a
1523-- the static optimizer performs optimizations which need not take any specific-relation statistics into account
16−optimizeRelationalExpr :: DatabaseContext -> RelationalExpr -> Either RelationalError RelationalExpr
17−optimizeRelationalExpr context expr = runReader (optimizeRelationalExprReader expr) (mkRelationalExprState context)
18−
19−optimizeRelationalExprReader :: RelationalExpr -> RelationalExprState (Either RelationalError RelationalExpr)
20−optimizeRelationalExprReader expr = do
21− eOptExpr <- applyStaticRelationalOptimization expr
22− case eOptExpr of
23− Left err -> pure (Left err)
24− Right optExpr ->
25− applyStaticJoinElimination (applyStaticRestrictionPushdown (applyStaticRestrictionCollapse optExpr))
26−
27−optimizeDatabaseContextExpr :: DatabaseContext -> DatabaseContextExpr -> Either RelationalError DatabaseContextExpr
28−optimizeDatabaseContextExpr context dbExpr = evalState (applyStaticDatabaseOptimization dbExpr) (freshDatabaseState context)
24+optimize :: RelationalExprEnv -> GraphRefRelationalExpr -> Either RelationalError GraphRefRelationalExpr
25+optimize reEnv expr = runIdentity (runExceptT (runReaderT (optimizeGraphRefRelationalExpr expr) reEnv))
26+
27+
28+
29+fullOptimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> StaticOptimizerMonad GraphRefRelationalExpr
30+fullOptimizeGraphRefRelationalExpr expr = do
31+ optExpr <- optimizeGraphRefRelationalExpr expr
32+ let optExpr' = applyStaticRestrictionPushdown (applyStaticRestrictionCollapse optExpr)
33+ applyStaticJoinElimination optExpr'
34+
2935-- apply optimizations which merely remove steps to become no-ops: example: projection of a relation across all of its attributes => original relation
3036
3137--should optimizations offer the possibility to pure errors? If they perform the up-front type-checking, maybe so
32−applyStaticRelationalOptimization :: RelationalExpr -> RelationalExprState (Either RelationalError RelationalExpr)
33−applyStaticRelationalOptimization e@(MakeStaticRelation _ _) = pure $ Right e
38+optimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> StaticOptimizerMonad GraphRefRelationalExpr
39+optimizeGraphRefRelationalExpr e@(MakeStaticRelation _ _) = pure e
3440
35−applyStaticRelationalOptimization e@(MakeRelationFromExprs _ _) = pure $ Right e
41+optimizeGraphRefRelationalExpr e@(MakeRelationFromExprs _ _) = pure e
3642
37−applyStaticRelationalOptimization e@(ExistingRelation _) = pure $ Right e
43+optimizeGraphRefRelationalExpr e@(ExistingRelation _) = pure e
3844
39−applyStaticRelationalOptimization e@(RelationVariable _ _) = pure $ Right e
45+optimizeGraphRefRelationalExpr e@(RelationVariable _ _) = pure e
4046
4147--remove project of attributes which removes no attributes
42−applyStaticRelationalOptimization (Project attrNameSet expr) = do
43− relType <- typeForRelationalExpr expr
48+optimizeGraphRefRelationalExpr (Project attrNameSet expr) = do
49+ reenv <- ask
50+ let relType = runReader (typeForGraphRefRelationalExpr expr) reenv
4451 case relType of
45− Left err -> pure $ Left err
52+ Left err -> lift $ except (Left err)
4653 Right relType2
47− | AS.all == attrNameSet ->
48− applyStaticRelationalOptimization expr
54+ | AS.all == attrNameSet ->
55+ optimizeGraphRefRelationalExpr expr
4956 | AttributeNames (attributeNames relType2) == attrNameSet ->
50− applyStaticRelationalOptimization expr
57+ optimizeGraphRefRelationalExpr expr
5158 | otherwise -> do
52− optimizedSubExpression <- applyStaticRelationalOptimization expr
53− case optimizedSubExpression of
54− Left err -> pure $ Left err
55− Right optSubExpr -> pure (Right (Project attrNameSet optSubExpr))
59+ optSubExpr <- optimizeGraphRefRelationalExpr expr
60+ pure (Project attrNameSet optSubExpr)
5661
57−applyStaticRelationalOptimization (Union exprA exprB) = do
58− eOptExprA <- applyStaticRelationalOptimization exprA
59− eOptExprB <- applyStaticRelationalOptimization exprB
60− case eOptExprA of
61− Left err -> pure $ Left err
62− Right optExprA -> case eOptExprB of
63− Left err -> pure $ Left err
64− Right optExprB -> -- (x where pred1) union (x where pred2) -> (x where pred1 or pred2)
65− case (optExprA, optExprB) of
66− (Restrict predA (RelationVariable nameA ()),
67− Restrict predB (RelationVariable nameB ())) | nameA == nameB -> pure (Right (Restrict (AndPredicate predA predB) (RelationVariable nameA ())))
62+optimizeGraphRefRelationalExpr (Union exprA exprB) = do
63+ optExprA <- optimizeGraphRefRelationalExpr exprA
64+ optExprB <- optimizeGraphRefRelationalExpr exprB
65+ -- (x where pred1) union (x where pred2) -> (x where pred1 or pred2)
66+ case (optExprA, optExprB) of
67+ (Restrict predA (RelationVariable nameA sA),
68+ Restrict predB (RelationVariable nameB sB)) | nameA == nameB && sA == sB -> pure (Restrict (AndPredicate predA predB) (RelationVariable nameA sA))
6869 _ -> if optExprA == optExprB then
69− pure (Right optExprA)
70+ pure optExprA
7071 else
71− pure $ Right $ Union optExprA optExprB
72+ pure $ Union optExprA optExprB
7273
73−applyStaticRelationalOptimization (Join exprA exprB) = do
74− eOptExprA <- applyStaticRelationalOptimization exprA
75− eOptExprB <- applyStaticRelationalOptimization exprB
76− case eOptExprA of
77− Left err -> pure $ Left err
78− Right optExprA -> case eOptExprB of
79− Left err -> pure $ Left err
80− Right optExprB ->
81− -- if the relvars to join are the same but with predicates, then just AndPredicate the predicates
82− case (optExprA, optExprB) of
83− (Restrict predA (RelationVariable nameA ()),
84− Restrict predB (RelationVariable nameB ())) | nameA == nameB -> pure (Right (Restrict (AndPredicate predA predB) (RelationVariable nameA ())))
74+optimizeGraphRefRelationalExpr (Join exprA exprB) = do
75+ optExprA <- optimizeGraphRefRelationalExpr exprA
76+ optExprB <- optimizeGraphRefRelationalExpr exprB
77+ -- if the relvars to join are the same but with predicates, then just AndPredicate the predicates
78+ case (optExprA, optExprB) of
79+ (Restrict predA (RelationVariable nameA sA),
80+ Restrict predB (RelationVariable nameB sB)) | nameA == nameB && sA == sB -> pure (Restrict (AndPredicate predA predB) (RelationVariable nameA sA))
8581 _ -> if optExprA == optExprB then --A join A == A
86− pure (Right optExprA)
82+ pure optExprA
8783 else
88− pure (Right (Join optExprA optExprB))
84+ pure (Join optExprA optExprB)
8985
90−applyStaticRelationalOptimization (Difference exprA exprB) = do
91− optExprA <- applyStaticRelationalOptimization exprA
92− optExprB <- applyStaticRelationalOptimization exprB
93− case optExprA of
94− Left err -> pure $ Left err
95− Right optExprA2 -> case optExprB of
96− Left err -> pure $ Left err
97− Right optExprB2 -> if optExprA == optExprB then do --A difference A == A where false
98− eEmptyRel <- typeForRelationalExpr optExprA2
99− case eEmptyRel of
100− Left err -> pure (Left err)
101− Right emptyRel -> pure (Right (ExistingRelation emptyRel))
102− else
103− pure $ Right (Difference optExprA2 optExprB2)
86+optimizeGraphRefRelationalExpr (Difference exprA exprB) = do
87+ env <- ask
88+ optExprA <- optimizeGraphRefRelationalExpr exprA
89+ optExprB <- optimizeGraphRefRelationalExpr exprB
90+ if optExprA == optExprB then do --A difference A == A where false
91+ let eEmptyRel = runReader (typeForGraphRefRelationalExpr optExprA) env
92+ case eEmptyRel of
93+ Left err -> lift (except (Left err))
94+ Right emptyRel -> pure (ExistingRelation emptyRel)
95+ else
96+ pure (Difference optExprA optExprB)
10497
105−applyStaticRelationalOptimization e@Rename{} = pure $ Right e
98+optimizeGraphRefRelationalExpr e@Rename{} = pure e
10699
107−applyStaticRelationalOptimization (Group oldAttrNames newAttrName expr) =
108− pure $ Right $ Group oldAttrNames newAttrName expr
100+optimizeGraphRefRelationalExpr (Group oldAttrNames newAttrName expr) =
101+ pure $ Group oldAttrNames newAttrName expr
109102
110−applyStaticRelationalOptimization (Ungroup attrName expr) =
111− pure $ Right $ Ungroup attrName expr
103+optimizeGraphRefRelationalExpr (Ungroup attrName expr) =
104+ pure $ Ungroup attrName expr
112105
113106--remove restriction of nothing
114−applyStaticRelationalOptimization (Restrict predicate expr) = do
107+optimizeGraphRefRelationalExpr (Restrict predicate expr) = do
108+ env <- ask
115109 optimizedPredicate <- applyStaticPredicateOptimization predicate
116110 case optimizedPredicate of
117− Left err -> pure $ Left err
118− Right optimizedPredicate2
119− | isTrueExpr optimizedPredicate2 -> applyStaticRelationalOptimization expr -- remove predicate entirely
120− | isFalseExpr optimizedPredicate2 -> do -- replace where false predicate with empty relation with attributes from relexpr
121− attributesRel <- typeForRelationalExpr expr
111+ optimizedPredicate' | isTrueExpr optimizedPredicate' -> optimizeGraphRefRelationalExpr expr -- remove predicate entirely
112+ optimizedPredicate' | isFalseExpr optimizedPredicate' -> do -- replace where false predicate with empty relation with attributes from relexpr
113+ let attributesRel = runReader (typeForGraphRefRelationalExpr expr) env
122114 case attributesRel of
123− Left err -> pure $ Left err
124− Right attributesRelA -> pure $ Right $ MakeStaticRelation (attributes attributesRelA) emptyTupleSet
115+ Left err -> lift (except (Left err))
116+ Right attributesRelA -> pure $ MakeStaticRelation (attributes attributesRelA) emptyTupleSet
125117 | otherwise -> do
126− optimizedSubExpression <- applyStaticRelationalOptimization expr
127− case optimizedSubExpression of
128− Left err -> pure $ Left err
129− Right optSubExpr -> pure $ Right $ Restrict optimizedPredicate2 optSubExpr
118+ optSubExpr <- optimizeGraphRefRelationalExpr expr
119+ pure $ Restrict optimizedPredicate' optSubExpr
130120
131−applyStaticRelationalOptimization e@(Equals _ _) = pure $ Right e
121+optimizeGraphRefRelationalExpr e@(Equals _ _) = pure e
132122
133−applyStaticRelationalOptimization e@(NotEquals _ _) = pure $ Right e
123+optimizeGraphRefRelationalExpr e@(NotEquals _ _) = pure e
134124
135−applyStaticRelationalOptimization e@(Extend _ _) = pure $ Right e
125+optimizeGraphRefRelationalExpr e@(Extend _ _) = pure e
136126
137−applyStaticRelationalOptimization e@(With _ _) = pure $ Right e
127+optimizeGraphRefRelationalExpr e@(With _ _) = pure e
138128
139−applyStaticDatabaseOptimization :: DatabaseContextExpr -> DatabaseState (Either RelationalError DatabaseContextExpr)
140−applyStaticDatabaseOptimization x@NoOperation = pure $ Right x
141−applyStaticDatabaseOptimization x@(Define _ _) = pure $ Right x
129+-- database context expr
130+optimizeDatabaseContextExpr :: GraphRefDatabaseContextExpr -> StaticOptimizerMonad GraphRefDatabaseContextExpr
131+optimizeDatabaseContextExpr x@NoOperation = pure x
132+optimizeDatabaseContextExpr x@(Define _ _) = pure x
142133
143−applyStaticDatabaseOptimization x@(Undefine _) = pure $ Right x
134+optimizeDatabaseContextExpr x@(Undefine _) = pure x
144135
145−applyStaticDatabaseOptimization (Assign name expr) = do
146− context <- getStateContext
147− let optimizedExpr = optimizeRelationalExpr context expr
148− case optimizedExpr of
149− Left err -> pure $ Left err
150− Right optimizedExpr2 -> pure $ Right (Assign name optimizedExpr2)
136+optimizeDatabaseContextExpr (Assign name expr) = do
137+ optExpr <- optimizeGraphRefRelationalExpr expr
138+ pure $ Assign name optExpr
151139
152−applyStaticDatabaseOptimization (Insert targetName expr) = do
153− context <- getStateContext
154− let optimizedExpr = optimizeRelationalExpr context expr
155− case optimizedExpr of
156− Left err -> pure $ Left err
157− Right optimizedExpr2 -> if isEmptyRelationExpr optimizedExpr2 then -- if we are trying to insert an empty relation, do nothing
158− pure (Right NoOperation)
159− else
160− case optimizedExpr2 of
161− -- if the target relvar and the insert relvar are the same, there is nothing to do
162− -- insert s s -> NoOperation
163− RelationVariable insName () | insName == targetName -> pure (Right NoOperation)
164− _ -> pure $ Right (Insert targetName optimizedExpr2)
140+optimizeDatabaseContextExpr (Insert targetName expr) = do
141+ optimizedExpr <- optimizeGraphRefRelationalExpr expr
142+ if isEmptyRelationExpr optimizedExpr then -- if we are trying to insert an empty relation, do nothing
143+ pure NoOperation
144+ else
145+ case optimizedExpr of
146+ -- if the target relvar and the insert relvar are the same, there is nothing to do
147+ -- insert s s -> NoOperation
148+ RelationVariable insName _ | insName == targetName -> pure NoOperation
149+ _ -> pure (Insert targetName optimizedExpr)
165150
166−applyStaticDatabaseOptimization (Delete name predicate) = do
167− context <- getStateContext
168− let optimizedPredicate = runReader (applyStaticPredicateOptimization predicate) (RelationalExprStateElems context)
169− case optimizedPredicate of
170− Left err -> pure $ Left err
171− Right optimizedPredicate2 -> pure $ Right (Delete name optimizedPredicate2)
151+optimizeDatabaseContextExpr (Delete name predicate) =
152+ Delete name <$> applyStaticPredicateOptimization predicate
172153
173−applyStaticDatabaseOptimization (Update name upmap predicate) = do
174− context <- getStateContext
175− let optimizedPredicate = runReader (applyStaticPredicateOptimization predicate) (RelationalExprStateElems context)
176− case optimizedPredicate of
177− Left err -> pure $ Left err
178− Right optimizedPredicate2 -> pure $ Right (Update name upmap optimizedPredicate2)
154+optimizeDatabaseContextExpr (Update name upmap predicate) =
155+ Update name upmap <$> applyStaticPredicateOptimization predicate
179156
180−applyStaticDatabaseOptimization dep@(AddInclusionDependency _ _) = pure $ Right dep
157+optimizeDatabaseContextExpr dep@(AddInclusionDependency _ _) = pure dep
181158
182−applyStaticDatabaseOptimization (RemoveInclusionDependency name) = pure $ Right (RemoveInclusionDependency name)
159+optimizeDatabaseContextExpr (RemoveInclusionDependency name) = pure (RemoveInclusionDependency name)
183160
184−applyStaticDatabaseOptimization (AddNotification name triggerExpr resultOldExpr resultNewExpr) = do
185− context <- getStateContext
186− let eTriggerExprOpt = optimizeRelationalExpr context triggerExpr
187− case eTriggerExprOpt of
188− Left err -> pure $ Left err
189− Right triggerExprOpt -> --it doesn't make sense to optimize queries when we don't have their proper contexts
190− pure (Right (AddNotification name triggerExprOpt resultOldExpr resultNewExpr))
161+optimizeDatabaseContextExpr (AddNotification name triggerExpr resultOldExpr resultNewExpr) = do
162+ optExpr <- optimizeGraphRefRelationalExpr triggerExpr
163+ pure (AddNotification name optExpr resultOldExpr resultNewExpr)
191164
192−applyStaticDatabaseOptimization notif@(RemoveNotification _) = pure (Right notif)
165+optimizeDatabaseContextExpr notif@(RemoveNotification _) = pure notif
193166
194−applyStaticDatabaseOptimization c@(AddTypeConstructor _ _) = pure (Right c)
195−applyStaticDatabaseOptimization c@(RemoveTypeConstructor _) = pure (Right c)
196−applyStaticDatabaseOptimization c@(RemoveAtomFunction _) = pure (Right c)
197−applyStaticDatabaseOptimization c@(RemoveDatabaseContextFunction _) = pure (Right c)
198−applyStaticDatabaseOptimization c@(ExecuteDatabaseContextFunction _ _) = pure (Right c)
167+optimizeDatabaseContextExpr c@(AddTypeConstructor _ _) = pure c
168+optimizeDatabaseContextExpr c@(RemoveTypeConstructor _) = pure c
169+optimizeDatabaseContextExpr c@(RemoveAtomFunction _) = pure c
170+optimizeDatabaseContextExpr c@(RemoveDatabaseContextFunction _) = pure c
171+optimizeDatabaseContextExpr c@(ExecuteDatabaseContextFunction _ _) = pure c
199172
200173--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
201174
202175--applyStaticDatabaseOptimization (MultipleExpr exprs) = pure $ Right $ MultipleExpr exprs
203176--for multiple expressions, we must evaluate
204177applyStaticDatabaseOptimization (MultipleExpr exprs) = do
205− context <- getStateContext
206− let optExprs = evalState substateRunner (contextWithEmptyTupleSets context, M.empty, False)
207− let errors = lefts optExprs
208− if not (null errors) then
209− pure $ Left (head errors)
210− else
211− pure $ Right $ MultipleExpr (rights optExprs)
212− where
213− substateRunner = forM exprs $ \expr -> do
214− --a previous expression 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
215− _ <- evalDatabaseContextExpr expr
216− applyStaticDatabaseOptimization expr
217− --this error handling could be improved with some lifting presumably
218− --restore original context
219−
220−applyStaticPredicateOptimization :: RestrictionPredicateExpr -> RelationalExprState (Either RelationalError RestrictionPredicateExpr)
178+ --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
179+ let processEmptyRelVars env = env { relationVariables = mkEmptyRelVars (relationVariables env) }
180+ MultipleExpr <$> local processEmptyRelVars (mapM applyStaticDatabaseOptimization exprs)
181+
182+
183+applyStaticPredicateOptimization :: GraphRefRestrictionPredicateExpr -> StaticOptimizerMonad GraphRefRestrictionPredicateExpr
221184applyStaticPredicateOptimization predi = do
222− eOptPred <- case predi of
185+ optPred <- case predi of
223186-- where x and x => where x
224187 AndPredicate pred1 pred2 -> do
225− eOptPred1 <- applyStaticPredicateOptimization pred1
226− case eOptPred1 of
227− Left err -> pure (Left err)
228− Right optPred1 -> do
229− eOptPred2 <- applyStaticPredicateOptimization pred2
230− case eOptPred2 of
231− Left err -> pure (Left err)
232− Right optPred2 ->
233− if optPred1 == optPred2 then
234− pure (Right optPred1)
235− else
236− pure (Right (AndPredicate optPred1 optPred2))
188+ optPredA <- applyStaticPredicateOptimization pred1
189+ optPredB <- applyStaticPredicateOptimization pred2
190+ if optPredA == optPredB then
191+ pure optPredA
192+ else
193+ pure (AndPredicate optPredA optPredB)
237194-- where x or x => where x
238195 OrPredicate pred1 pred2 -> do
239− eOptPred1 <- applyStaticPredicateOptimization pred1
240− case eOptPred1 of
241− Left err -> pure (Left err)
242− Right optPred1 -> do
243− eOptPred2 <- applyStaticPredicateOptimization pred2
244− case eOptPred2 of
245− Left err -> pure (Left err)
246− Right optPred2 | optPred1 == optPred2 -> pure (Right optPred1)
247− | isTrueExpr optPred1 -> pure (Right optPred1) -- True or x -> True
248− | isTrueExpr optPred2 -> pure (Right optPred2)
249− | otherwise -> pure (Right (OrPredicate optPred1 optPred2))
196+ optPredA <- applyStaticPredicateOptimization pred1
197+ optPredB <- applyStaticPredicateOptimization pred2
198+ if optPredA == optPredB then
199+ pure optPredA
200+ else if isTrueExpr optPredA then
201+ pure optPredA -- True or x -> True
202+ else if isTrueExpr optPredB then
203+ pure optPredB
204+ else
205+ pure (OrPredicate optPredA optPredB)
250206 AttributeEqualityPredicate attrNameA (AttributeAtomExpr attrNameB) ->
251207 if attrNameA == attrNameB then
252− pure (Right TruePredicate)
208+ pure TruePredicate
253209 else
254− pure (Right predi)
255− AttributeEqualityPredicate{} -> pure (Right predi)
256− TruePredicate -> pure $ Right predi
257− NotPredicate{} -> pure $ Right predi
258− RelationalExprPredicate{} -> pure (Right predi)
259− AtomExprPredicate{} -> pure (Right predi)
260− case eOptPred of
261− Left err -> pure (Left err)
262− Right optPred ->
263− let attrMap = findStaticRestrictionPredicates optPred in
264− pure (Right (replaceStaticAtomExprs optPred attrMap))
210+ pure predi
211+ AttributeEqualityPredicate{} -> pure predi
212+ TruePredicate -> pure predi
213+ NotPredicate{} -> pure predi
214+ RelationalExprPredicate{} -> pure predi
215+ AtomExprPredicate{} -> pure predi
216+ let attrMap = findStaticRestrictionPredicates optPred
217+ pure (replaceStaticAtomExprs optPred attrMap)
265218
266219--determines if an atom expression is tautologically true
267−isTrueExpr :: RestrictionPredicateExpr -> Bool
220+isTrueExpr :: RestrictionPredicateExprBase a -> Bool
268221isTrueExpr TruePredicate = True
269222isTrueExpr (AtomExprPredicate (NakedAtomExpr (BoolAtom True))) = True
270223isTrueExpr _ = False
271224
272225--determines if an atom expression is tautologically false
273−isFalseExpr :: RestrictionPredicateExpr -> Bool
226+isFalseExpr :: RestrictionPredicateExprBase a -> Bool
274227isFalseExpr (NotPredicate expr) = isTrueExpr expr
275228isFalseExpr (AtomExprPredicate (NakedAtomExpr (BoolAtom False))) = True
276229isFalseExpr _ = False
277230
278231-- determine if the created relation can statically be determined to be empty
279−isEmptyRelationExpr :: RelationalExpr -> Bool
232+isEmptyRelationExpr :: RelationalExprBase a -> Bool
280233isEmptyRelationExpr (MakeRelationFromExprs _ []) = True
281234isEmptyRelationExpr (MakeStaticRelation _ tupSet) = null (asList tupSet)
282235isEmptyRelationExpr (ExistingRelation rel) = rel == emptyRelationWithAttrs (attributes rel)
283236isEmptyRelationExpr _ = False
284237
285238--transitive static variable optimization
286−replaceStaticAtomExprs :: RestrictionPredicateExpr -> M.Map AttributeName AtomExpr -> RestrictionPredicateExpr
239+replaceStaticAtomExprs :: GraphRefRestrictionPredicateExpr -> M.Map AttributeName GraphRefAtomExpr -> GraphRefRestrictionPredicateExpr
287240replaceStaticAtomExprs predIn replaceMap = case predIn of
288241 AttributeEqualityPredicate newAttrName (AttributeAtomExpr matchName) -> case M.lookup matchName replaceMap of
289242 Nothing -> predIn
@@ -296,7 +249,7 @@ replaceStaticAtomExprs predIn replaceMap = case predIn of
296249 RelationalExprPredicate{} -> predIn
297250 AtomExprPredicate{} -> predIn
298251-- used for transitive attribute optimization- only works on statically-determined atoms for now- in the future, this could work for all AtomExprs which don't reference attributes
299−findStaticRestrictionPredicates :: RestrictionPredicateExpr -> M.Map AttributeName AtomExpr
252+findStaticRestrictionPredicates :: GraphRefRestrictionPredicateExpr -> M.Map AttributeName GraphRefAtomExpr
300253findStaticRestrictionPredicates (AttributeEqualityPredicate attrName atomExpr) =
301254 case atomExpr of
302255 val@NakedAtomExpr{} -> M.singleton attrName val
@@ -320,20 +273,22 @@ isStaticAtomExpr FunctionAtomExpr{} = False
320273isStaticAtomExpr RelationAtomExpr{} = False
321274
322275--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
323−applyStaticJoinElimination :: RelationalExpr -> RelationalExprState (Either RelationalError RelationalExpr)
276+applyStaticJoinElimination :: GraphRefRelationalExpr -> StaticOptimizerMonad GraphRefRelationalExpr
324277applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
325− relState <- ask
326− eProjType <- typeForRelationalExpr expr
327− eTypeA <- typeForRelationalExpr exprA
328− eTypeB <- typeForRelationalExpr exprB
278+ env <- ask
279+ let typeForExpr e = runReader (typeForGraphRefRelationalExpr e) env
280+ eProjType = typeForExpr expr
281+ eTypeA = typeForExpr exprA
282+ eTypeB = typeForExpr exprB
283+ liftErr = lift . except . Left
329284 case eProjType of
330− Left err -> pure (Left err)
285+ Left err -> liftErr err
331286 Right projType ->
332287 case eTypeA of
333− Left err -> pure (Left err)
288+ Left err -> liftErr err
334289 Right typeA ->
335290 case eTypeB of
336− Left err -> pure (Left err)
291+ Left err -> liftErr err
337292 Right typeB -> do
338293 let matchesProjectionAttributes
339294 | attrNames projType `S.isSubsetOf` attrNames typeA =
@@ -345,35 +300,39 @@ applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
345300 attrNames = A.attributeNameSet . attributes
346301 case matchesProjectionAttributes of
347302 Nothing -> -- this optimization does not apply
348− pure (Right expr)
303+ pure expr
349304 Just ((joinedExpr, joinedType), (unjoinedExpr, _)) -> do
350305 --scan inclusion dependencies for a foreign key relationship
351− incDeps <- inclusionDependencies . stateElemsContext <$> ask
306+ incDeps <- inclusionDependencies . re_context <$> ask
352307 let fkConstraint = foldM isFkConstraint False incDeps
353308 --search for matching fk constraint
354− isFkConstraint acc (InclusionDependency (Project subattrNames subrv) (Project _ superrv)) =
355− case runReader (evalAttributeNames subattrNames expr) relState of
309+ isFkConstraint acc (InclusionDependency (Project subAttrNames subrv) (Project _ superrv)) = do
310+ let gfSubAttrNames = runReader (processAttributeNames subAttrNames) env
311+ gfSubRv = runReader (processRelationalExpr subrv) env
312+ gfSuperRv = runReader (processRelationalExpr superrv) env
313+
314+ case runReader (evalGraphRefAttributeNames gfSubAttrNames expr) env of
356315 Left _ -> pure acc
357316 Right subAttrNameSet ->
358− pure (acc || (joinedExpr == subrv &&
359− unjoinedExpr == superrv &&
317+ pure (acc || (joinedExpr == gfSubRv &&
318+ unjoinedExpr == gfSuperRv &&
360319 -- the fk attribute is one of the projection attributes
361320 A.attributeNamesContained subAttrNameSet (A.attributeNameSet (attributes joinedType))
362321 ))
363322 isFkConstraint acc _ = pure acc
364323 case fkConstraint of
365324 Right True -> --join elimination optimization applies
366− applyStaticRelationalOptimization (Project attrNameSet joinedExpr)
325+ optimizeGraphRefRelationalExpr (Project attrNameSet joinedExpr)
367326 Right False -> --join elimination optimization does not apply
368− pure (Right expr)
327+ pure expr
369328 Left err ->
370− pure (Left err)
329+ lift $ except (Left err)
371330
372−applyStaticJoinElimination expr = pure (Right expr)
331+applyStaticJoinElimination expr = pure expr
373332
374333--restriction collapse converts chained restrictions into (Restrict (And pred1 pred2 pred3...))
375334 --this optimization should be fairly uncontroversial- performing a tuple scan once is cheaper than twice- parallelization can still take place
376−applyStaticRestrictionCollapse :: RelationalExpr -> RelationalExpr
335+applyStaticRestrictionCollapse :: GraphRefRelationalExpr -> GraphRefRelationalExpr
377336applyStaticRestrictionCollapse expr =
378337 case expr of
379338 MakeRelationFromExprs _ _ -> expr
@@ -410,14 +369,14 @@ applyStaticRestrictionCollapse expr =
410369 andPreds = foldr (\(Restrict subpred _) acc -> AndPredicate acc subpred) firstPred (tail restrictions) in
411370 Restrict andPreds optFinalExpr
412371
413−sequentialRestrictions :: RelationalExpr -> [RelationalExpr]
372+sequentialRestrictions :: RelationalExprBase a -> [RelationalExprBase a]
414373sequentialRestrictions expr@(Restrict _ subexpr) = expr:sequentialRestrictions subexpr
415374sequentialRestrictions _ = []
416375
417376--restriction pushdown only really makes sense for tuple-oriented storage schemes where performing a restriction before projection can cut down on the intermediate storage needed to store the data before the projection
418377-- x{proj} where c1 -> (x where c1){proj} #project on fewer tuples
419378-- (x union y) where c -> (x where c) union (y where c) #with a selective restriction, fewer tuples will need to be joined
420−applyStaticRestrictionPushdown :: RelationalExpr -> RelationalExpr
379+applyStaticRestrictionPushdown :: GraphRefRelationalExpr -> GraphRefRelationalExpr
421380applyStaticRestrictionPushdown expr = case expr of
422381 MakeRelationFromExprs _ _ -> expr
423382 MakeStaticRelation _ _ -> expr