@@ -1,289 +1,242 @@
1module ProjectM36.StaticOptimizer where
1module ProjectM36.StaticOptimizer where
2import ProjectM36.Base
2import ProjectM36.Base
3−import ProjectM36.RelationalExpression
3+import ProjectM36.GraphRefRelationalExpr
4import ProjectM36.Relation
4import ProjectM36.Relation
5+import ProjectM36.RelationalExpression
5import ProjectM36.Error
6import ProjectM36.Error
6import qualified ProjectM36.Attribute as A
7import qualified ProjectM36.Attribute as A
7import qualified ProjectM36.AttributeNames as AS
8import qualified ProjectM36.AttributeNames as AS
8import ProjectM36.TupleSet
9import ProjectM36.TupleSet
9import Control.Monad.State
10import Control.Monad.State
11+import Control.Monad.Trans.Reader
12+import Control.Monad.Trans.Except
13+import Data.Functor.Identity
10import Data.Either (rights, lefts)
14import Data.Either (rights, lefts)
11import Control.Monad.Trans.Reader
15import Control.Monad.Trans.Reader
12import qualified Data.Map as M
16import qualified Data.Map as M
13import qualified Data.Set as S
17import qualified Data.Set as S
20+type StaticOptimizerEnv = RelationalExprEnv
22+type StaticOptimizerMonad a = ReaderT StaticOptimizerEnv (ExceptT RelationalError Identity) a
15-- the static optimizer performs optimizations which need not take any specific-relation statistics into account
23-- the static optimizer performs optimizations which need not take any specific-relation statistics into account
16−optimizeRelationalExpr :: DatabaseContext -> RelationalExpr -> Either RelationalError RelationalExpr
24+optimize :: RelationalExprEnv -> GraphRefRelationalExpr -> Either RelationalError GraphRefRelationalExpr
17−optimizeRelationalExpr context expr = runReader (optimizeRelationalExprReader expr) (mkRelationalExprState context)
25+optimize reEnv expr = runIdentity (runExceptT (runReaderT (optimizeGraphRefRelationalExpr expr) reEnv))
19−optimizeRelationalExprReader :: RelationalExpr -> RelationalExprState (Either RelationalError RelationalExpr)
27+
20−optimizeRelationalExprReader expr = do
28+
21− eOptExpr <- applyStaticRelationalOptimization expr
29+fullOptimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> StaticOptimizerMonad GraphRefRelationalExpr
22− case eOptExpr of
30+fullOptimizeGraphRefRelationalExpr expr = do
23− Left err -> pure (Left err)
31+ optExpr <- optimizeGraphRefRelationalExpr expr
25− applyStaticJoinElimination (applyStaticRestrictionPushdown (applyStaticRestrictionCollapse optExpr))
32+ let optExpr' = applyStaticRestrictionPushdown (applyStaticRestrictionCollapse optExpr)
26−
33+ applyStaticJoinElimination optExpr'
27−optimizeDatabaseContextExpr :: DatabaseContext -> DatabaseContextExpr -> Either RelationalError DatabaseContextExpr
34+
28−optimizeDatabaseContextExpr context dbExpr = evalState (applyStaticDatabaseOptimization dbExpr) (freshDatabaseState context)
29-- apply optimizations which merely remove steps to become no-ops: example: projection of a relation across all of its attributes => original relation
35-- apply optimizations which merely remove steps to become no-ops: example: projection of a relation across all of its attributes => original relation
31--should optimizations offer the possibility to pure errors? If they perform the up-front type-checking, maybe so
37--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)
38+optimizeGraphRefRelationalExpr :: GraphRefRelationalExpr -> StaticOptimizerMonad GraphRefRelationalExpr
33−applyStaticRelationalOptimization e@(MakeStaticRelation _ _) = pure $ Right e
39+optimizeGraphRefRelationalExpr e@(MakeStaticRelation _ _) = pure e
35−applyStaticRelationalOptimization e@(MakeRelationFromExprs _ _) = pure $ Right e
41+optimizeGraphRefRelationalExpr e@(MakeRelationFromExprs _ _) = pure e
37−applyStaticRelationalOptimization e@(ExistingRelation _) = pure $ Right e
43+optimizeGraphRefRelationalExpr e@(ExistingRelation _) = pure e
39−applyStaticRelationalOptimization e@(RelationVariable _ _) = pure $ Right e
45+optimizeGraphRefRelationalExpr e@(RelationVariable _ _) = pure e
41--remove project of attributes which removes no attributes
47--remove project of attributes which removes no attributes
42−applyStaticRelationalOptimization (Project attrNameSet expr) = do
48+optimizeGraphRefRelationalExpr (Project attrNameSet expr) = do
43− relType <- typeForRelationalExpr expr
49+ reenv <- ask
50+ let relType = runReader (typeForGraphRefRelationalExpr expr) reenv
44 case relType of
51 case relType of
45− Left err -> pure $ Left err
52+ Left err -> lift $ except (Left err)
46 Right relType2
53 Right relType2
47− | AS.all == attrNameSet ->
54+ | AS.all == attrNameSet ->
48− applyStaticRelationalOptimization expr
55+ optimizeGraphRefRelationalExpr expr
49 | AttributeNames (attributeNames relType2) == attrNameSet ->
56 | AttributeNames (attributeNames relType2) == attrNameSet ->
50− applyStaticRelationalOptimization expr
57+ optimizeGraphRefRelationalExpr expr
51 | otherwise -> do
58 | otherwise -> do
52− optimizedSubExpression <- applyStaticRelationalOptimization expr
59+ optSubExpr <- optimizeGraphRefRelationalExpr expr
53− case optimizedSubExpression of
54− Left err -> pure $ Left err
55− Right optSubExpr -> pure (Right (Project attrNameSet optSubExpr))
60+ pure (Project attrNameSet optSubExpr)
57−applyStaticRelationalOptimization (Union exprA exprB) = do
62+optimizeGraphRefRelationalExpr (Union exprA exprB) = do
58− eOptExprA <- applyStaticRelationalOptimization exprA
63+ optExprA <- optimizeGraphRefRelationalExpr exprA
59− eOptExprB <- applyStaticRelationalOptimization exprB
64+ optExprB <- optimizeGraphRefRelationalExpr exprB
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+ -- (x where pred1) union (x where pred2) -> (x where pred1 or pred2)
65− case (optExprA, optExprB) of
66+ case (optExprA, optExprB) of
66− (Restrict predA (RelationVariable nameA ()),
67+ (Restrict predA (RelationVariable nameA sA),
67− Restrict predB (RelationVariable nameB ())) | nameA == nameB -> pure (Right (Restrict (AndPredicate predA predB) (RelationVariable nameA ())))
68+ Restrict predB (RelationVariable nameB sB)) | nameA == nameB && sA == sB -> pure (Restrict (AndPredicate predA predB) (RelationVariable nameA sA))
68 _ -> if optExprA == optExprB then
69 _ -> if optExprA == optExprB then
69− pure (Right optExprA)
70+ pure optExprA
71− pure $ Right $ Union optExprA optExprB
72+ pure $ Union optExprA optExprB
73−applyStaticRelationalOptimization (Join exprA exprB) = do
74+optimizeGraphRefRelationalExpr (Join exprA exprB) = do
74− eOptExprA <- applyStaticRelationalOptimization exprA
75+ optExprA <- optimizeGraphRefRelationalExpr exprA
75− eOptExprB <- applyStaticRelationalOptimization exprB
76+ optExprB <- optimizeGraphRefRelationalExpr exprB
77− Left err -> pure $ Left err
78− Right optExprA -> case eOptExprB of
79− Left err -> pure $ Left err
81− -- if the relvars to join are the same but with predicates, then just AndPredicate the predicates
77+ -- if the relvars to join are the same but with predicates, then just AndPredicate the predicates
82− case (optExprA, optExprB) of
78+ case (optExprA, optExprB) of
83− (Restrict predA (RelationVariable nameA ()),
79+ (Restrict predA (RelationVariable nameA sA),
84− Restrict predB (RelationVariable nameB ())) | nameA == nameB -> pure (Right (Restrict (AndPredicate predA predB) (RelationVariable nameA ())))
80+ Restrict predB (RelationVariable nameB sB)) | nameA == nameB && sA == sB -> pure (Restrict (AndPredicate predA predB) (RelationVariable nameA sA))
85 _ -> if optExprA == optExprB then --A join A == A
81 _ -> if optExprA == optExprB then --A join A == A
86− pure (Right optExprA)
82+ pure optExprA
88− pure (Right (Join optExprA optExprB))
84+ pure (Join optExprA optExprB)
90−applyStaticRelationalOptimization (Difference exprA exprB) = do
86+optimizeGraphRefRelationalExpr (Difference exprA exprB) = do
91− optExprA <- applyStaticRelationalOptimization exprA
87+ env <- ask
92− optExprB <- applyStaticRelationalOptimization exprB
88+ optExprA <- optimizeGraphRefRelationalExpr exprA
93− case optExprA of
89+ optExprB <- optimizeGraphRefRelationalExpr exprB
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
90+ if optExprA == optExprB then do --A difference A == A where false
98− eEmptyRel <- typeForRelationalExpr optExprA2
91+ let eEmptyRel = runReader (typeForGraphRefRelationalExpr optExprA) env
99− case eEmptyRel of
92+ case eEmptyRel of
100− Left err -> pure (Left err)
93+ Left err -> lift (except (Left err))
101− Right emptyRel -> pure (Right (ExistingRelation emptyRel))
94+ Right emptyRel -> pure (ExistingRelation emptyRel)
103− pure $ Right (Difference optExprA2 optExprB2)
96+ pure (Difference optExprA optExprB)
105−applyStaticRelationalOptimization e@Rename{} = pure $ Right e
98+optimizeGraphRefRelationalExpr e@Rename{} = pure e
107−applyStaticRelationalOptimization (Group oldAttrNames newAttrName expr) =
100+optimizeGraphRefRelationalExpr (Group oldAttrNames newAttrName expr) =
108− pure $ Right $ Group oldAttrNames newAttrName expr
101+ pure $ Group oldAttrNames newAttrName expr
110−applyStaticRelationalOptimization (Ungroup attrName expr) =
103+optimizeGraphRefRelationalExpr (Ungroup attrName expr) =
111− pure $ Right $ Ungroup attrName expr
104+ pure $ Ungroup attrName expr
113--remove restriction of nothing
106--remove restriction of nothing
114−applyStaticRelationalOptimization (Restrict predicate expr) = do
107+optimizeGraphRefRelationalExpr (Restrict predicate expr) = do
115 optimizedPredicate <- applyStaticPredicateOptimization predicate
109 optimizedPredicate <- applyStaticPredicateOptimization predicate
116 case optimizedPredicate of
110 case optimizedPredicate of
117− Left err -> pure $ Left err
111+ optimizedPredicate' | isTrueExpr optimizedPredicate' -> optimizeGraphRefRelationalExpr expr -- remove predicate entirely
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
112+ optimizedPredicate' | isFalseExpr optimizedPredicate' -> do -- replace where false predicate with empty relation with attributes from relexpr
121− attributesRel <- typeForRelationalExpr expr
113+ let attributesRel = runReader (typeForGraphRefRelationalExpr expr) env
122 case attributesRel of
114 case attributesRel of
123− Left err -> pure $ Left err
115+ Left err -> lift (except (Left err))
124− Right attributesRelA -> pure $ Right $ MakeStaticRelation (attributes attributesRelA) emptyTupleSet
116+ Right attributesRelA -> pure $ MakeStaticRelation (attributes attributesRelA) emptyTupleSet
125 | otherwise -> do
117 | otherwise -> do
126− optimizedSubExpression <- applyStaticRelationalOptimization expr
118+ optSubExpr <- optimizeGraphRefRelationalExpr expr
127− case optimizedSubExpression of
128− Left err -> pure $ Left err
129− Right optSubExpr -> pure $ Right $ Restrict optimizedPredicate2 optSubExpr
119+ pure $ Restrict optimizedPredicate' optSubExpr
131−applyStaticRelationalOptimization e@(Equals _ _) = pure $ Right e
121+optimizeGraphRefRelationalExpr e@(Equals _ _) = pure e
133−applyStaticRelationalOptimization e@(NotEquals _ _) = pure $ Right e
123+optimizeGraphRefRelationalExpr e@(NotEquals _ _) = pure e
135−applyStaticRelationalOptimization e@(Extend _ _) = pure $ Right e
125+optimizeGraphRefRelationalExpr e@(Extend _ _) = pure e
137−applyStaticRelationalOptimization e@(With _ _) = pure $ Right e
127+optimizeGraphRefRelationalExpr e@(With _ _) = pure e
139−applyStaticDatabaseOptimization :: DatabaseContextExpr -> DatabaseState (Either RelationalError DatabaseContextExpr)
129+-- database context expr
140−applyStaticDatabaseOptimization x@NoOperation = pure $ Right x
130+optimizeDatabaseContextExpr :: GraphRefDatabaseContextExpr -> StaticOptimizerMonad GraphRefDatabaseContextExpr
141−applyStaticDatabaseOptimization x@(Define _ _) = pure $ Right x
131+optimizeDatabaseContextExpr x@NoOperation = pure x
132+optimizeDatabaseContextExpr x@(Define _ _) = pure x
143−applyStaticDatabaseOptimization x@(Undefine _) = pure $ Right x
134+optimizeDatabaseContextExpr x@(Undefine _) = pure x
145−applyStaticDatabaseOptimization (Assign name expr) = do
136+optimizeDatabaseContextExpr (Assign name expr) = do
146− context <- getStateContext
137+ optExpr <- optimizeGraphRefRelationalExpr expr
147− let optimizedExpr = optimizeRelationalExpr context expr
138+ pure $ Assign name optExpr
148− case optimizedExpr of
149− Left err -> pure $ Left err
150− Right optimizedExpr2 -> pure $ Right (Assign name optimizedExpr2)
152−applyStaticDatabaseOptimization (Insert targetName expr) = do
140+optimizeDatabaseContextExpr (Insert targetName expr) = do
153− context <- getStateContext
141+ optimizedExpr <- optimizeGraphRefRelationalExpr expr
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
142+ if isEmptyRelationExpr optimizedExpr then -- if we are trying to insert an empty relation, do nothing
158− pure (Right NoOperation)
143+ pure NoOperation
160− case optimizedExpr2 of
145+ case optimizedExpr of
161− -- if the target relvar and the insert relvar are the same, there is nothing to do
146+ -- if the target relvar and the insert relvar are the same, there is nothing to do
162− -- insert s s -> NoOperation
147+ -- insert s s -> NoOperation
163− RelationVariable insName () | insName == targetName -> pure (Right NoOperation)
148+ RelationVariable insName _ | insName == targetName -> pure NoOperation
164− _ -> pure $ Right (Insert targetName optimizedExpr2)
149+ _ -> pure (Insert targetName optimizedExpr)
166−applyStaticDatabaseOptimization (Delete name predicate) = do
151+optimizeDatabaseContextExpr (Delete name predicate) =
167− context <- getStateContext
168− let optimizedPredicate = runReader (applyStaticPredicateOptimization predicate) (RelationalExprStateElems context)
152+ Delete name <$> applyStaticPredicateOptimization predicate
169− case optimizedPredicate of
170− Left err -> pure $ Left err
171− Right optimizedPredicate2 -> pure $ Right (Delete name optimizedPredicate2)
173−applyStaticDatabaseOptimization (Update name upmap predicate) = do
154+optimizeDatabaseContextExpr (Update name upmap predicate) =
174− context <- getStateContext
175− let optimizedPredicate = runReader (applyStaticPredicateOptimization predicate) (RelationalExprStateElems context)
155+ Update name upmap <$> applyStaticPredicateOptimization predicate
176− case optimizedPredicate of
177− Left err -> pure $ Left err
178− Right optimizedPredicate2 -> pure $ Right (Update name upmap optimizedPredicate2)
180−applyStaticDatabaseOptimization dep@(AddInclusionDependency _ _) = pure $ Right dep
157+optimizeDatabaseContextExpr dep@(AddInclusionDependency _ _) = pure dep
182−applyStaticDatabaseOptimization (RemoveInclusionDependency name) = pure $ Right (RemoveInclusionDependency name)
159+optimizeDatabaseContextExpr (RemoveInclusionDependency name) = pure (RemoveInclusionDependency name)
184−applyStaticDatabaseOptimization (AddNotification name triggerExpr resultOldExpr resultNewExpr) = do
161+optimizeDatabaseContextExpr (AddNotification name triggerExpr resultOldExpr resultNewExpr) = do
185− context <- getStateContext
162+ optExpr <- optimizeGraphRefRelationalExpr triggerExpr
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))
163+ pure (AddNotification name optExpr resultOldExpr resultNewExpr)
192−applyStaticDatabaseOptimization notif@(RemoveNotification _) = pure (Right notif)
165+optimizeDatabaseContextExpr notif@(RemoveNotification _) = pure notif
194−applyStaticDatabaseOptimization c@(AddTypeConstructor _ _) = pure (Right c)
167+optimizeDatabaseContextExpr c@(AddTypeConstructor _ _) = pure c
195−applyStaticDatabaseOptimization c@(RemoveTypeConstructor _) = pure (Right c)
168+optimizeDatabaseContextExpr c@(RemoveTypeConstructor _) = pure c
196−applyStaticDatabaseOptimization c@(RemoveAtomFunction _) = pure (Right c)
169+optimizeDatabaseContextExpr c@(RemoveAtomFunction _) = pure c
197−applyStaticDatabaseOptimization c@(RemoveDatabaseContextFunction _) = pure (Right c)
170+optimizeDatabaseContextExpr c@(RemoveDatabaseContextFunction _) = pure c
198−applyStaticDatabaseOptimization c@(ExecuteDatabaseContextFunction _ _) = pure (Right c)
171+optimizeDatabaseContextExpr c@(ExecuteDatabaseContextFunction _ _) = pure c
200--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
173--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
202--applyStaticDatabaseOptimization (MultipleExpr exprs) = pure $ Right $ MultipleExpr exprs
175--applyStaticDatabaseOptimization (MultipleExpr exprs) = pure $ Right $ MultipleExpr exprs
203--for multiple expressions, we must evaluate
176--for multiple expressions, we must evaluate
204applyStaticDatabaseOptimization (MultipleExpr exprs) = do
177applyStaticDatabaseOptimization (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)
211− pure $ Right $ MultipleExpr (rights optExprs)
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
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
215− _ <- evalDatabaseContextExpr expr
179+ let processEmptyRelVars env = env { relationVariables = mkEmptyRelVars (relationVariables env) }
216− applyStaticDatabaseOptimization expr
180+ MultipleExpr <$> local processEmptyRelVars (mapM applyStaticDatabaseOptimization exprs)
217− --this error handling could be improved with some lifting presumably
181+
218− --restore original context
182+
219−
183+applyStaticPredicateOptimization :: GraphRefRestrictionPredicateExpr -> StaticOptimizerMonad GraphRefRestrictionPredicateExpr
220−applyStaticPredicateOptimization :: RestrictionPredicateExpr -> RelationalExprState (Either RelationalError RestrictionPredicateExpr)
221applyStaticPredicateOptimization predi = do
184applyStaticPredicateOptimization predi = do
222− eOptPred <- case predi of
185+ optPred <- case predi of
223-- where x and x => where x
186-- where x and x => where x
224 AndPredicate pred1 pred2 -> do
187 AndPredicate pred1 pred2 -> do
225− eOptPred1 <- applyStaticPredicateOptimization pred1
188+ optPredA <- applyStaticPredicateOptimization pred1
227− Left err -> pure (Left err)
228− Right optPred1 -> do
229− eOptPred2 <- applyStaticPredicateOptimization pred2
189+ optPredB <- applyStaticPredicateOptimization pred2
230− case eOptPred2 of
190+ if optPredA == optPredB then
231− Left err -> pure (Left err)
191+ pure optPredA
233− if optPred1 == optPred2 then
234− pure (Right optPred1)
236− pure (Right (AndPredicate optPred1 optPred2))
193+ pure (AndPredicate optPredA optPredB)
237-- where x or x => where x
194-- where x or x => where x
238 OrPredicate pred1 pred2 -> do
195 OrPredicate pred1 pred2 -> do
239− eOptPred1 <- applyStaticPredicateOptimization pred1
196+ optPredA <- applyStaticPredicateOptimization pred1
241− Left err -> pure (Left err)
242− Right optPred1 -> do
243− eOptPred2 <- applyStaticPredicateOptimization pred2
197+ optPredB <- applyStaticPredicateOptimization pred2
244− case eOptPred2 of
198+ if optPredA == optPredB then
245− Left err -> pure (Left err)
199+ pure optPredA
246− Right optPred2 | optPred1 == optPred2 -> pure (Right optPred1)
200+ else if isTrueExpr optPredA then
247− | isTrueExpr optPred1 -> pure (Right optPred1) -- True or x -> True
201+ pure optPredA -- True or x -> True
248− | isTrueExpr optPred2 -> pure (Right optPred2)
202+ else if isTrueExpr optPredB then
249− | otherwise -> pure (Right (OrPredicate optPred1 optPred2))
203+ pure optPredB
205+ pure (OrPredicate optPredA optPredB)
250 AttributeEqualityPredicate attrNameA (AttributeAtomExpr attrNameB) ->
206 AttributeEqualityPredicate attrNameA (AttributeAtomExpr attrNameB) ->
251 if attrNameA == attrNameB then
207 if attrNameA == attrNameB then
252− pure (Right TruePredicate)
208+ pure TruePredicate
254− pure (Right predi)
210+ pure predi
255− AttributeEqualityPredicate{} -> pure (Right predi)
211+ AttributeEqualityPredicate{} -> pure predi
256− TruePredicate -> pure $ Right predi
212+ TruePredicate -> pure predi
257− NotPredicate{} -> pure $ Right predi
213+ NotPredicate{} -> pure predi
258− RelationalExprPredicate{} -> pure (Right predi)
214+ RelationalExprPredicate{} -> pure predi
259− AtomExprPredicate{} -> pure (Right predi)
215+ AtomExprPredicate{} -> pure predi
261− Left err -> pure (Left err)
263− let attrMap = findStaticRestrictionPredicates optPred in
216+ let attrMap = findStaticRestrictionPredicates optPred
264− pure (Right (replaceStaticAtomExprs optPred attrMap))
217+ pure (replaceStaticAtomExprs optPred attrMap)
266--determines if an atom expression is tautologically true
219--determines if an atom expression is tautologically true
267−isTrueExpr :: RestrictionPredicateExpr -> Bool
220+isTrueExpr :: RestrictionPredicateExprBase a -> Bool
268isTrueExpr TruePredicate = True
221isTrueExpr TruePredicate = True
269isTrueExpr (AtomExprPredicate (NakedAtomExpr (BoolAtom True))) = True
222isTrueExpr (AtomExprPredicate (NakedAtomExpr (BoolAtom True))) = True
270isTrueExpr _ = False
223isTrueExpr _ = False
272--determines if an atom expression is tautologically false
225--determines if an atom expression is tautologically false
273−isFalseExpr :: RestrictionPredicateExpr -> Bool
226+isFalseExpr :: RestrictionPredicateExprBase a -> Bool
274isFalseExpr (NotPredicate expr) = isTrueExpr expr
227isFalseExpr (NotPredicate expr) = isTrueExpr expr
275isFalseExpr (AtomExprPredicate (NakedAtomExpr (BoolAtom False))) = True
228isFalseExpr (AtomExprPredicate (NakedAtomExpr (BoolAtom False))) = True
276isFalseExpr _ = False
229isFalseExpr _ = False
278-- determine if the created relation can statically be determined to be empty
231-- determine if the created relation can statically be determined to be empty
279−isEmptyRelationExpr :: RelationalExpr -> Bool
232+isEmptyRelationExpr :: RelationalExprBase a -> Bool
280isEmptyRelationExpr (MakeRelationFromExprs _ []) = True
233isEmptyRelationExpr (MakeRelationFromExprs _ []) = True
281isEmptyRelationExpr (MakeStaticRelation _ tupSet) = null (asList tupSet)
234isEmptyRelationExpr (MakeStaticRelation _ tupSet) = null (asList tupSet)
282isEmptyRelationExpr (ExistingRelation rel) = rel == emptyRelationWithAttrs (attributes rel)
235isEmptyRelationExpr (ExistingRelation rel) = rel == emptyRelationWithAttrs (attributes rel)
283isEmptyRelationExpr _ = False
236isEmptyRelationExpr _ = False
285--transitive static variable optimization
238--transitive static variable optimization
286−replaceStaticAtomExprs :: RestrictionPredicateExpr -> M.Map AttributeName AtomExpr -> RestrictionPredicateExpr
239+replaceStaticAtomExprs :: GraphRefRestrictionPredicateExpr -> M.Map AttributeName GraphRefAtomExpr -> GraphRefRestrictionPredicateExpr
287replaceStaticAtomExprs predIn replaceMap = case predIn of
240replaceStaticAtomExprs predIn replaceMap = case predIn of
288 AttributeEqualityPredicate newAttrName (AttributeAtomExpr matchName) -> case M.lookup matchName replaceMap of
241 AttributeEqualityPredicate newAttrName (AttributeAtomExpr matchName) -> case M.lookup matchName replaceMap of
289 Nothing -> predIn
242 Nothing -> predIn
@@ -296,7 +249,7 @@ replaceStaticAtomExprs predIn replaceMap = case predIn of
296 RelationalExprPredicate{} -> predIn
249 RelationalExprPredicate{} -> predIn
297 AtomExprPredicate{} -> predIn
250 AtomExprPredicate{} -> predIn
298-- 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
251-- 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
300findStaticRestrictionPredicates (AttributeEqualityPredicate attrName atomExpr) =
253findStaticRestrictionPredicates (AttributeEqualityPredicate attrName atomExpr) =
301 case atomExpr of
254 case atomExpr of
302 val@NakedAtomExpr{} -> M.singleton attrName val
255 val@NakedAtomExpr{} -> M.singleton attrName val
@@ -320,20 +273,22 @@ isStaticAtomExpr FunctionAtomExpr{} = False
320isStaticAtomExpr RelationAtomExpr{} = False
273isStaticAtomExpr RelationAtomExpr{} = False
322--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
275--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
324applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
277applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
325− relState <- ask
278+ env <- ask
279+ let typeForExpr e = runReader (typeForGraphRefRelationalExpr e) env
326− eProjType <- typeForRelationalExpr expr
280+ eProjType = typeForExpr expr
327− eTypeA <- typeForRelationalExpr exprA
281+ eTypeA = typeForExpr exprA
328− eTypeB <- typeForRelationalExpr exprB
282+ eTypeB = typeForExpr exprB
283+ liftErr = lift . except . Left
329 case eProjType of
284 case eProjType of
330− Left err -> pure (Left err)
285+ Left err -> liftErr err
331 Right projType ->
286 Right projType ->
332 case eTypeA of
287 case eTypeA of
333− Left err -> pure (Left err)
288+ Left err -> liftErr err
334 Right typeA ->
289 Right typeA ->
335 case eTypeB of
290 case eTypeB of
336− Left err -> pure (Left err)
291+ Left err -> liftErr err
337 Right typeB -> do
292 Right typeB -> do
338 let matchesProjectionAttributes
293 let matchesProjectionAttributes
339 | attrNames projType `S.isSubsetOf` attrNames typeA =
294 | attrNames projType `S.isSubsetOf` attrNames typeA =
@@ -345,35 +300,39 @@ applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
345 attrNames = A.attributeNameSet . attributes
300 attrNames = A.attributeNameSet . attributes
346 case matchesProjectionAttributes of
301 case matchesProjectionAttributes of
347 Nothing -> -- this optimization does not apply
302 Nothing -> -- this optimization does not apply
348− pure (Right expr)
303+ pure expr
349 Just ((joinedExpr, joinedType), (unjoinedExpr, _)) -> do
304 Just ((joinedExpr, joinedType), (unjoinedExpr, _)) -> do
350 --scan inclusion dependencies for a foreign key relationship
305 --scan inclusion dependencies for a foreign key relationship
351− incDeps <- inclusionDependencies . stateElemsContext <$> ask
306+ incDeps <- inclusionDependencies . re_context <$> ask
352 let fkConstraint = foldM isFkConstraint False incDeps
307 let fkConstraint = foldM isFkConstraint False incDeps
353 --search for matching fk constraint
308 --search for matching fk constraint
354− isFkConstraint acc (InclusionDependency (Project subattrNames subrv) (Project _ superrv)) =
309+ isFkConstraint acc (InclusionDependency (Project subAttrNames subrv) (Project _ superrv)) = do
355− case runReader (evalAttributeNames subattrNames expr) relState of
310+ let gfSubAttrNames = runReader (processAttributeNames subAttrNames) env
311+ gfSubRv = runReader (processRelationalExpr subrv) env
312+ gfSuperRv = runReader (processRelationalExpr superrv) env
314+ case runReader (evalGraphRefAttributeNames gfSubAttrNames expr) env of
356 Left _ -> pure acc
315 Left _ -> pure acc
357 Right subAttrNameSet ->
316 Right subAttrNameSet ->
358− pure (acc || (joinedExpr == subrv &&
317+ pure (acc || (joinedExpr == gfSubRv &&
359− unjoinedExpr == superrv &&
318+ unjoinedExpr == gfSuperRv &&
360 -- the fk attribute is one of the projection attributes
319 -- the fk attribute is one of the projection attributes
361 A.attributeNamesContained subAttrNameSet (A.attributeNameSet (attributes joinedType))
320 A.attributeNamesContained subAttrNameSet (A.attributeNameSet (attributes joinedType))
363 isFkConstraint acc _ = pure acc
322 isFkConstraint acc _ = pure acc
364 case fkConstraint of
323 case fkConstraint of
365 Right True -> --join elimination optimization applies
324 Right True -> --join elimination optimization applies
366− applyStaticRelationalOptimization (Project attrNameSet joinedExpr)
325+ optimizeGraphRefRelationalExpr (Project attrNameSet joinedExpr)
367 Right False -> --join elimination optimization does not apply
326 Right False -> --join elimination optimization does not apply
368− pure (Right expr)
327+ pure expr
369 Left err ->
328 Left err ->
370− pure (Left err)
329+ lift $ except (Left err)
372−applyStaticJoinElimination expr = pure (Right expr)
331+applyStaticJoinElimination expr = pure expr
374--restriction collapse converts chained restrictions into (Restrict (And pred1 pred2 pred3...))
333--restriction collapse converts chained restrictions into (Restrict (And pred1 pred2 pred3...))
375 --this optimization should be fairly uncontroversial- performing a tuple scan once is cheaper than twice- parallelization can still take place
334 --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
377applyStaticRestrictionCollapse expr =
336applyStaticRestrictionCollapse expr =
378 case expr of
337 case expr of
379 MakeRelationFromExprs _ _ -> expr
338 MakeRelationFromExprs _ _ -> expr
@@ -410,14 +369,14 @@ applyStaticRestrictionCollapse expr =
410 andPreds = foldr (\(Restrict subpred _) acc -> AndPredicate acc subpred) firstPred (tail restrictions) in
369 andPreds = foldr (\(Restrict subpred _) acc -> AndPredicate acc subpred) firstPred (tail restrictions) in
411 Restrict andPreds optFinalExpr
370 Restrict andPreds optFinalExpr
413−sequentialRestrictions :: RelationalExpr -> [RelationalExpr]
372+sequentialRestrictions :: RelationalExprBase a -> [RelationalExprBase a]
414sequentialRestrictions expr@(Restrict _ subexpr) = expr:sequentialRestrictions subexpr
373sequentialRestrictions expr@(Restrict _ subexpr) = expr:sequentialRestrictions subexpr
415sequentialRestrictions _ = []
374sequentialRestrictions _ = []
417--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
376--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
418-- x{proj} where c1 -> (x where c1){proj} #project on fewer tuples
377-- x{proj} where c1 -> (x where c1){proj} #project on fewer tuples
419-- (x union y) where c -> (x where c) union (y where c) #with a selective restriction, fewer tuples will need to be joined
378-- (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
421applyStaticRestrictionPushdown expr = case expr of
380applyStaticRestrictionPushdown expr = case expr of
422 MakeRelationFromExprs _ _ -> expr
381 MakeRelationFromExprs _ _ -> expr
423 MakeStaticRelation _ _ -> expr
382 MakeStaticRelation _ _ -> expr