@@ -16,13 +16,14 @@ import qualified ProjectM36.Attribute as A
1616import qualified Data.UUID as U
1717import qualified Data.Set as S
1818import qualified Data.Map as M
19+import qualified Data.List.NonEmpty as NE
1920import Control.Monad
2021import Data.Time.Clock
2122import qualified Data.Text as T
2223import GHC.Generics
2324import Data.Binary
2425import Data.Either (lefts, rights, isRight)
25−import Data.Monoid
26+--import Data.Monoid
2627import Control.Arrow
2728import Data.Maybe
2829
@@ -63,11 +64,11 @@ data ROTransactionGraphOperator = ShowGraph
6364 deriving Show
6465
6566bootstrapTransactionGraph :: UTCTime -> TransactionId -> DatabaseContext -> TransactionGraph
66−bootstrapTransactionGraph stamp freshId context = TransactionGraph bootstrapHeads bootstrapTransactions
67+bootstrapTransactionGraph stamp' freshId context = TransactionGraph bootstrapHeads bootstrapTransactions
6768 where
6869 bootstrapHeads = M.singleton "master" freshTransaction
6970 newSchemas = Schemas context M.empty
70− freshTransaction = Transaction freshId (TransactionInfo U.nil TD.empty stamp) newSchemas
71+ freshTransaction = fresh freshId stamp' newSchemas
7172 bootstrapTransactions = S.singleton freshTransaction
7273
7374emptyTransactionGraph :: TransactionGraph
@@ -108,57 +109,58 @@ transactionsForIds :: S.Set TransactionId -> TransactionGraph -> Either Relation
108109transactionsForIds idSet graph =
109110 S.fromList <$> forM (S.toList idSet) (`transactionForId` graph)
110111
111−isRootTransaction :: Transaction -> TransactionGraph -> Bool
112−isRootTransaction (Transaction _ (TransactionInfo pId _ _) _) _ = U.null pId
113−isRootTransaction (Transaction _ MergeTransactionInfo{} _) _ = False
112+-- | A root transaction terminates a graph and has no parents.
113+isRootTransaction :: Transaction -> Bool
114+isRootTransaction trans = diffs trans == TD.root
114115
115116-- the first transaction has no parent - all other do have parents- merges have two parents
116117parentTransactions :: Transaction -> TransactionGraph -> Either RelationalError (S.Set Transaction)
117−parentTransactions (Transaction _ (TransactionInfo pId _ _) _) graph =
118− S.singleton <$> transactionForId pId graph
119−
120−
121−parentTransactions (Transaction _ (MergeTransactionInfo pId1 pId2 _ _) _ ) graph = transactionsForIds (S.fromList [pId1, pId2]) graph
122−
118+parentTransactions trans graph = transactionsForIds (parentIds trans) graph
123119
124120childTransactions :: Transaction -> TransactionGraph -> Either RelationalError (S.Set Transaction)
125−childTransactions trans = transactionsForIds (transactionChildIds trans)
121+childTransactions trans graph = transactionsForIds childIds graph
122+ where
123+ childIds = S.map transactionId (S.filter filt (transactionsForGraph graph))
124+ filt trans' = S.member (transactionId trans) (parentIds trans')
126125
127126-- create a new commit and add it to the heads
128127-- technically, the new head could be added to an existing commit, but by adding a new commit, the new head is unambiguously linked to a new commit (with a context indentical to its parent)
129128addBranch :: UTCTime -> TransactionId -> HeadName -> TransactionId -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
130−addBranch stamp newId newBranchName branchPointId graph = do
129+addBranch stamp' newId newBranchName branchPointId graph = do
131130 parentTrans <- transactionForId branchPointId graph
132− let newTrans = Transaction newId (TransactionInfo branchPointId TD.empty stamp) (schemas parentTrans)
133− addTransactionToGraph newBranchName newTrans [(newId, NoOperation)] graph
131+ let newTrans = Transaction newId (TransactionInfo {
132+ parents = TD.single branchPointId NoOperation,
133+ stamp = stamp'}) (schemas parentTrans)
134+ addTransactionToGraph newBranchName newTrans graph
134135
135136--adds a disconnected transaction to a transaction graph at some head
136137addDisconnectedTransaction :: UTCTime -> TransactionId -> HeadName -> DisconnectedTransaction -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
137−addDisconnectedTransaction stamp newId headName discon@(DisconnectedTransaction parentId schemas' _) = addTransactionToGraph headName (Transaction newId (TransactionInfo parentId TD.empty stamp) schemas') [(newId, Discon.diffExpr discon)]
138+addDisconnectedTransaction stamp' newId headName discon@(DisconnectedTransaction parentId schemas' _) = addTransactionToGraph headName newTrans
139+ where
140+ newTrans = Transaction newId (TransactionInfo {
141+ parents = TD.single parentId (Discon.diffExpr discon),
142+ stamp = stamp'}) schemas'
138143
139144
140−addTransactionToGraph :: HeadName -> Transaction -> TransactionDiffs -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
141−addTransactionToGraph headName newTrans transDiffs graph = do
142− let parentIds = transactionParentIds newTrans
143− childIds = transactionChildIds newTrans
145+addTransactionToGraph :: HeadName -> Transaction -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
146+addTransactionToGraph headName newTrans graph = do
147+ let parentIds' = parentIds newTrans
144148 newId = transactionId newTrans
145149 validateIds ids = mapM (`transactionForId` graph) (S.toList ids)
146− addChildTransaction trans = transactionSetChildren trans (transDiffs ++ diffs trans)
150+ childTs <- childTransactions newTrans graph
147151 --validate that the parent transactions are in the graph
148− _ <- validateIds parentIds
149− when (S.size parentIds < 1) (Left $ NewTransactionMissingParentError newId)
152+ _ <- validateIds parentIds'
153+ when (S.size parentIds' < 1) (Left $ NewTransactionMissingParentError newId)
150154 --if the headName already exists, ensure that it refers to a parent
151155 case transactionForHead headName graph of
152156 Nothing -> pure () -- any headName is OK
153− Just trans -> when (S.notMember (transactionId trans) parentIds) (Left (HeadNameSwitchingHeadProhibitedError headName))
157+ Just trans -> when (S.notMember (transactionId trans) parentIds') (Left (HeadNameSwitchingHeadProhibitedError headName))
154158 --validate that the transaction has no children
155− unless (S.null childIds) (Left $ NewTransactionMayNotHaveChildrenError newId)
159+ unless (S.null childTs) (Left $ NewTransactionMayNotHaveChildrenError newId)
156160 --validate that the trasaction's id is unique
157161 when (isRight (transactionForId newId graph)) (Left (TransactionIdInUseError newId))
158− --update the parent transactions to point to the new transaction
159− parents <- mapM (`transactionForId` graph) (S.toList parentIds)
160− let updatedParents = S.map addChildTransaction (S.fromList parents)
161− updatedTransSet = S.insert newTrans (S.union updatedParents (transactionsForGraph graph))
162+
163+ let updatedTransSet = S.insert newTrans (transactionsForGraph graph)
162164 updatedHeads = M.insert headName newTrans (transactionHeadsForGraph graph)
163165 pure (newTrans, TransactionGraph updatedHeads updatedTransSet)
164166
@@ -250,15 +252,15 @@ evalGraphOp newId discon@(DisconnectedTransaction parentId disconContext) graph
250252
251253-- create a new commit and add it to the heads
252254-- technically, the new head could be added to an existing commit, but by adding a new commit, the new head is unambiguously linked to a new commit (with a context indentical to its parent)
253−evalGraphOp stamp newId (DisconnectedTransaction parentId schemas' _) graph (Branch newBranchName) = do
255+evalGraphOp stamp' newId (DisconnectedTransaction parentId schemas' _) graph (Branch newBranchName) = do
254256 let newDiscon = Discon.freshTransaction newId schemas'
255− case addBranch stamp newId newBranchName parentId graph of
257+ case addBranch stamp' newId newBranchName parentId graph of
256258 Left err -> Left err
257259 Right (_, newGraph) -> Right (newDiscon, newGraph)
258260
259261-- add the disconnected transaction to the graph
260262-- affects graph and disconnectedtransaction- the new disconnectedtransaction's parent is the freshly committed transaction
261−evalGraphOp stamp newTransId discon@(DisconnectedTransaction parentId schemas' _) graph Commit = case transactionForId parentId graph of
263+evalGraphOp stamp' newTransId discon@(DisconnectedTransaction parentId schemas' _) graph Commit = case transactionForId parentId graph of
262264 Left err -> Left err
263265 Right parentTransaction -> case headNameForTransaction parentTransaction graph of
264266 Nothing -> Left $ TransactionIsNotAHeadError parentId
@@ -267,7 +269,7 @@ evalGraphOp stamp newTransId discon@(DisconnectedTransaction parentId schemas' _
267269 Right (_, updatedGraph) -> Right (newDisconnectedTrans, updatedGraph)
268270 where
269271 newDisconnectedTrans = Discon.freshTransaction newTransId schemas'
270− maybeUpdatedGraph = addDisconnectedTransaction stamp newTransId headName discon graph
272+ maybeUpdatedGraph = addDisconnectedTransaction stamp' newTransId headName discon graph
271273
272274-- refresh the disconnected transaction, return the same graph
273275evalGraphOp _ _ (DisconnectedTransaction parentId _ _) graph Rollback = case transactionForId parentId graph of
@@ -276,7 +278,7 @@ evalGraphOp _ _ (DisconnectedTransaction parentId _ _) graph Rollback = case tra
276278 where
277279 newDiscon = Discon.freshTransaction parentId (schemas parentTransaction)
278280
279−evalGraphOp stamp newId (DisconnectedTransaction parentId _ _) graph (MergeTransactions mergeStrategy headNameA headNameB) = mergeTransactions stamp newId parentId mergeStrategy (headNameA, headNameB) graph
281+evalGraphOp stamp' newId (DisconnectedTransaction parentId _ _) graph (MergeTransactions mergeStrategy headNameA headNameB) = mergeTransactions stamp' newId parentId mergeStrategy (headNameA, headNameB) graph
280282
281283evalGraphOp _ _ discon graph@(TransactionGraph graphHeads transSet) (DeleteBranch branchName) = case transactionForHead branchName graph of
282284 Nothing -> Left (NoSuchHeadNameError branchName)
@@ -298,7 +300,7 @@ graphAsRelation (DisconnectedTransaction parentId _ _) graph@(TransactionGraph _
298300 tupleGenerator transaction = case transactionParentsRelation transaction graph of
299301 Left err -> Left err
300302 Right parentTransRel -> Right [TextAtom $ T.pack $ show (transactionId transaction),
301− DateTimeAtom (transactionTimestamp transaction),
303+ DateTimeAtom (timestamp transaction),
302304 RelationAtom parentTransRel,
303305 BoolAtom $ parentId == transactionId transaction,
304306 TextAtom $ fromMaybe "" (headNameForTransaction transaction graph)
@@ -306,7 +308,7 @@ graphAsRelation (DisconnectedTransaction parentId _ _) graph@(TransactionGraph _
306308
307309transactionParentsRelation :: Transaction -> TransactionGraph -> Either RelationalError Relation
308310transactionParentsRelation trans graph =
309− if isRootTransaction trans graph then
311+ if isRootTransaction trans then
310312 mkRelation attrs emptyTupleSet
311313 else do
312314 parentTransSet <- parentTransactions trans graph
@@ -326,15 +328,18 @@ evalROGraphOp discon graph ShowGraph = do
326328
327329-- | Execute the merge strategy against the transactions, returning a new transaction which can be then added to the transaction graph
328330createMergeTransaction :: UTCTime -> TransactionId -> MergeStrategy -> TransactionGraph -> (Transaction, Transaction) -> Either MergeError Transaction
329−createMergeTransaction stamp newId (SelectedBranchMergeStrategy selectedBranch) graph t2@(trans1, trans2) = do
331+createMergeTransaction stamp' newId (SelectedBranchMergeStrategy selectedBranch) graph t2@(trans1, trans2) = do
330332 let selectedTrans = validateHeadName selectedBranch graph t2
331− Transaction newId (MergeTransactionInfo (transactionId trans1) (transactionId trans2) TD.empty stamp) . schemas <$> selectedTrans
333+ Transaction newId (TransactionInfo {
334+ parents = NE.fromList [(transactionId trans1, undefined),
335+ (transactionId trans2, undefined)],
336+ stamp = stamp' }) . schemas <$> selectedTrans
332337
333338-- merge functions, relvars, individually
334−createMergeTransaction stamp newId strat@UnionMergeStrategy graph t2 = createUnionMergeTransaction stamp newId strat graph t2
339+createMergeTransaction stamp' newId strat@UnionMergeStrategy graph t2 = createUnionMergeTransaction stamp' newId strat graph t2
335340
336341-- merge function, relvars, but, on error, just take the component from the preferred branch
337−createMergeTransaction stamp newId strat@(UnionPreferMergeStrategy _) graph t2 = createUnionMergeTransaction stamp newId strat graph t2
342+createMergeTransaction stamp' newId strat@(UnionPreferMergeStrategy _) graph t2 = createUnionMergeTransaction stamp' newId strat graph t2
338343
339344-- | Returns the correct Transaction for the branch name in the graph and ensures that it is one of the two transaction arguments in the tuple.
340345validateHeadName :: HeadName -> TransactionGraph -> (Transaction, Transaction) -> Either MergeError Transaction
@@ -355,7 +360,7 @@ subGraphOfFirstCommonAncestor origGraph resultHeads currentTrans goalTrans trave
355360 Right (TransactionGraph resultHeads traverseSet) -- add filter
356361 --catch root transaction to improve error?
357362 else do
358− currentTransChildren <- S.fromList <$> mapM (`transactionForId` origGraph) (S.toList (transactionChildIds currentTrans))
363+ currentTransChildren <- childTransactions currentTrans origGraph
359364 let searchChildren = S.difference (S.insert currentTrans traverseSet) currentTransChildren
360365 searchChild start = pathToTransaction origGraph start goalTrans (S.insert currentTrans traverseSet)
361366 childSearches = map searchChild (S.toList searchChildren)
@@ -374,9 +379,8 @@ subGraphOfFirstCommonAncestor origGraph resultHeads currentTrans goalTrans trave
374379 else -- we found a path
375380 Right (TransactionGraph resultHeads (S.unions (traverseSet : pathsFound)))
376381 where
377− oneParent (Transaction _ (TransactionInfo parentId _ _) _) = transactionForId parentId origGraph
378− oneParent (Transaction _ (MergeTransactionInfo parentId _ _ _) _) = transactionForId parentId origGraph
379−
382+ oneParent (Transaction _ tinfo _) = transactionForId (fst (NE.head (parents tinfo))) origGraph
383+
380384-- | Search from a past graph point to all following heads for a specific transaction. If found, return the transaction path, otherwise a RelationalError.
381385pathToTransaction :: TransactionGraph -> Transaction -> Transaction -> S.Set Transaction -> Either RelationalError (S.Set Transaction)
382386pathToTransaction graph currentTransaction targetTransaction accumTransSet = do
@@ -384,11 +388,11 @@ pathToTransaction graph currentTransaction targetTransaction accumTransSet = do
384388 if transactionId targetTransaction == transactionId currentTransaction then
385389 Right accumTransSet
386390 else do
387− currentTransChildren <- mapM (`transactionForId` graph) (S.toList (transactionChildIds currentTransaction))
391+ currentTransChildren <- childTransactions currentTransaction graph
388392 if null currentTransChildren then
389393 Left (FailedToFindTransactionError targetId)
390394 else do
391− let searches = map (\t -> pathToTransaction graph t targetTransaction (S.insert t accumTransSet)) currentTransChildren
395+ let searches = map (\t -> pathToTransaction graph t targetTransaction (S.insert t accumTransSet)) (S.toList currentTransChildren)
392396 let realErrors = filter (/= FailedToFindTransactionError targetId) (lefts searches)
393397 paths = rights searches
394398 if not (null realErrors) then -- found some real errors
@@ -399,7 +403,7 @@ pathToTransaction graph currentTransaction targetTransaction accumTransSet = do
399403 Right (S.unions paths)
400404
401405mergeTransactions :: UTCTime -> TransactionId -> TransactionId -> MergeStrategy -> (HeadName, HeadName) -> TransactionGraph -> Either RelationalError (DisconnectedTransaction, TransactionGraph)
402−mergeTransactions stamp newId parentId mergeStrategy (headNameA, headNameB) graph = do
406+mergeTransactions stamp' newId parentId mergeStrategy (headNameA, headNameB) graph = do
403407 let transactionForHeadErr name = case transactionForHead name graph of
404408 Nothing -> Left (NoSuchHeadNameError name)
405409 Just t -> Right t
@@ -409,16 +413,16 @@ mergeTransactions stamp newId parentId mergeStrategy (headNameA, headNameB) grap
409413 let subHeads = M.filterWithKey (\k _ -> k `elem` [headNameA, headNameB]) (transactionHeadsForGraph graph)
410414 subGraph <- subGraphOfFirstCommonAncestor graph subHeads transA transB S.empty
411415 subGraph' <- filterSubGraph subGraph subHeads
412− case createMergeTransaction stamp newId mergeStrategy subGraph' (transA, transB) of
416+ case createMergeTransaction stamp' newId mergeStrategy subGraph' (transA, transB) of
413417 Left err -> Left (MergeTransactionError err)
414418 Right mergedTrans -> case checkConstraints (concreteDatabaseContext mergedTrans) of
415419 Left err -> Left err
416420 Right _ -> case headNameForTransaction disconParent graph of
417421 Nothing -> Left (TransactionIsNotAHeadError parentId)
418422 Just headName -> do
419− (newTrans, newGraph) <- addTransactionToGraph headName mergedTrans ??? graph
423+ (newTrans, newGraph) <- addTransactionToGraph headName mergedTrans graph
420424 let newGraph' = TransactionGraph (transactionHeadsForGraph newGraph) (transactionsForGraph newGraph)
421− newDiscon = DisconnectedTransaction newId (schemas newTrans) False
425+ newDiscon = Discon.freshTransaction newId (schemas newTrans)
422426 pure (newDiscon, newGraph')
423427
424428--TEMPORARY COPY/PASTE
@@ -426,7 +430,7 @@ showTransactionStructureX :: Transaction -> TransactionGraph -> String
426430showTransactionStructureX trans graph = headInfo ++ " " ++ show (transactionId trans) ++ " " ++ parentTransactionsInfo
427431 where
428432 headInfo = maybe "" show (headNameForTransaction trans graph)
429− parentTransactionsInfo = if isRootTransaction trans graph then "root" else case parentTransactions trans graph of
433+ parentTransactionsInfo = if isRootTransaction trans then "root" else case parentTransactions trans graph of
430434 Left err -> show err
431435 Right parentTransSet -> concat $ S.toList $ S.map (show . transactionId) parentTransSet
432436
@@ -446,7 +450,7 @@ filterSubGraph graph heads = Right $ TransactionGraph newHeads newTransSet
446450
447451--helper function for commonalities in union merge
448452createUnionMergeTransaction :: UTCTime -> TransactionId -> MergeStrategy -> TransactionGraph -> (Transaction, Transaction) -> Either MergeError Transaction
449−createUnionMergeTransaction stamp newId strategy graph (t1,t2) = do
453+createUnionMergeTransaction stamp' newId strategy graph (t1,t2) = do
450454 let contextA = concreteDatabaseContext t1
451455 contextB = concreteDatabaseContext t2
452456
@@ -474,7 +478,10 @@ createUnionMergeTransaction stamp newId strategy graph (t1,t2) = do
474478 typeConstructorMapping = types
475479 }
476480 newSchemas = Schemas newContext (subschemas t1)
477− pure (Transaction newId (MergeTransactionInfo (transactionId t1) (transactionId t2) TD.empty stamp) newSchemas)
481+ pure (Transaction newId (TransactionInfo {
482+ parents = NE.fromList [(transactionId t1, undefined),
483+ (transactionId t2, undefined)],
484+ stamp = stamp'}) newSchemas)
478485
479486lookupTransaction :: TransactionGraph -> TransactionIdLookup -> Either RelationalError Transaction
480487lookupTransaction graph (TransactionIdLookup tid) = transactionForId tid graph
@@ -491,11 +498,11 @@ backtrackGraph :: TransactionGraph -> TransactionId -> TransactionIdHeadBacktrac
491498-- tilde, step back one parent link- if a choice must be made, choose the "first" link arbitrarily
492499backtrackGraph graph currentTid (TransactionIdHeadParentBacktrack steps) = do
493500 trans <- transactionForId currentTid graph
494− let parents = S.toAscList (transactionParentIds trans)
495− if length parents < 1 then
501+ let parentIds' = S.toList (parentIds trans)
502+ if length parentIds' < 1 then
496503 Left RootTransactionTraversalError
497504 else do
498− parentTrans <- transactionForId (head parents) graph
505+ parentTrans <- transactionForId (head parentIds') graph
499506 if steps == 1 then
500507 pure (transactionId parentTrans)
501508 else
@@ -503,44 +510,44 @@ backtrackGraph graph currentTid (TransactionIdHeadParentBacktrack steps) = do
503510
504511backtrackGraph graph currentTid (TransactionIdHeadBranchBacktrack steps) = do
505512 trans <- transactionForId currentTid graph
506− let parents = transactionParentIds trans
507− if S.size parents < 1 then
513+ let parentIds' = parentIds trans
514+ if S.size parentIds' < 1 then
508515 Left RootTransactionTraversalError
509− else if S.size parents < steps then
510− Left (ParentCountTraversalError (S.size parents) steps)
516+ else if S.size parentIds' < steps then
517+ Left (ParentCountTraversalError (S.size parentIds') steps)
511518 else
512− pure (S.elemAt (steps - 1) parents)
519+ pure (S.elemAt (steps - 1) parentIds')
513520
514−backtrackGraph graph currentTid btrack@(TransactionStampHeadBacktrack stamp) = do
521+backtrackGraph graph currentTid btrack@(TransactionStampHeadBacktrack stamp') = do
515522 trans <- transactionForId currentTid graph
516− let parents = transactionParentIds trans
517− if transactionTimestamp trans <= stamp then
523+ let parentIds' = parentIds trans
524+ if timestamp trans <= stamp' then
518525 pure currentTid
519− else if S.null parents then
526+ else if S.null parentIds' then
520527 Left RootTransactionTraversalError
521528 else
522− let arbitraryParent = head (S.toList parents) in
529+ let arbitraryParent = head (S.toList parentIds') in
523530 backtrackGraph graph arbitraryParent btrack
524531
525532-- | Create a temporary branch for commit, merge the result to head, delete the temporary branch. This is useful to atomically commit a transaction, avoiding a TransactionIsNotHeadError but trading it for a potential MergeError.
526533--this is not a GraphOp because it combines multiple graph operations
527534autoMergeToHead :: UTCTime -> (TransactionId, TransactionId, TransactionId) -> DisconnectedTransaction -> HeadName -> MergeStrategy -> TransactionGraph -> Either RelationalError (DisconnectedTransaction, TransactionGraph)
528−autoMergeToHead stamp (tempBranchTransId, tempCommitTransId, mergeTransId) discon mergeToHeadName strat graph = do
535+autoMergeToHead stamp' (tempBranchTransId, tempCommitTransId, mergeTransId) discon mergeToHeadName strat graph = do
529536 let tempBranchName = "mergebranch_" <> U.toText tempBranchTransId
530537 --create the temp branch
531− (discon', graph') <- evalGraphOp stamp tempBranchTransId discon graph (Branch tempBranchName)
538+ (discon', graph') <- evalGraphOp stamp' tempBranchTransId discon graph (Branch tempBranchName)
532539
533540 --commit to the new branch- possible future optimization: don't require fsync for this- create a temp commit type
534− (discon'', graph'') <- evalGraphOp stamp tempCommitTransId discon' graph' Commit
541+ (discon'', graph'') <- evalGraphOp stamp' tempCommitTransId discon' graph' Commit
535542
536543 --jump to merge head
537− (discon''', graph''') <- evalGraphOp stamp tempBranchTransId discon'' graph'' (JumpToHead mergeToHeadName)
544+ (discon''', graph''') <- evalGraphOp stamp' tempBranchTransId discon'' graph'' (JumpToHead mergeToHeadName)
538545
539546 --create the merge
540− (discon'''', graph'''') <- evalGraphOp stamp mergeTransId discon''' graph''' (MergeTransactions strat tempBranchName mergeToHeadName)
547+ (discon'''', graph'''') <- evalGraphOp stamp' mergeTransId discon''' graph''' (MergeTransactions strat tempBranchName mergeToHeadName)
541548
542549 --delete the temp branch
543− (discon''''', graph''''') <- evalGraphOp stamp tempBranchTransId discon'''' graph'''' (DeleteBranch tempBranchName)
550+ (discon''''', graph''''') <- evalGraphOp stamp' tempBranchTransId discon'''' graph'''' (DeleteBranch tempBranchName)
544551 {-
545552 let rel = runReader (evalRelationalExpr (RelationVariable "s" ())) (mkRelationalExprState $ D.concreteDatabaseContext discon'''')
546553 traceShowM rel