on master help sign in
WIP RelationalExpr + StaticOptimizer treatment
51b014dAgentM
src/lib/ProjectM36/AttributeNames.hs+3−2
@@ -3,8 +3,9 @@ import ProjectM36.Base
3import qualified Data.Set as S
3import qualified Data.Set as S
4--AttributeNames is a data structure which can represent inverted projection attributes and attribute names derived from relational expressions
4--AttributeNames is a data structure which can represent inverted projection attributes and attribute names derived from relational expressions
5
5
6−empty :: AttributeNames
6+empty :: AttributeNamesBase a
7empty = AttributeNames S.empty
7empty = AttributeNames S.empty
8
8
9−all :: AttributeNames
9+all :: AttributeNamesBase a
10all = InvertedAttributeNames S.empty
10all = InvertedAttributeNames S.empty
11+
src/lib/ProjectM36/Base.hs+4−2
@@ -311,6 +311,8 @@ type DatabaseContextExprName = StringType
311
311
312type DatabaseContextExpr = DatabaseContextExprBase ()
312type DatabaseContextExpr = DatabaseContextExprBase ()
313
313
314+type GraphRefDatabaseContextExpr = DatabaseContextExprBase TransactionId
315+
314-- | Database context expressions modify the database context.
316-- | Database context expressions modify the database context.
315data DatabaseContextExprBase a =
317data DatabaseContextExprBase a =
316 NoOperation |
318 NoOperation |
@@ -318,8 +320,8 @@ data DatabaseContextExprBase a =
318 Undefine RelVarName | --forget existence of relvar X
320 Undefine RelVarName | --forget existence of relvar X
319 Assign RelVarName (RelationalExprBase a) |
321 Assign RelVarName (RelationalExprBase a) |
320 Insert RelVarName (RelationalExprBase a) |
322 Insert RelVarName (RelationalExprBase a) |
321− Delete RelVarName RestrictionPredicateExpr |
323+ Delete RelVarName (RestrictionPredicateExprBase a) |
322− Update RelVarName AttributeNameAtomExprMap RestrictionPredicateExpr |
324+ Update RelVarName AttributeNameAtomExprMap (RestrictionPredicateExprBase a) |
323
325
324 AddInclusionDependency IncDepName InclusionDependency |
326 AddInclusionDependency IncDepName InclusionDependency |
325 RemoveInclusionDependency IncDepName |
327 RemoveInclusionDependency IncDepName |
src/lib/ProjectM36/DatabaseContextFunctionUtils.hs+3−3
@@ -6,9 +6,9 @@ import ProjectM36.Error
6import Control.Monad.State
6import Control.Monad.State
7import Control.Monad.Trans.Reader
7import Control.Monad.Trans.Reader
8
8
9−executeDatabaseContextExpr :: DatabaseContextExpr -> DatabaseContext -> Either DatabaseContextFunctionError DatabaseContext
9+executeDatabaseContextExpr :: DatabaseContextExpr -> TransactionId -> TransactionGraph -> DatabaseContext -> Either DatabaseContextFunctionError DatabaseContext
10−executeDatabaseContextExpr expr context = case runState (evalDatabaseContextExpr expr) (freshDatabaseState context) of
10+executeDatabaseContextExpr expr tid graph context = case runState (evalDatabaseContextExpr expr tid graph) (freshDatabaseState context) of
11− (Right (), (context', _, _)) -> pure context'
11+ (Right (), st) -> pure (context t)
12 (Left err, _) -> error (show err)
12 (Left err, _) -> error (show err)
13
13
14executeRelationalExpr :: RelationalExpr -> DatabaseContext -> Either RelationalError Relation
14executeRelationalExpr :: RelationalExpr -> DatabaseContext -> Either RelationalError Relation
src/lib/ProjectM36/GraphRefRelationalExpr.hsnew file+22
@@ -0,0 +1,22 @@
1+module ProjectM36.GraphRefRelationalExpr where
2+--evaluate relational expressions across the entire transaction graph to support cross-transaction referencing
3+import ProjectM36.Base
4+import ProjectM36.Error
5+import qualified ProjectM36.Attribute as A
6+import Control.Monad.Trans.Except
7+
8+-- core evaluation function- all other relational expr forms compile to GraphRefRelationalExpr
9+eval :: GraphRefRelationalExpr -> TransactionGraph -> Either RelationalError Relation
10+eval = undefined
11+{-eval (MakeRelationFromExprs mAttrExprs tupleExprs) graph = do
12+ mAttrs <- case mAttrExprs of
13+ Just _ ->
14+ Just . A.attributesFromList <$> mapM (evalAttrExpr tConss) (fromMaybe [] mAttrExprs)
15+ Nothing -> pure Nothing
16+ tuples <- mapM (evalTupleExpr mAttrs) tupleExprs
17+ let attrs = fromMaybe firstTupleAttrs mAttrs
18+ firstTupleAttrs = if null tuples then A.emptyAttributes else tupleAttributes (head tuples)
19+ mkRelation attrs (RelationTupleSet tuples)
20+
21+
22+-}
src/lib/ProjectM36/IsomorphicSchema.hs+3−2
@@ -261,7 +261,7 @@ relationVariablesInSchema schema@(Schema morphs) context = foldM transform M.emp
261 let rvNames = isomorphInRelVarNames morph
261 let rvNames = isomorphInRelVarNames morph
262 rvAssocs <- mapM (\rv -> do
262 rvAssocs <- mapM (\rv -> do
263 expr' <- processRelationalExprInSchema schema (RelationVariable rv ())
263 expr' <- processRelationalExprInSchema schema (RelationVariable rv ())
264− rel <- runReader (evalRelationalExpr expr') (RelationalExprStateElems context)
264+ rel <- unimplemented --runReader (evalRelationalExpr expr') (RelationalExprStateElems context)
265 pure (rv, rel)) rvNames
265 pure (rv, rel)) rvNames
266 pure (M.union newRvMap (M.fromList rvAssocs))
266 pure (M.union newRvMap (M.fromList rvAssocs))
267
267
@@ -321,7 +321,8 @@ evalSchemaExpr (AddSubschema sname morphs) context sschemas =
321 moreIncDeps = foldr (\morph acc -> M.union acc (createIncDepsForIsomorph sname morph)) M.empty morphs
321 moreIncDeps = foldr (\morph acc -> M.union acc (createIncDepsForIsomorph sname morph)) M.empty morphs
322 incDepExprs = MultipleExpr (map (uncurry AddInclusionDependency) (M.toList moreIncDeps))
322 incDepExprs = MultipleExpr (map (uncurry AddInclusionDependency) (M.toList moreIncDeps))
323 in
323 in
324+ case unimplemented of
324− case runState (evalDatabaseContextExpr incDepExprs) (context, M.empty, False) of
325+-- case runState (evalDatabaseContextExpr incDepExprs) (context, M.empty, False) of
325 (Left err, _) -> Left err
326 (Left err, _) -> Left err
326 (Right (), (newContext,_,_)) -> pure (newSchemas, newContext) --need to propagate dirty flag here
327 (Right (), (newContext,_,_)) -> pure (newSchemas, newContext) --need to propagate dirty flag here
327 where
328 where
src/lib/ProjectM36/RelationalExpression.hs+70−42
@@ -58,50 +58,51 @@ freshDatabaseState context = DatabaseStateElems {
58 } --future work: propagate return accumulator
58 } --future work: propagate return accumulator
59
59
60-- we need to pass around a higher level RelationTuple and Attributes in order to solve #52
60-- we need to pass around a higher level RelationTuple and Attributes in order to solve #52
61−data RelationalExprStateElems = RelationalExprStateElems {
61+data RelationalExprEnv = RelationalExprEnv {
62− elems_context :: DatabaseContext,
62+ re_context :: DatabaseContext,
63− elems_graph :: TransactionGraph,
63+ re_graph :: TransactionGraph,
64− elems_currentTransId :: TransactionId,
64+ re_currentTransId :: TransactionId,
65− elems_extra :: Maybe (Either RelationTuple Attributes)
65+ re_extra :: Maybe (Either RelationTuple Attributes)
66 }
66 }
67
67
68−stateTuple :: RelationalExprStateElems -> RelationTuple
68+stateTuple :: RelationalExprEnv -> RelationTuple
69−stateTuple e = fromLeft emptyTuple (fromMaybe (Left emptyTuple) (elems_extra e))
69+stateTuple e = fromLeft emptyTuple (fromMaybe (Left emptyTuple) (re_extra e))
70
70
71−stateAttributes :: RelationalExprStateElems -> Attributes
71+stateAttributes :: RelationalExprEnv -> Attributes
72−stateAttributes e = fromRight emptyAttributes (fromMaybe (Right emptyAttributes) (elems_extra e))
72+stateAttributes e = fromRight emptyAttributes (fromMaybe (Right emptyAttributes) (re_extra e))
73{-
73{-
74−data RelationalExprStateElems = RelationalExprStateTupleElems DatabaseContext RelationTuple | -- used when fully evaluating a relexpr
74+data RelationalExprEnv = RelationalExprStateTupleElems DatabaseContext RelationTuple | -- used when fully evaluating a relexpr
75 RelationalExprStateAttrsElems DatabaseContext Attributes | --used when evaluating the type of a relexpr
75 RelationalExprStateAttrsElems DatabaseContext Attributes | --used when evaluating the type of a relexpr
76− RelationalExprStateElems DatabaseContext --used by default at the top level of evaluation
76+ RelationalExprEnv DatabaseContext --used by default at the top level of evaluation
77 -}
77 -}
78
78
79−instance Show RelationalExprStateElems where show e@RelationalExprStateElems{} = "RelationalExprStateElems " ++ show (elems_extra e)
79+instance Show RelationalExprEnv where
80+ show e@RelationalExprEnv{} = "RelationalExprEnv " ++ show (re_extra e)
80
81
81−mkRelationalExprState :: DatabaseContext -> TransactionId -> TransactionGraph -> RelationalExprStateElems
82+mkRelationalExprState :: DatabaseContext -> TransactionId -> TransactionGraph -> RelationalExprEnv
82mkRelationalExprState ctx currentTransId graph =
83mkRelationalExprState ctx currentTransId graph =
83− RelationalExprStateElems
84+ RelationalExprEnv
84− { elems_context = ctx,
85+ { re_context = ctx,
85− elems_graph = graph,
86+ re_graph = graph,
86− elems_currentTransId = currentTransId,
87+ re_currentTransId = currentTransId,
87− elems_extra = Nothing }
88+ re_extra = Nothing }
88
89
89currentTrans :: RelationalExprState (Either RelationalError Transaction)
90currentTrans :: RelationalExprState (Either RelationalError Transaction)
90currentTrans = do
91currentTrans = do
91− tid <- elems_currentTransId <$> ask
92+ tid <- re_currentTransId <$> ask
92− graph <- elems_graph <$> ask
93+ graph <- re_graph <$> ask
93 pure (transactionForId tid graph)
94 pure (transactionForId tid graph)
94
95
95−mergeTuplesIntoRelationalExprState :: RelationTuple -> RelationalExprStateElems -> RelationalExprStateElems
96+mergeTuplesIntoRelationalExprState :: RelationTuple -> RelationalExprEnv -> RelationalExprEnv
96−mergeTuplesIntoRelationalExprState tupIn e@RelationalExprStateElems{} =
97+mergeTuplesIntoRelationalExprState tupIn e@RelationalExprEnv{} =
97− e{elems_extra = new_elems }
98+ e{re_extra = new_elems }
98 where
99 where
99 new_elems = Just (Left newTuple)
100 new_elems = Just (Left newTuple)
100 mergedTupMap = M.union (tupleToMap tupIn) (tupleToMap (stateTuple e))
101 mergedTupMap = M.union (tupleToMap tupIn) (tupleToMap (stateTuple e))
101 newTuple = mkRelationTupleFromMap mergedTupMap
102 newTuple = mkRelationTupleFromMap mergedTupMap
102
103
103−mergeAttributesIntoRelationalExprState :: Attributes -> RelationalExprStateElems -> RelationalExprStateElems
104+mergeAttributesIntoRelationalExprState :: Attributes -> RelationalExprEnv -> RelationalExprEnv
104−mergeAttributesIntoRelationalExprState attrsIn e@RelationalExprStateElems{} = e{elems_extra = newattrs }
105+mergeAttributesIntoRelationalExprState attrsIn e@RelationalExprEnv{} = e{re_extra = newattrs }
105 where
106 where
106 newattrs = Just (Right (A.union attrsIn (stateAttributes e)))
107 newattrs = Just (Right (A.union attrsIn (stateAttributes e)))
107
108
@@ -129,18 +130,18 @@ putStateContext ctx' = do
129 s <- get
130 s <- get
130 put (s {context = ctx'})
131 put (s {context = ctx'})
131
132
132−type RelationalExprState a = Reader RelationalExprStateElems a
133+type RelationalExprState a = Reader RelationalExprEnv a
133
134
134−stateElemsContext :: RelationalExprStateElems -> DatabaseContext
135+envContext :: RelationalExprEnv -> DatabaseContext
135−stateElemsContext = elems_context
136+envContext = re_context
136
137
137−setStateElemsContext :: RelationalExprStateElems -> DatabaseContext -> RelationalExprStateElems
138+setEnvContext :: RelationalExprEnv -> DatabaseContext -> RelationalExprEnv
138−setStateElemsContext e ctx = e { elems_context = ctx }
139+setEnvContext e ctx = e { re_context = ctx }
139
140
140--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
141--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
141evalRelationalExpr :: RelationalExpr -> RelationalExprState (Either RelationalError GraphRefRelationalExpr)
142evalRelationalExpr :: RelationalExpr -> RelationalExprState (Either RelationalError GraphRefRelationalExpr)
142evalRelationalExpr (RelationVariable name _) = do
143evalRelationalExpr (RelationVariable name _) = do
143− relvarTable <- fmap (relationVariables . stateElemsContext) ask
144+ relvarTable <- fmap (relationVariables . envContext) ask
144 return $ case M.lookup name relvarTable of
145 return $ case M.lookup name relvarTable of
145 Just res -> Right res
146 Just res -> Right res
146 Nothing -> Left $ RelVarNotDefinedError name
147 Nothing -> Left $ RelVarNotDefinedError name
@@ -188,7 +189,7 @@ evalRelationalExpr (MakeStaticRelation attributeSet tupleSet) =
188 Left err -> return $ Left err
189 Left err -> return $ Left err
189
190
190evalRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do
191evalRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do
191− currentContext <- fmap stateElemsContext ask
192+ currentContext <- fmap envContext ask
192 let tConss = typeConstructorMapping currentContext
193 let tConss = typeConstructorMapping currentContext
193 -- if the mAttrExprs is Nothing, then we should attempt to infer the tuple attributes from the first tuple itself- note that this is not always possible
194 -- if the mAttrExprs is Nothing, then we should attempt to infer the tuple attributes from the first tuple itself- note that this is not always possible
194 runExceptT $ do
195 runExceptT $ do
@@ -257,7 +258,7 @@ evalRelationalExpr (With views mainExpr) = do
257 case foldM addScopedView (stateElemsContext rstate) views of
258 case foldM addScopedView (stateElemsContext rstate) views of
258 Left err -> return $ Left err
259 Left err -> return $ Left err
259 Right ctx'' -> do
260 Right ctx'' -> do
260− let evalMainExpr expr = runReader (evalRelationalExpr expr) (RelationalExprStateElems ctx'')
261+ let evalMainExpr expr = runReader (evalRelationalExpr expr) (RelationalExprEnv ctx'')
261 case evalMainExpr mainExpr of
262 case evalMainExpr mainExpr of
262 Left err -> return $ Left err
263 Left err -> return $ Left err
263 Right rel -> return $ Right rel
264 Right rel -> return $ Right rel
@@ -886,7 +887,7 @@ typeFromAtomExpr attrs (AttributeAtomExpr attrName) = do
886
887
887typeFromAtomExpr _ (NakedAtomExpr atom) = pure (Right (atomTypeForAtom atom))
888typeFromAtomExpr _ (NakedAtomExpr atom) = pure (Right (atomTypeForAtom atom))
888typeFromAtomExpr attrs (FunctionAtomExpr funcName atomArgs _) = do
889typeFromAtomExpr attrs (FunctionAtomExpr funcName atomArgs _) = do
889− context <- fmap stateElemsContext ask
890+ context <- fmap envContext ask
890 let funcs = atomFunctions context
891 let funcs = atomFunctions context
891 case atomFunctionForName funcName funcs of
892 case atomFunctionForName funcName funcs of
892 Left err -> pure (Left err)
893 Left err -> pure (Left err)
@@ -912,7 +913,7 @@ typeFromAtomExpr attrs (RelationAtomExpr relExpr) = do
912typeFromAtomExpr attrs (ConstructedAtomExpr dConsName dConsArgs _) =
913typeFromAtomExpr attrs (ConstructedAtomExpr dConsName dConsArgs _) =
913 runExceptT $ do
914 runExceptT $ do
914 argsTypes <- mapM (liftE . typeFromAtomExpr attrs) dConsArgs
915 argsTypes <- mapM (liftE . typeFromAtomExpr attrs) dConsArgs
915− context <- fmap stateElemsContext (lift ask)
916+ context <- fmap envContext (lift ask)
916 either throwE pure (atomTypeForDataConstructor (typeConstructorMapping context) dConsName argsTypes)
917 either throwE pure (atomTypeForDataConstructor (typeConstructorMapping context) dConsName argsTypes)
917
918
918-- | Validate that the type of the AtomExpr matches the expected type.
919-- | Validate that the type of the AtomExpr matches the expected type.
@@ -933,7 +934,7 @@ verifyAtomExprTypes _ (NakedAtomExpr atom) expectedType = pure (atomTypeVerify e
933verifyAtomExprTypes relIn (FunctionAtomExpr funcName funcArgExprs _) expectedType = do
934verifyAtomExprTypes relIn (FunctionAtomExpr funcName funcArgExprs _) expectedType = do
934 rstate <- ask
935 rstate <- ask
935 let functions = atomFunctions context
936 let functions = atomFunctions context
936− context = stateElemsContext rstate
937+ context = envContext rstate
937 runExceptT $ do
938 runExceptT $ do
938 func <- either throwE pure (atomFunctionForName funcName functions)
939 func <- either throwE pure (atomFunctionForName funcName functions)
939 let expectedArgTypes = atomFuncType func
940 let expectedArgTypes = atomFuncType func
@@ -965,7 +966,7 @@ evalAttrExpr _ (NakedAttributeExpr attr) = Right attr
965
966
966evalTupleExpr :: Maybe Attributes -> TupleExpr -> RelationalExprState (Either RelationalError RelationTuple)
967evalTupleExpr :: Maybe Attributes -> TupleExpr -> RelationalExprState (Either RelationalError RelationTuple)
967evalTupleExpr mAttrs (TupleExpr tupMap) = do
968evalTupleExpr mAttrs (TupleExpr tupMap) = do
968− context <- fmap stateElemsContext ask
969+ context <- fmap envContext ask
969 runExceptT $ do
970 runExceptT $ do
970 -- it's not possible for AtomExprs in tuple constructors to reference other Attributes' atoms due to the necessary order-of-operations (need a tuple to pass to evalAtomExpr)- it may be possible with some refactoring of type usage or delayed evaluation- needs more thought, but not a priority
971 -- it's not possible for AtomExprs in tuple constructors to reference other Attributes' atoms due to the necessary order-of-operations (need a tuple to pass to evalAtomExpr)- it may be possible with some refactoring of type usage or delayed evaluation- needs more thought, but not a priority
971 -- I could adjust this logic so that when the attributes are not specified (Nothing), then I can attempt to extract the attributes from the tuple- the type resolution will blow up if an ambiguous data constructor is used (Left 4) and this should allow simple cases to "relation{tuple{a 4}}" to be processed
972 -- I could adjust this logic so that when the attributes are not specified (Nothing), then I can attempt to extract the attributes from the tuple- the type resolution will blow up if an ambiguous data constructor is used (Left 4) and this should allow simple cases to "relation{tuple{a 4}}" to be processed
@@ -1039,7 +1040,7 @@ evalAttributeNames attrNames expr = do
1039 case eAttrExprType of
1040 case eAttrExprType of
1040 Left err -> pure (Left err)
1041 Left err -> pure (Left err)
1041 Right attrExprType -> pure (Right (A.attributeNameSet (attributes attrExprType)))
1042 Right attrExprType -> pure (Right (A.attributeNameSet (attributes attrExprType)))
1042−
1043+
1043evalGraphRefRelationalExpr :: GraphRefRelationalExpr -> TransactionGraph -> Either RelationalError Relation
1044evalGraphRefRelationalExpr :: GraphRefRelationalExpr -> TransactionGraph -> Either RelationalError Relation
1044evalGraphRefRelationalExpr (RelationVariable name tid) graph = do
1045evalGraphRefRelationalExpr (RelationVariable name tid) graph = do
1045 ctx <- dbContextForTransId tid graph
1046 ctx <- dbContextForTransId tid graph
@@ -1190,10 +1191,10 @@ processAtomExpr :: AtomExpr -> RelationalExprState GraphRefAtomExpr
1190processAtomExpr (AttributeAtomExpr nam) = pure $ AttributeAtomExpr nam
1191processAtomExpr (AttributeAtomExpr nam) = pure $ AttributeAtomExpr nam
1191processAtomExpr (NakedAtomExpr atom) = pure $ NakedAtomExpr atom
1192processAtomExpr (NakedAtomExpr atom) = pure $ NakedAtomExpr atom
1192processAtomExpr (FunctionAtomExpr fName atomExprs ()) = do
1193processAtomExpr (FunctionAtomExpr fName atomExprs ()) = do
1193− tid <- elems_currentTransId <$> ask
1194+ tid <- re_currentTransId <$> ask
1194 FunctionAtomExpr fName <$> mapM processAtomExpr atomExprs <*> pure tid
1195 FunctionAtomExpr fName <$> mapM processAtomExpr atomExprs <*> pure tid
1195processAtomExpr (RelationAtomExpr expr) = RelationAtomExpr <$> processRelationalExpr expr
1196processAtomExpr (RelationAtomExpr expr) = RelationAtomExpr <$> processRelationalExpr expr
1196−processAtomExpr (ConstructedAtomExpr dConsName atomExprs ()) = ConstructedAtomExpr dConsName <$> mapM processAtomExpr atomExprs <*> (elems_currentTransId <$> ask)
1197+processAtomExpr (ConstructedAtomExpr dConsName atomExprs ()) = ConstructedAtomExpr dConsName <$> mapM processAtomExpr atomExprs <*> (re_currentTransId <$> ask)
1197
1198
1198processTupleExpr :: TupleExpr -> RelationalExprState GraphRefTupleExpr
1199processTupleExpr :: TupleExpr -> RelationalExprState GraphRefTupleExpr
1199processTupleExpr (TupleExpr tMap) =
1200processTupleExpr (TupleExpr tMap) =
@@ -1201,7 +1202,7 @@ processTupleExpr (TupleExpr tMap) =
1201
1202
1202evalGraphRefAttributeExpr :: GraphRefAttributeExpr -> RelationalExprState (Either RelationalError Attribute)
1203evalGraphRefAttributeExpr :: GraphRefAttributeExpr -> RelationalExprState (Either RelationalError Attribute)
1203evalGraphRefAttributeExpr (AttributeAndTypeNameExpr attrName tCons tid) = do
1204evalGraphRefAttributeExpr (AttributeAndTypeNameExpr attrName tCons tid) = do
1204− graph <- elems_graph <$> ask
1205+ graph <- re_graph <$> ask
1205 case transactionForId tid graph of
1206 case transactionForId tid graph of
1206 Left err -> pure (Left err)
1207 Left err -> pure (Left err)
1207 Right trans -> do
1208 Right trans -> do
@@ -1216,7 +1217,7 @@ evalGraphRefAttributeExpr (AttributeAndTypeNameExpr attrName tCons tid) = do
1216--convert AttributeExpr to GraphRefAttributeExpr
1217--convert AttributeExpr to GraphRefAttributeExpr
1217processAttributeExpr :: AttributeExpr -> RelationalExprState GraphRefAttributeExpr
1218processAttributeExpr :: AttributeExpr -> RelationalExprState GraphRefAttributeExpr
1218processAttributeExpr (AttributeAndTypeNameExpr nam tCons ()) = do
1219processAttributeExpr (AttributeAndTypeNameExpr nam tCons ()) = do
1219− tid <- elems_currentTransId <$> ask
1220+ tid <- re_currentTransId <$> ask
1220 pure $ AttributeAndTypeNameExpr nam tCons tid
1221 pure $ AttributeAndTypeNameExpr nam tCons tid
1221processAttributeExpr (NakedAttributeExpr attr) = pure $ NakedAttributeExpr attr
1222processAttributeExpr (NakedAttributeExpr attr) = pure $ NakedAttributeExpr attr
1222
1223
@@ -1227,3 +1228,30 @@ processRelationalExpr (MakeRelationFromExprs mAttrs tupleExprs) = do
1227 Nothing -> pure Nothing
1228 Nothing -> pure Nothing
1228 Just mAttrs'' -> Just <$> mapM processAttributeExpr mAttrs''
1229 Just mAttrs'' -> Just <$> mapM processAttributeExpr mAttrs''
1229 MakeRelationFromExprs mAttrs' <$> mapM processTupleExpr tupleExprs
1230 MakeRelationFromExprs mAttrs' <$> mapM processTupleExpr tupleExprs
1231+
1232+
1233+mkEmptyRelVars :: RelationVariables -> RelationVariables
1234+mkEmptyRelVars rvMap = M.map mkEmptyRelVar rvMap
1235+ where
1236+ mkEmptyRelVar (MakeRelationFromExprs mAttrs _) = MakeRelationFromExprs mAttrs []
1237+ mkEmptyRelVar (MakeStaticRelation attrs _) = MakeStaticRelation attrs emptyTupleSet
1238+ mkEmptyRelVar (ExistingRelation rel) = ExistingRelation (emptyRelationWithAttrs (attributes rel))
1239+ mkEmptyRelVar rv@RelationVariable{} = Restrict (NotPredicate TruePredicate) rv
1240+ mkEmptyRelVar (Project attrNames expr) = Project attrNames (mkEmptyRelVar expr)
1241+ mkEmptyRelVar (Union exprA exprB) = Union (mkEmptyRelVar exprA) (mkEmptyRelVar exprB)
1242+ mkEmptyRelVar (Join exprA exprB) = Join (mkEmptyRelVar exprA) (mkEmptyRelVar exprB)
1243+ mkEmptyRelVar (Rename nameA nameB expr) = Rename nameA nameB (mkEmptyRelVar expr)
1244+ mkEmptyRelVar (Difference exprA exprB) = Difference (mkEmptyRelVar exprA) (mkEmptyRelVar exprB)
1245+ mkEmptyRelVar (Group attrNames attrName expr) = Group attrNames attrName (mkEmptyRelVar expr)
1246+ mkEmptyRelVar (Ungroup attrName expr) = Ungroup attrName (mkEmptyRelVar expr)
1247+ mkEmptyRelVar (Restrict pred expr) = Restrict pred (mkEmptyRelVar expr)
1248+ mkEmptyRelVar (Equals exprA exprB) = Equals (mkEmptyRelVar exprA) (mkEmptyRelVar exprB)
1249+ mkEmptyRelVar (NotEquals exprA exprB) = NotEquals (mkEmptyRelVar exprA) (mkEmptyRelVar exprB)
1250+ mkEmptyRelVar (Extend extTuple expr) = Extend extTuple (mkEmptyRelVar expr)
1251+ mkEmptyRelVar (With macros expr) = With (map (\(rv, expr) -> (rv, mkEmptyRelVar expr)) macros) (mkEmptyRelVar expr)
1252+
1253+processAttributeNames :: AttributeNames -> RelationalExprState GraphRefAttributeNames
1254+processAttributeNames (AttributeNames nameSet) = pure $ AttributeNames nameSet
1255+processAttributeNames (UnionAttributeNames attrNamesA attrNamesB) = UnionAttributeNames <$> processAttributeNames attrNamesA <*> processAttributeNames attrNamesB
1256+processAttributeNames (IntersectAttributeNames attrNamesA attrNamesB) = IntersectAttributeNames <$> processAttributeNames attrNamesA <*> processAttributeNames attrNamesB
1257+processAttributeNames (RelationalExprAttributeNames expr) = RelationalExprAttributeNames <$> processRelationalExpr expr
src/lib/ProjectM36/StaticOptimizer.hs+178−219
@@ -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
14
18
19+
20+type StaticOptimizerEnv = RelationalExprEnv
21+
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))
18−
26+
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
24− Right optExpr ->
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
30
36
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
34
40
35−applyStaticRelationalOptimization e@(MakeRelationFromExprs _ _) = pure $ Right e
41+optimizeGraphRefRelationalExpr e@(MakeRelationFromExprs _ _) = pure e
36
42
37−applyStaticRelationalOptimization e@(ExistingRelation _) = pure $ Right e
43+optimizeGraphRefRelationalExpr e@(ExistingRelation _) = pure e
38
44
39−applyStaticRelationalOptimization e@(RelationVariable _ _) = pure $ Right e
45+optimizeGraphRefRelationalExpr e@(RelationVariable _ _) = pure e
40
46
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)
56
61
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
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+ -- (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
70 else
71 else
71− pure $ Right $ Union optExprA optExprB
72+ pure $ Union optExprA optExprB
72
73
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
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
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
87 else
83 else
88− pure (Right (Join optExprA optExprB))
84+ pure (Join optExprA optExprB)
89
85
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)
102− else
95+ else
103− pure $ Right (Difference optExprA2 optExprB2)
96+ pure (Difference optExprA optExprB)
104
97
105−applyStaticRelationalOptimization e@Rename{} = pure $ Right e
98+optimizeGraphRefRelationalExpr e@Rename{} = pure e
106
99
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
109
102
110−applyStaticRelationalOptimization (Ungroup attrName expr) =
103+optimizeGraphRefRelationalExpr (Ungroup attrName expr) =
111− pure $ Right $ Ungroup attrName expr
104+ pure $ Ungroup attrName expr
112
105
113--remove restriction of nothing
106--remove restriction of nothing
114−applyStaticRelationalOptimization (Restrict predicate expr) = do
107+optimizeGraphRefRelationalExpr (Restrict predicate expr) = do
108+ env <- ask
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
130
120
131−applyStaticRelationalOptimization e@(Equals _ _) = pure $ Right e
121+optimizeGraphRefRelationalExpr e@(Equals _ _) = pure e
132
122
133−applyStaticRelationalOptimization e@(NotEquals _ _) = pure $ Right e
123+optimizeGraphRefRelationalExpr e@(NotEquals _ _) = pure e
134
124
135−applyStaticRelationalOptimization e@(Extend _ _) = pure $ Right e
125+optimizeGraphRefRelationalExpr e@(Extend _ _) = pure e
136
126
137−applyStaticRelationalOptimization e@(With _ _) = pure $ Right e
127+optimizeGraphRefRelationalExpr e@(With _ _) = pure e
138
128
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
142
133
143−applyStaticDatabaseOptimization x@(Undefine _) = pure $ Right x
134+optimizeDatabaseContextExpr x@(Undefine _) = pure x
144
135
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)
151
139
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
159− else
144+ else
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)
165
150
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)
172
153
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)
179
156
180−applyStaticDatabaseOptimization dep@(AddInclusionDependency _ _) = pure $ Right dep
157+optimizeDatabaseContextExpr dep@(AddInclusionDependency _ _) = pure dep
181
158
182−applyStaticDatabaseOptimization (RemoveInclusionDependency name) = pure $ Right (RemoveInclusionDependency name)
159+optimizeDatabaseContextExpr (RemoveInclusionDependency name) = pure (RemoveInclusionDependency name)
183
160
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)
191
164
192−applyStaticDatabaseOptimization notif@(RemoveNotification _) = pure (Right notif)
165+optimizeDatabaseContextExpr notif@(RemoveNotification _) = pure notif
193
166
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
199
172
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
201
174
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)
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
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
226− case eOptPred1 of
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
232− Right optPred2 ->
233− if optPred1 == optPred2 then
234− pure (Right optPred1)
235− else
192+ else
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
240− case eOptPred1 of
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
204+ else
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
253 else
209 else
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
260− case eOptPred of
261− Left err -> pure (Left err)
262− Right optPred ->
263− let attrMap = findStaticRestrictionPredicates optPred in
216+ let attrMap = findStaticRestrictionPredicates optPred
264− pure (Right (replaceStaticAtomExprs optPred attrMap))
217+ pure (replaceStaticAtomExprs optPred attrMap)
265
218
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
271
224
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
277
230
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
284
237
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
321
274
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
313+
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))
362 ))
321 ))
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)
371
330
372−applyStaticJoinElimination expr = pure (Right expr)
331+applyStaticJoinElimination expr = pure expr
373
332
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
412
371
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 _ = []
416
375
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
src/lib/ProjectM36/TransGraphRelationalExpression.hs+124−116
@@ -5,12 +5,16 @@ module ProjectM36.TransGraphRelationalExpression where
5import ProjectM36.Base
5import ProjectM36.Base
6import ProjectM36.TransactionGraph
6import ProjectM36.TransactionGraph
7import ProjectM36.Transaction
7import ProjectM36.Transaction
8+import ProjectM36.GraphRefRelationalExpr
8−import ProjectM36.RelationalExpression
9+import ProjectM36.RelationalExpression hiding (liftE)
9import ProjectM36.Error
10import ProjectM36.Error
10import ProjectM36.Tuple
11import ProjectM36.Tuple
11import ProjectM36.AtomType
12import ProjectM36.AtomType
12import qualified Data.Map as M
13import qualified Data.Map as M
13import Control.Monad.Trans.Reader
14import Control.Monad.Trans.Reader
15+import Control.Monad.Trans.Class
16+import Control.Monad.Trans.Except
17+import Data.Functor.Identity
14import Data.Binary
18import Data.Binary
15
19
16-- | The TransGraphRelationalExpression is equivalent to a relational expression except that relation variables can reference points in the transaction graph (at previous points in time).
20-- | The TransGraphRelationalExpression is equivalent to a relational expression except that relation variables can reference points in the transaction graph (at previous points in time).
@@ -40,143 +44,147 @@ instance Binary TransGraphAtomExpr
40
44
41type TransGraphAttributeExpr = AttributeExprBase TransactionIdLookup
45type TransGraphAttributeExpr = AttributeExprBase TransactionIdLookup
42
46
47+data TransGraphEvalEnv = TransGraphEvalEnv { transId :: TransactionId,
48+ graph :: TransactionGraph
49+ }
50+
51+type TransGraphEvalMonad a = ReaderT TransGraphEvalEnv (ExceptT RelationalError Identity) a
52+
53+run :: TransGraphEvalEnv -> TransGraphRelationalExpr -> Either RelationalError GraphRefRelationalExpr
54+run env texpr = runIdentity (runExceptT (runReaderT (evalTransGraphRelationalExpr texpr) env))
55+
56+liftE :: Either RelationalError a -> TransGraphEvalMonad a
57+liftE = lift . except
58+
59+
60+askTid :: TransGraphEvalMonad TransactionId
61+askTid = transId <$> ask
62+
63+askGraph :: TransGraphEvalMonad TransactionGraph
64+askGraph = graph <$> ask
65+
66+findTransId :: TransactionIdLookup -> TransGraphEvalMonad TransactionId
67+findTransId tlook = transactionId <$> findTrans tlook
68+
69+findTrans :: TransactionIdLookup -> TransGraphEvalMonad Transaction
70+findTrans tlook = do
71+ graph <- askGraph
72+ liftE $ lookupTransaction graph tlook
73+
43-- OUTDATED a previous attempt at this function attempted to convert TransGraphRelationalExpr to RelationalExpr by resolving the transaction lookups. However, there is no way to resolve a FunctionAtomExpr to an Atom without fully evaluating the higher levels (TupleExpr, etc.). An anonymous function expression cannot be serialized, so that workaround is out. Still, I suspect we can reuse the existing static optimizer logic to work on both structures. The current conversion reduces the chance of whole-query optimization due to full-evaluation on top of full-evaluation, so this function would benefit from some re-design.
74-- OUTDATED a previous attempt at this function attempted to convert TransGraphRelationalExpr to RelationalExpr by resolving the transaction lookups. However, there is no way to resolve a FunctionAtomExpr to an Atom without fully evaluating the higher levels (TupleExpr, etc.). An anonymous function expression cannot be serialized, so that workaround is out. Still, I suspect we can reuse the existing static optimizer logic to work on both structures. The current conversion reduces the chance of whole-query optimization due to full-evaluation on top of full-evaluation, so this function would benefit from some re-design.
44−evalTransGraphRelationalExpr :: TransGraphRelationalExpr -> TransactionGraph -> Either RelationalError RelationalExpr
75+evalTransGraphRelationalExpr :: TransGraphRelationalExpr -> TransGraphEvalMonad GraphRefRelationalExpr
45−evalTransGraphRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) graph = do
76+evalTransGraphRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do
46− tupleExprs' <- mapM (evalTransGraphTupleExpr graph) tupleExprs
77+ tupleExprs' <- mapM evalTransGraphTupleExpr tupleExprs
47 case mAttrExprs of
78 case mAttrExprs of
48 Nothing -> pure (MakeRelationFromExprs Nothing tupleExprs')
79 Nothing -> pure (MakeRelationFromExprs Nothing tupleExprs')
49 Just attrExprs -> do
80 Just attrExprs -> do
50− attrExprs' <- mapM (evalTransGraphAttributeExpr graph) attrExprs
81+ attrExprs' <- mapM evalTransGraphAttributeExpr attrExprs
51 pure (MakeRelationFromExprs (Just attrExprs') tupleExprs')
82 pure (MakeRelationFromExprs (Just attrExprs') tupleExprs')
52−evalTransGraphRelationalExpr (MakeStaticRelation attrs tupSet) _ = pure (MakeStaticRelation attrs tupSet)
83+evalTransGraphRelationalExpr (MakeStaticRelation attrs tupSet) = pure (MakeStaticRelation attrs tupSet)
53−evalTransGraphRelationalExpr (ExistingRelation rel) _ = pure (ExistingRelation rel)
84+evalTransGraphRelationalExpr (ExistingRelation rel) = pure (ExistingRelation rel)
54−evalTransGraphRelationalExpr (RelationVariable rvname transLookup) graph = do
85+evalTransGraphRelationalExpr (RelationVariable rvname transLookup) =
55− trans <- lookupTransaction graph transLookup
86+ RelationVariable rvname <$> findTransId transLookup
56− rel <- runReader (evalRelationalExpr (RelationVariable rvname ())) (RelationalExprStateElems (concreteDatabaseContext trans))
57− pure (ExistingRelation rel)
58−evalTransGraphRelationalExpr (Project transAttrNames expr) graph = do
87+evalTransGraphRelationalExpr (Project transAttrNames expr) =
59− expr' <- evalTransGraphRelationalExpr expr graph
60− attrNames <- evalTransAttributeNames transAttrNames graph
88+ Project <$> evalTransAttributeNames transAttrNames <*> evalTransGraphRelationalExpr expr
61− pure (Project attrNames expr')
62−evalTransGraphRelationalExpr (Union exprA exprB) graph = do
89+evalTransGraphRelationalExpr (Union exprA exprB) =
63− exprA' <- evalTransGraphRelationalExpr exprA graph
90+ Union <$> evalTransGraphRelationalExpr exprA <*> evalTransGraphRelationalExpr exprB
64− exprB' <- evalTransGraphRelationalExpr exprB graph
65− pure (Union exprA' exprB')
66−evalTransGraphRelationalExpr (Join exprA exprB) graph = do
91+evalTransGraphRelationalExpr (Join exprA exprB) =
67− exprA' <- evalTransGraphRelationalExpr exprA graph
92+ Join <$> evalTransGraphRelationalExpr exprA <*> evalTransGraphRelationalExpr exprB
68− exprB' <- evalTransGraphRelationalExpr exprB graph
69− pure (Join exprA' exprB')
70−evalTransGraphRelationalExpr (Rename attrName1 attrName2 expr) graph = do
93+evalTransGraphRelationalExpr (Rename attrName1 attrName2 expr) =
71− let expr' = evalTransGraphRelationalExpr expr graph
72− Rename attrName1 attrName2 <$> expr'
94+ Rename attrName1 attrName2 <$> evalTransGraphRelationalExpr expr
73−evalTransGraphRelationalExpr (Difference exprA exprB) graph = do
95+evalTransGraphRelationalExpr (Difference exprA exprB) =
74− exprA' <- evalTransGraphRelationalExpr exprA graph
96+ Difference <$> evalTransGraphRelationalExpr exprA <*> evalTransGraphRelationalExpr exprB
75− exprB' <- evalTransGraphRelationalExpr exprB graph
76− pure (Difference exprA' exprB')
77−evalTransGraphRelationalExpr (Group transAttrNames attrName expr) graph = do
97+evalTransGraphRelationalExpr (Group transAttrNames attrName expr) =
78− expr' <- evalTransGraphRelationalExpr expr graph
98+ Group <$>
79− attrNames <- evalTransAttributeNames transAttrNames graph
99+ evalTransAttributeNames transAttrNames <*>
80− pure (Group attrNames attrName expr')
100+ pure attrName <*>
101+ evalTransGraphRelationalExpr expr
81−evalTransGraphRelationalExpr (Ungroup attrName expr) graph = do
102+evalTransGraphRelationalExpr (Ungroup attrName expr) =
82− let expr' = evalTransGraphRelationalExpr expr graph
83− Ungroup attrName <$> expr'
103+ Ungroup attrName <$> evalTransGraphRelationalExpr expr
84−evalTransGraphRelationalExpr (Restrict predicateExpr expr) graph = do
104+evalTransGraphRelationalExpr (Restrict predicateExpr expr) =
85− expr' <- evalTransGraphRelationalExpr expr graph
86− predicateExpr' <- evalTransGraphRestrictionPredicateExpr predicateExpr graph
105+ Restrict <$> evalTransGraphRestrictionPredicateExpr predicateExpr <*>
87− pure (Restrict predicateExpr' expr')
106+ evalTransGraphRelationalExpr expr
88−evalTransGraphRelationalExpr (Equals exprA exprB) graph = do
107+evalTransGraphRelationalExpr (Equals exprA exprB) = do
89− exprA' <- evalTransGraphRelationalExpr exprA graph
108+ exprA' <- evalTransGraphRelationalExpr exprA
90− exprB' <- evalTransGraphRelationalExpr exprB graph
109+ exprB' <- evalTransGraphRelationalExpr exprB
91 pure (Equals exprA' exprB')
110 pure (Equals exprA' exprB')
92−evalTransGraphRelationalExpr (NotEquals exprA exprB) graph = do
111+evalTransGraphRelationalExpr (NotEquals exprA exprB) = do
93− exprA' <- evalTransGraphRelationalExpr exprA graph
112+ exprA' <- evalTransGraphRelationalExpr exprA
94− exprB' <- evalTransGraphRelationalExpr exprB graph
113+ exprB' <- evalTransGraphRelationalExpr exprB
95 pure (NotEquals exprA' exprB')
114 pure (NotEquals exprA' exprB')
96−evalTransGraphRelationalExpr (Extend extendExpr expr) graph = do
115+evalTransGraphRelationalExpr (Extend extendExpr expr) = do
97− extendExpr' <- evalTransGraphExtendTupleExpr extendExpr graph
116+ extendExpr' <- evalTransGraphExtendTupleExpr extendExpr
98− expr' <- evalTransGraphRelationalExpr expr graph
117+ expr' <- evalTransGraphRelationalExpr expr
99 pure (Extend extendExpr' expr')
118 pure (Extend extendExpr' expr')
100−evalTransGraphRelationalExpr (With views expr) graph = do
119+evalTransGraphRelationalExpr (With views expr) = do
101 evaldViews <- mapM (\(vname, vexpr) -> do
120 evaldViews <- mapM (\(vname, vexpr) -> do
102− vexpr' <- evalTransGraphRelationalExpr vexpr graph
121+ vexpr' <- evalTransGraphRelationalExpr vexpr
103 pure (vname, vexpr')
122 pure (vname, vexpr')
104 ) views
123 ) views
105− expr' <- evalTransGraphRelationalExpr expr graph
124+ expr' <- evalTransGraphRelationalExpr expr
106 pure (With evaldViews expr')
125 pure (With evaldViews expr')
107
126
108−evalTransGraphTupleExpr :: TransactionGraph -> TransGraphTupleExpr -> Either RelationalError TupleExpr
127+evalTransGraphTupleExpr :: TransGraphTupleExpr -> TransGraphEvalMonad GraphRefTupleExpr
109−evalTransGraphTupleExpr graph (TupleExpr attrMap) = do
128+evalTransGraphTupleExpr (TupleExpr attrMap) = do
129+ graph <- askGraph
110 let attrAssoc = mapM (\(attrName, atomExpr) -> do
130 let attrAssoc = mapM (\(attrName, atomExpr) -> do
111− aExpr <- evalTransGraphAtomExpr graph atomExpr
131+ aExpr <- evalTransGraphAtomExpr atomExpr
112 pure (attrName, aExpr)
132 pure (attrName, aExpr)
113 ) (M.toList attrMap)
133 ) (M.toList attrMap)
114 TupleExpr . M.fromList <$> attrAssoc
134 TupleExpr . M.fromList <$> attrAssoc
115
135
116−evalTransGraphAtomExpr :: TransactionGraph -> TransGraphAtomExpr -> Either RelationalError AtomExpr
136+evalTransGraphAtomExpr :: TransGraphAtomExpr -> TransGraphEvalMonad GraphRefAtomExpr
117−evalTransGraphAtomExpr _ (AttributeAtomExpr aname) = pure $ AttributeAtomExpr aname
137+evalTransGraphAtomExpr (AttributeAtomExpr aname) = pure $ AttributeAtomExpr aname
118−evalTransGraphAtomExpr _ (NakedAtomExpr atom) = pure $ NakedAtomExpr atom
138+evalTransGraphAtomExpr (NakedAtomExpr atom) = pure $ NakedAtomExpr atom
119−evalTransGraphAtomExpr graph (FunctionAtomExpr funcName args tLookup) = do
139+evalTransGraphAtomExpr (FunctionAtomExpr funcName args tLookup) =
120− trans <- lookupTransaction graph tLookup
121− --I can't return a FunctionAtomExpr because the function needs to be resolved at a specific context
122− args' <- mapM (evalTransGraphAtomExpr graph) args
140+ FunctionAtomExpr funcName <$> mapM evalTransGraphAtomExpr args <*> findTransId tLookup
123− atom <- runReader (evalAtomExpr emptyTuple (FunctionAtomExpr funcName args' ())) (RelationalExprStateElems (concreteDatabaseContext trans))
124− pure (NakedAtomExpr atom)
125−evalTransGraphAtomExpr graph (RelationAtomExpr expr) = do
141+evalTransGraphAtomExpr (RelationAtomExpr expr) =
126− let expr' = evalTransGraphRelationalExpr expr graph
142+ RelationAtomExpr <$> evalTransGraphRelationalExpr expr
127− RelationAtomExpr <$> expr'
128−evalTransGraphAtomExpr graph (ConstructedAtomExpr dConsName args tLookup) = do
143+evalTransGraphAtomExpr (ConstructedAtomExpr dConsName args tLookup) =
129− trans <- lookupTransaction graph tLookup
130− args' <- mapM (evalTransGraphAtomExpr graph) args
144+ ConstructedAtomExpr dConsName <$> mapM evalTransGraphAtomExpr args <*> findTransId tLookup
131− atom <- runReader (evalAtomExpr emptyTuple (ConstructedAtomExpr dConsName args' ())) (RelationalExprStateElems (concreteDatabaseContext trans))
132− pure (NakedAtomExpr atom)
133−
134−evalTransGraphRestrictionPredicateExpr :: TransGraphRestrictionPredicateExpr -> TransactionGraph -> Either RelationalError RestrictionPredicateExpr
145+evalTransGraphRestrictionPredicateExpr :: TransGraphRestrictionPredicateExpr -> TransGraphEvalMonad GraphRefRestrictionPredicateExpr
135−evalTransGraphRestrictionPredicateExpr TruePredicate _ = pure TruePredicate
146+evalTransGraphRestrictionPredicateExpr TruePredicate = pure TruePredicate
136−evalTransGraphRestrictionPredicateExpr (AndPredicate exprA exprB) graph = do
147+evalTransGraphRestrictionPredicateExpr (AndPredicate exprA exprB) = do
137− exprA' <- evalTransGraphRestrictionPredicateExpr exprA graph
148+ exprA' <- evalTransGraphRestrictionPredicateExpr exprA
138− exprB' <- evalTransGraphRestrictionPredicateExpr exprB graph
149+ exprB' <- evalTransGraphRestrictionPredicateExpr exprB
139 pure (AndPredicate exprA' exprB')
150 pure (AndPredicate exprA' exprB')
140−evalTransGraphRestrictionPredicateExpr (OrPredicate exprA exprB) graph = do
151+evalTransGraphRestrictionPredicateExpr (OrPredicate exprA exprB) = do
141− exprA' <- evalTransGraphRestrictionPredicateExpr exprA graph
152+ exprA' <- evalTransGraphRestrictionPredicateExpr exprA
142− exprB' <- evalTransGraphRestrictionPredicateExpr exprB graph
153+ exprB' <- evalTransGraphRestrictionPredicateExpr exprB
143 pure (OrPredicate exprA' exprB')
154 pure (OrPredicate exprA' exprB')
144−evalTransGraphRestrictionPredicateExpr (NotPredicate expr) graph = do
155+evalTransGraphRestrictionPredicateExpr (NotPredicate expr) = do
145− let expr' = evalTransGraphRestrictionPredicateExpr expr graph
156+ let expr' = evalTransGraphRestrictionPredicateExpr expr
146 NotPredicate <$> expr'
157 NotPredicate <$> expr'
147−evalTransGraphRestrictionPredicateExpr (RelationalExprPredicate expr) graph = do
158+evalTransGraphRestrictionPredicateExpr (RelationalExprPredicate expr) = do
148− let expr' = evalTransGraphRelationalExpr expr graph
159+ let expr' = evalTransGraphRelationalExpr expr
149 RelationalExprPredicate <$> expr'
160 RelationalExprPredicate <$> expr'
150−evalTransGraphRestrictionPredicateExpr (AtomExprPredicate expr) graph = do
161+evalTransGraphRestrictionPredicateExpr (AtomExprPredicate expr) = do
151− let expr' = evalTransGraphAtomExpr graph expr
162+ let expr' = evalTransGraphAtomExpr expr
152 AtomExprPredicate <$> expr'
163 AtomExprPredicate <$> expr'
153−evalTransGraphRestrictionPredicateExpr (AttributeEqualityPredicate attrName expr) graph = do
164+evalTransGraphRestrictionPredicateExpr (AttributeEqualityPredicate attrName expr) = do
154− let expr' = evalTransGraphAtomExpr graph expr
165+ let expr' = evalTransGraphAtomExpr expr
155 AttributeEqualityPredicate attrName <$> expr'
166 AttributeEqualityPredicate attrName <$> expr'
156
167
157−evalTransGraphExtendTupleExpr :: TransGraphExtendTupleExpr -> TransactionGraph -> Either RelationalError ExtendTupleExpr
168+evalTransGraphExtendTupleExpr :: TransGraphExtendTupleExpr -> TransGraphEvalMonad GraphRefExtendTupleExpr
158−evalTransGraphExtendTupleExpr (AttributeExtendTupleExpr attrName expr) graph = do
169+evalTransGraphExtendTupleExpr (AttributeExtendTupleExpr attrName expr) = do
159− let expr' = evalTransGraphAtomExpr graph expr
170+ AttributeExtendTupleExpr attrName <$> evalTransGraphAtomExpr expr
160− AttributeExtendTupleExpr attrName <$> expr'
171+
161−
162−evalTransGraphAttributeExpr :: TransactionGraph -> TransGraphAttributeExpr -> Either RelationalError AttributeExpr
172+evalTransGraphAttributeExpr :: TransGraphAttributeExpr -> TransGraphEvalMonad GraphRefAttributeExpr
163−evalTransGraphAttributeExpr graph (AttributeAndTypeNameExpr attrName tCons tLookup) = do
173+evalTransGraphAttributeExpr (AttributeAndTypeNameExpr attrName tCons tLookup) =
164− trans <- lookupTransaction graph tLookup
174+ AttributeAndTypeNameExpr attrName tCons <$> findTransId tLookup
165− aType <- atomTypeForTypeConstructor tCons (typeConstructorMapping (concreteDatabaseContext trans)) M.empty
166− pure (NakedAttributeExpr (Attribute attrName aType))
167−evalTransGraphAttributeExpr _ (NakedAttributeExpr attr) = pure (NakedAttributeExpr attr)
175+evalTransGraphAttributeExpr (NakedAttributeExpr attr) = pure (NakedAttributeExpr attr)
168−
176+
169−evalTransAttributeNames :: TransGraphAttributeNames -> TransactionGraph -> Either RelationalError AttributeNames
177+evalTransAttributeNames :: TransGraphAttributeNames -> TransGraphEvalMonad GraphRefAttributeNames
170−evalTransAttributeNames (AttributeNames names) _ = Right (AttributeNames names)
178+evalTransAttributeNames (AttributeNames names) = pure (AttributeNames names)
171−evalTransAttributeNames (InvertedAttributeNames names) _ = Right (InvertedAttributeNames names)
179+evalTransAttributeNames (InvertedAttributeNames names) = pure (InvertedAttributeNames names)
172−evalTransAttributeNames (UnionAttributeNames namesA namesB) graph = do
180+evalTransAttributeNames (UnionAttributeNames namesA namesB) = do
173− nA <- evalTransAttributeNames namesA graph
181+ nA <- evalTransAttributeNames namesA
174− nB <- evalTransAttributeNames namesB graph
182+ nB <- evalTransAttributeNames namesB
175− Right (UnionAttributeNames nA nB)
183+ pure (UnionAttributeNames nA nB)
176−evalTransAttributeNames (IntersectAttributeNames namesA namesB) graph = do
184+evalTransAttributeNames (IntersectAttributeNames namesA namesB) = do
177− nA <- evalTransAttributeNames namesA graph
185+ nA <- evalTransAttributeNames namesA
178− nB <- evalTransAttributeNames namesB graph
186+ nB <- evalTransAttributeNames namesB
179− Right (IntersectAttributeNames nA nB)
187+ pure (IntersectAttributeNames nA nB)
180−evalTransAttributeNames (RelationalExprAttributeNames expr) graph = do
188+evalTransAttributeNames (RelationalExprAttributeNames expr) = do
181− evaldExpr <- evalTransGraphRelationalExpr expr graph
189+ evaldExpr <- evalTransGraphRelationalExpr expr
182− Right (RelationalExprAttributeNames evaldExpr)
190+ pure (RelationalExprAttributeNames evaldExpr)
src/lib/ProjectM36/Transaction/Type.hsnew file+8
@@ -0,0 +1,8 @@
1+module ProjectM36.Transaction where
2+import ProjectM36.Base
3+
4+uid :: Transaction -> TransactionId
5+uid (Transaction uid _ _) = uid
6+
7+info :: Transaction -> TransactionInfo
8+info (Transaction _ info _) = info
src/lib/ProjectM36/TransactionGraph.hs+17−19
@@ -3,6 +3,7 @@ module ProjectM36.TransactionGraph where
3import ProjectM36.Base
3import ProjectM36.Base
4import ProjectM36.Error
4import ProjectM36.Error
5import ProjectM36.Transaction
5import ProjectM36.Transaction
6+import ProjectM36.TransactionInfo as TI
6import ProjectM36.Relation
7import ProjectM36.Relation
7import ProjectM36.TupleSet
8import ProjectM36.TupleSet
8import ProjectM36.Tuple
9import ProjectM36.Tuple
@@ -94,7 +95,7 @@ transactionsForIds idSet graph =
94
95
95-- | A root transaction terminates a graph and has no parents.
96-- | A root transaction terminates a graph and has no parents.
96isRootTransaction :: Transaction -> Bool
97isRootTransaction :: Transaction -> Bool
97−isRootTransaction trans = parentTransactions == nil :| []
98+isRootTransaction trans = parentIds trans == S.singleton U.nil
98
99
99-- the first transaction has no parent - all other do have parents- merges have two parents
100-- the first transaction has no parent - all other do have parents- merges have two parents
100parentTransactions :: Transaction -> TransactionGraph -> Either RelationalError (S.Set Transaction)
101parentTransactions :: Transaction -> TransactionGraph -> Either RelationalError (S.Set Transaction)
@@ -111,19 +112,14 @@ childTransactions trans graph = transactionsForIds childIds graph
111addBranch :: UTCTime -> TransactionId -> HeadName -> TransactionId -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
112addBranch :: UTCTime -> TransactionId -> HeadName -> TransactionId -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
112addBranch stamp' newId newBranchName branchPointId graph = do
113addBranch stamp' newId newBranchName branchPointId graph = do
113 parentTrans <- transactionForId branchPointId graph
114 parentTrans <- transactionForId branchPointId graph
114− let newTrans = Transaction newId (TransactionInfo {
115+ let newTrans = Transaction newId (TI.singleParent branchPointId stamp') (schemas parentTrans)
115− parents = TD.single branchPointId NoOperation,
116− stamp = stamp'}) (schemas parentTrans)
117 addTransactionToGraph newBranchName newTrans graph
116 addTransactionToGraph newBranchName newTrans graph
118
117
119--adds a disconnected transaction to a transaction graph at some head
118--adds a disconnected transaction to a transaction graph at some head
120addDisconnectedTransaction :: UTCTime -> TransactionId -> HeadName -> DisconnectedTransaction -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
119addDisconnectedTransaction :: UTCTime -> TransactionId -> HeadName -> DisconnectedTransaction -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
121addDisconnectedTransaction stamp' newId headName discon@(DisconnectedTransaction parentId schemas' _) = addTransactionToGraph headName newTrans
120addDisconnectedTransaction stamp' newId headName discon@(DisconnectedTransaction parentId schemas' _) = addTransactionToGraph headName newTrans
122 where
121 where
123− newTrans = Transaction newId (TransactionInfo {
122+ newTrans = Transaction newId (TI.singleParent parentId stamp') schemas'
124− parents = TD.single parentId (Discon.diffExpr discon),
125− stamp = stamp'}) schemas'
126−
127
123
128addTransactionToGraph :: HeadName -> Transaction -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
124addTransactionToGraph :: HeadName -> Transaction -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
129addTransactionToGraph headName newTrans graph = do
125addTransactionToGraph headName newTrans graph = do
@@ -314,8 +310,8 @@ createMergeTransaction :: UTCTime -> TransactionId -> MergeStrategy -> Transacti
314createMergeTransaction stamp' newId (SelectedBranchMergeStrategy selectedBranch) graph t2@(trans1, trans2) = do
310createMergeTransaction stamp' newId (SelectedBranchMergeStrategy selectedBranch) graph t2@(trans1, trans2) = do
315 let selectedTrans = validateHeadName selectedBranch graph t2
311 let selectedTrans = validateHeadName selectedBranch graph t2
316 Transaction newId (TransactionInfo {
312 Transaction newId (TransactionInfo {
317− parents = NE.fromList [(transactionId trans1, undefined),
313+ parents = NE.fromList [transactionId trans1,
318− (transactionId trans2, undefined)],
314+ transactionId trans2],
319 stamp = stamp' }) . schemas <$> selectedTrans
315 stamp = stamp' }) . schemas <$> selectedTrans
320
316
321-- merge functions, relvars, individually
317-- merge functions, relvars, individually
@@ -362,7 +358,7 @@ subGraphOfFirstCommonAncestor origGraph resultHeads currentTrans goalTrans trave
362 else -- we found a path
358 else -- we found a path
363 Right (TransactionGraph resultHeads (S.unions (traverseSet : pathsFound)))
359 Right (TransactionGraph resultHeads (S.unions (traverseSet : pathsFound)))
364 where
360 where
365− oneParent (Transaction _ tinfo _) = transactionForId (fst (NE.head (parents tinfo))) origGraph
361+ oneParent (Transaction _ tinfo _) = transactionForId (NE.head (parents tinfo)) origGraph
366
362
367-- | Search from a past graph point to all following heads for a specific transaction. If found, return the transaction path, otherwise a RelationalError.
363-- | Search from a past graph point to all following heads for a specific transaction. If found, return the transaction path, otherwise a RelationalError.
368pathToTransaction :: TransactionGraph -> Transaction -> Transaction -> S.Set Transaction -> Either RelationalError (S.Set Transaction)
364pathToTransaction :: TransactionGraph -> Transaction -> Transaction -> S.Set Transaction -> Either RelationalError (S.Set Transaction)
@@ -398,15 +394,17 @@ mergeTransactions stamp' newId parentId mergeStrategy (headNameA, headNameB) gra
398 subGraph' <- filterSubGraph subGraph subHeads
394 subGraph' <- filterSubGraph subGraph subHeads
399 case createMergeTransaction stamp' newId mergeStrategy subGraph' (transA, transB) of
395 case createMergeTransaction stamp' newId mergeStrategy subGraph' (transA, transB) of
400 Left err -> Left (MergeTransactionError err)
396 Left err -> Left (MergeTransactionError err)
401− Right mergedTrans -> case checkConstraints (concreteDatabaseContext mergedTrans) of
397+ Right mergedTrans ->
402− Left err -> Left err
403− Right _ -> case headNameForTransaction disconParent graph of
398+ case headNameForTransaction disconParent graph of
404 Nothing -> Left (TransactionIsNotAHeadError parentId)
399 Nothing -> Left (TransactionIsNotAHeadError parentId)
405 Just headName -> do
400 Just headName -> do
406 (newTrans, newGraph) <- addTransactionToGraph headName mergedTrans graph
401 (newTrans, newGraph) <- addTransactionToGraph headName mergedTrans graph
402+ case checkConstraints (concreteDatabaseContext mergedTrans) newId graph of
403+ Left err -> Left err
404+ Right _ -> do
407− let newGraph' = TransactionGraph (transactionHeadsForGraph newGraph) (transactionsForGraph newGraph)
405+ let newGraph' = TransactionGraph (transactionHeadsForGraph newGraph) (transactionsForGraph newGraph)
408− newDiscon = Discon.freshTransaction newId (schemas newTrans)
406+ newDiscon = Discon.freshTransaction newId (schemas newTrans)
409− pure (newDiscon, newGraph')
407+ pure (newDiscon, newGraph')
410
408
411--TEMPORARY COPY/PASTE
409--TEMPORARY COPY/PASTE
412showTransactionStructureX :: Transaction -> TransactionGraph -> String
410showTransactionStructureX :: Transaction -> TransactionGraph -> String
@@ -462,8 +460,8 @@ createUnionMergeTransaction stamp' newId strategy graph (t1,t2) = do
462 }
460 }
463 newSchemas = Schemas newContext (subschemas t1)
461 newSchemas = Schemas newContext (subschemas t1)
464 pure (Transaction newId (TransactionInfo {
462 pure (Transaction newId (TransactionInfo {
465− parents = NE.fromList [(transactionId t1, undefined),
463+ parents = NE.fromList [transactionId t1,
466− (transactionId t2, undefined)],
464+ transactionId t2],
467 stamp = stamp'}) newSchemas)
465 stamp = stamp'}) newSchemas)
468
466
469lookupTransaction :: TransactionGraph -> TransactionIdLookup -> Either RelationalError Transaction
467lookupTransaction :: TransactionGraph -> TransactionIdLookup -> Either RelationalError Transaction
src/lib/ProjectM36/TransactionGraph/Persist.hs+1
@@ -3,6 +3,7 @@ import ProjectM36.Error
3import ProjectM36.TransactionGraph
3import ProjectM36.TransactionGraph
4import ProjectM36.Transaction
4import ProjectM36.Transaction
5import ProjectM36.Transaction.Persist
5import ProjectM36.Transaction.Persist
6+import ProjectM36.RelationalExpression
6import ProjectM36.Base
7import ProjectM36.Base
7import ProjectM36.ScriptSession
8import ProjectM36.ScriptSession
8import ProjectM36.Persist (writeFileSync, renameSync, DiskSync)
9import ProjectM36.Persist (writeFileSync, renameSync, DiskSync)
src/lib/ProjectM36/TransactionInfo.hs+8−16
@@ -1,19 +1,11 @@
1module ProjectM36.TransactionInfo where
1module ProjectM36.TransactionInfo where
2import ProjectM36.Base
2import ProjectM36.Base
3import qualified Data.Set as S
3import qualified Data.Set as S
4−import Data.Time.Clock.POSIX
4+import Data.Time.Clock
5−
5+import Data.List.NonEmpty
6−parentTids :: TransactionInfo -> S.Set TransactionId
6+
7−parentTids (TransactionInfo tid _ _) = S.singleton tid
7+-- | Create a TransactionInfo with just one parent transaction ID.
8−parentTids (MergeTransactionInfo tid1 tid2 _ _) = S.fromList [tid1, tid2]
8+singleParent :: TransactionId -> UTCTime -> TransactionInfo
9−
9+singleParent tid stamp = TransactionInfo {
10−diffs :: TransactionInfo -> TransactionDiffs
10+ parents = tid :| [],
11−diffs (TransactionInfo _ diffs _) = diffs
11+ stamp = stamp }
12−diffs (MergeTransactionInfo _ _ diffs _) = diffs
13−
14−children :: TransactionInfo -> S.Set TransactionId
15−children ti = S.fromList (map snd (diffs ti))
16−
17−stamp :: TransactionInfo -> UTCTime
18−stamp (TransactionInfo _ _ t) = t
19−stamp (MergeTransactionInfo _ _ _ t) = t