@@ -16,13 +16,14 @@ import qualified ProjectM36.Attribute as A
16import qualified Data.UUID as U
16import qualified Data.UUID as U
17import qualified Data.Set as S
17import qualified Data.Set as S
18import qualified Data.Map as M
18import qualified Data.Map as M
19+import qualified Data.List.NonEmpty as NE
19import Control.Monad
20import Control.Monad
20import Data.Time.Clock
21import Data.Time.Clock
21import qualified Data.Text as T
22import qualified Data.Text as T
22import GHC.Generics
23import GHC.Generics
23import Data.Binary
24import Data.Binary
24import Data.Either (lefts, rights, isRight)
25import Data.Either (lefts, rights, isRight)
25−import Data.Monoid
26+--import Data.Monoid
26import Control.Arrow
27import Control.Arrow
27import Data.Maybe
28import Data.Maybe
@@ -63,11 +64,11 @@ data ROTransactionGraphOperator = ShowGraph
63 deriving Show
64 deriving Show
65bootstrapTransactionGraph :: UTCTime -> TransactionId -> DatabaseContext -> TransactionGraph
66bootstrapTransactionGraph :: UTCTime -> TransactionId -> DatabaseContext -> TransactionGraph
66−bootstrapTransactionGraph stamp freshId context = TransactionGraph bootstrapHeads bootstrapTransactions
67+bootstrapTransactionGraph stamp' freshId context = TransactionGraph bootstrapHeads bootstrapTransactions
68 bootstrapHeads = M.singleton "master" freshTransaction
69 bootstrapHeads = M.singleton "master" freshTransaction
69 newSchemas = Schemas context M.empty
70 newSchemas = Schemas context M.empty
70− freshTransaction = Transaction freshId (TransactionInfo U.nil TD.empty stamp) newSchemas
71+ freshTransaction = fresh freshId stamp' newSchemas
71 bootstrapTransactions = S.singleton freshTransaction
72 bootstrapTransactions = S.singleton freshTransaction
73emptyTransactionGraph :: TransactionGraph
74emptyTransactionGraph :: TransactionGraph
@@ -108,57 +109,58 @@ transactionsForIds :: S.Set TransactionId -> TransactionGraph -> Either Relation
108transactionsForIds idSet graph =
109transactionsForIds idSet graph =
109 S.fromList <$> forM (S.toList idSet) (`transactionForId` graph)
110 S.fromList <$> forM (S.toList idSet) (`transactionForId` graph)
112+-- | A root transaction terminates a graph and has no parents.
111−isRootTransaction :: Transaction -> TransactionGraph -> Bool
113+isRootTransaction :: Transaction -> Bool
112−isRootTransaction (Transaction _ (TransactionInfo pId _ _) _) _ = U.null pId
114+isRootTransaction trans = diffs trans == TD.root
113−isRootTransaction (Transaction _ MergeTransactionInfo{} _) _ = False
115-- the first transaction has no parent - all other do have parents- merges have two parents
116-- the first transaction has no parent - all other do have parents- merges have two parents
116parentTransactions :: Transaction -> TransactionGraph -> Either RelationalError (S.Set Transaction)
117parentTransactions :: Transaction -> TransactionGraph -> Either RelationalError (S.Set Transaction)
117−parentTransactions (Transaction _ (TransactionInfo pId _ _) _) graph =
118+parentTransactions trans graph = transactionsForIds (parentIds trans) graph
118− S.singleton <$> transactionForId pId graph
121−parentTransactions (Transaction _ (MergeTransactionInfo pId1 pId2 _ _) _ ) graph = transactionsForIds (S.fromList [pId1, pId2]) graph
124childTransactions :: Transaction -> TransactionGraph -> Either RelationalError (S.Set Transaction)
120childTransactions :: Transaction -> TransactionGraph -> Either RelationalError (S.Set Transaction)
125−childTransactions trans = transactionsForIds (transactionChildIds trans)
121+childTransactions trans graph = transactionsForIds childIds graph
123+ childIds = S.map transactionId (S.filter filt (transactionsForGraph graph))
124+ filt trans' = S.member (transactionId trans) (parentIds trans')
127-- create a new commit and add it to the heads
126-- create a new commit and add it to the heads
128-- 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)
127-- 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)
129addBranch :: UTCTime -> TransactionId -> HeadName -> TransactionId -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
128addBranch :: 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
131 parentTrans <- transactionForId branchPointId graph
130 parentTrans <- transactionForId branchPointId graph
132− let newTrans = Transaction newId (TransactionInfo branchPointId TD.empty stamp) (schemas parentTrans)
131+ let newTrans = Transaction newId (TransactionInfo {
132+ parents = TD.single branchPointId NoOperation,
133+ stamp = stamp'}) (schemas parentTrans)
133− addTransactionToGraph newBranchName newTrans [(newId, NoOperation)] graph
134+ addTransactionToGraph newBranchName newTrans graph
135--adds a disconnected transaction to a transaction graph at some head
136--adds a disconnected transaction to a transaction graph at some head
136addDisconnectedTransaction :: UTCTime -> TransactionId -> HeadName -> DisconnectedTransaction -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
137addDisconnectedTransaction :: 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
140+ newTrans = Transaction newId (TransactionInfo {
141+ parents = TD.single parentId (Discon.diffExpr discon),
142+ stamp = stamp'}) schemas'
140−addTransactionToGraph :: HeadName -> Transaction -> TransactionDiffs -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
145+addTransactionToGraph :: HeadName -> Transaction -> TransactionGraph -> Either RelationalError (Transaction, TransactionGraph)
141−addTransactionToGraph headName newTrans transDiffs graph = do
146+addTransactionToGraph headName newTrans graph = do
142− let parentIds = transactionParentIds newTrans
147+ let parentIds' = parentIds newTrans
143− childIds = transactionChildIds newTrans
144 newId = transactionId newTrans
148 newId = transactionId newTrans
145 validateIds ids = mapM (`transactionForId` graph) (S.toList ids)
149 validateIds ids = mapM (`transactionForId` graph) (S.toList ids)
146− addChildTransaction trans = transactionSetChildren trans (transDiffs ++ diffs trans)
150+ childTs <- childTransactions newTrans graph
147 --validate that the parent transactions are in the graph
151 --validate that the parent transactions are in the graph
148− _ <- validateIds parentIds
152+ _ <- validateIds parentIds'
149− when (S.size parentIds < 1) (Left $ NewTransactionMissingParentError newId)
153+ when (S.size parentIds' < 1) (Left $ NewTransactionMissingParentError newId)
150 --if the headName already exists, ensure that it refers to a parent
154 --if the headName already exists, ensure that it refers to a parent
151 case transactionForHead headName graph of
155 case transactionForHead headName graph of
152 Nothing -> pure () -- any headName is OK
156 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))
154 --validate that the transaction has no children
158 --validate that the transaction has no children
155− unless (S.null childIds) (Left $ NewTransactionMayNotHaveChildrenError newId)
159+ unless (S.null childTs) (Left $ NewTransactionMayNotHaveChildrenError newId)
156 --validate that the trasaction's id is unique
160 --validate that the trasaction's id is unique
157 when (isRight (transactionForId newId graph)) (Left (TransactionIdInUseError newId))
161 when (isRight (transactionForId newId graph)) (Left (TransactionIdInUseError newId))
158− --update the parent transactions to point to the new transaction
162+
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))
163+ let updatedTransSet = S.insert newTrans (transactionsForGraph graph)
162 updatedHeads = M.insert headName newTrans (transactionHeadsForGraph graph)
164 updatedHeads = M.insert headName newTrans (transactionHeadsForGraph graph)
163 pure (newTrans, TransactionGraph updatedHeads updatedTransSet)
165 pure (newTrans, TransactionGraph updatedHeads updatedTransSet)
@@ -250,15 +252,15 @@ evalGraphOp newId discon@(DisconnectedTransaction parentId disconContext) graph
251-- create a new commit and add it to the heads
253-- create a new commit and add it to the heads
252-- 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)
254-- 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
254 let newDiscon = Discon.freshTransaction newId schemas'
256 let newDiscon = Discon.freshTransaction newId schemas'
255− case addBranch stamp newId newBranchName parentId graph of
257+ case addBranch stamp' newId newBranchName parentId graph of
256 Left err -> Left err
258 Left err -> Left err
257 Right (_, newGraph) -> Right (newDiscon, newGraph)
259 Right (_, newGraph) -> Right (newDiscon, newGraph)
259-- add the disconnected transaction to the graph
261-- add the disconnected transaction to the graph
260-- affects graph and disconnectedtransaction- the new disconnectedtransaction's parent is the freshly committed transaction
262-- 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
262 Left err -> Left err
264 Left err -> Left err
263 Right parentTransaction -> case headNameForTransaction parentTransaction graph of
265 Right parentTransaction -> case headNameForTransaction parentTransaction graph of
264 Nothing -> Left $ TransactionIsNotAHeadError parentId
266 Nothing -> Left $ TransactionIsNotAHeadError parentId
@@ -267,7 +269,7 @@ evalGraphOp stamp newTransId discon@(DisconnectedTransaction parentId schemas' _
267 Right (_, updatedGraph) -> Right (newDisconnectedTrans, updatedGraph)
269 Right (_, updatedGraph) -> Right (newDisconnectedTrans, updatedGraph)
269 newDisconnectedTrans = Discon.freshTransaction newTransId schemas'
271 newDisconnectedTrans = Discon.freshTransaction newTransId schemas'
270− maybeUpdatedGraph = addDisconnectedTransaction stamp newTransId headName discon graph
272+ maybeUpdatedGraph = addDisconnectedTransaction stamp' newTransId headName discon graph
272-- refresh the disconnected transaction, return the same graph
274-- refresh the disconnected transaction, return the same graph
273evalGraphOp _ _ (DisconnectedTransaction parentId _ _) graph Rollback = case transactionForId parentId graph of
275evalGraphOp _ _ (DisconnectedTransaction parentId _ _) graph Rollback = case transactionForId parentId graph of
@@ -276,7 +278,7 @@ evalGraphOp _ _ (DisconnectedTransaction parentId _ _) graph Rollback = case tra
277 newDiscon = Discon.freshTransaction parentId (schemas parentTransaction)
279 newDiscon = Discon.freshTransaction parentId (schemas parentTransaction)
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
281evalGraphOp _ _ discon graph@(TransactionGraph graphHeads transSet) (DeleteBranch branchName) = case transactionForHead branchName graph of
283evalGraphOp _ _ discon graph@(TransactionGraph graphHeads transSet) (DeleteBranch branchName) = case transactionForHead branchName graph of
282 Nothing -> Left (NoSuchHeadNameError branchName)
284 Nothing -> Left (NoSuchHeadNameError branchName)
@@ -298,7 +300,7 @@ graphAsRelation (DisconnectedTransaction parentId _ _) graph@(TransactionGraph _
298 tupleGenerator transaction = case transactionParentsRelation transaction graph of
300 tupleGenerator transaction = case transactionParentsRelation transaction graph of
299 Left err -> Left err
301 Left err -> Left err
300 Right parentTransRel -> Right [TextAtom $ T.pack $ show (transactionId transaction),
302 Right parentTransRel -> Right [TextAtom $ T.pack $ show (transactionId transaction),
301− DateTimeAtom (transactionTimestamp transaction),
303+ DateTimeAtom (timestamp transaction),
302 RelationAtom parentTransRel,
304 RelationAtom parentTransRel,
303 BoolAtom $ parentId == transactionId transaction,
305 BoolAtom $ parentId == transactionId transaction,
304 TextAtom $ fromMaybe "" (headNameForTransaction transaction graph)
306 TextAtom $ fromMaybe "" (headNameForTransaction transaction graph)
@@ -306,7 +308,7 @@ graphAsRelation (DisconnectedTransaction parentId _ _) graph@(TransactionGraph _
307transactionParentsRelation :: Transaction -> TransactionGraph -> Either RelationalError Relation
309transactionParentsRelation :: Transaction -> TransactionGraph -> Either RelationalError Relation
308transactionParentsRelation trans graph =
310transactionParentsRelation trans graph =
309− if isRootTransaction trans graph then
311+ if isRootTransaction trans then
310 mkRelation attrs emptyTupleSet
312 mkRelation attrs emptyTupleSet
312 parentTransSet <- parentTransactions trans graph
314 parentTransSet <- parentTransactions trans graph
@@ -326,15 +328,18 @@ evalROGraphOp discon graph ShowGraph = do
327-- | Execute the merge strategy against the transactions, returning a new transaction which can be then added to the transaction graph
329-- | Execute the merge strategy against the transactions, returning a new transaction which can be then added to the transaction graph
328createMergeTransaction :: UTCTime -> TransactionId -> MergeStrategy -> TransactionGraph -> (Transaction, Transaction) -> Either MergeError Transaction
330createMergeTransaction :: 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
330 let selectedTrans = validateHeadName selectedBranch graph t2
332 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
333-- merge functions, relvars, individually
338-- 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
336-- merge function, relvars, but, on error, just take the component from the preferred branch
341-- 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
339-- | 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.
344-- | 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.
340validateHeadName :: HeadName -> TransactionGraph -> (Transaction, Transaction) -> Either MergeError Transaction
345validateHeadName :: HeadName -> TransactionGraph -> (Transaction, Transaction) -> Either MergeError Transaction
@@ -355,7 +360,7 @@ subGraphOfFirstCommonAncestor origGraph resultHeads currentTrans goalTrans trave
355 Right (TransactionGraph resultHeads traverseSet) -- add filter
360 Right (TransactionGraph resultHeads traverseSet) -- add filter
356 --catch root transaction to improve error?
361 --catch root transaction to improve error?
358− currentTransChildren <- S.fromList <$> mapM (`transactionForId` origGraph) (S.toList (transactionChildIds currentTrans))
363+ currentTransChildren <- childTransactions currentTrans origGraph
359 let searchChildren = S.difference (S.insert currentTrans traverseSet) currentTransChildren
364 let searchChildren = S.difference (S.insert currentTrans traverseSet) currentTransChildren
360 searchChild start = pathToTransaction origGraph start goalTrans (S.insert currentTrans traverseSet)
365 searchChild start = pathToTransaction origGraph start goalTrans (S.insert currentTrans traverseSet)
361 childSearches = map searchChild (S.toList searchChildren)
366 childSearches = map searchChild (S.toList searchChildren)
@@ -374,9 +379,8 @@ subGraphOfFirstCommonAncestor origGraph resultHeads currentTrans goalTrans trave
374 else -- we found a path
379 else -- we found a path
375 Right (TransactionGraph resultHeads (S.unions (traverseSet : pathsFound)))
380 Right (TransactionGraph resultHeads (S.unions (traverseSet : pathsFound)))
377− oneParent (Transaction _ (TransactionInfo parentId _ _) _) = transactionForId parentId origGraph
382+ oneParent (Transaction _ tinfo _) = transactionForId (fst (NE.head (parents tinfo))) origGraph
378− oneParent (Transaction _ (MergeTransactionInfo parentId _ _ _) _) = transactionForId parentId origGraph
383+
380-- | Search from a past graph point to all following heads for a specific transaction. If found, return the transaction path, otherwise a RelationalError.
384-- | Search from a past graph point to all following heads for a specific transaction. If found, return the transaction path, otherwise a RelationalError.
381pathToTransaction :: TransactionGraph -> Transaction -> Transaction -> S.Set Transaction -> Either RelationalError (S.Set Transaction)
385pathToTransaction :: TransactionGraph -> Transaction -> Transaction -> S.Set Transaction -> Either RelationalError (S.Set Transaction)
382pathToTransaction graph currentTransaction targetTransaction accumTransSet = do
386pathToTransaction graph currentTransaction targetTransaction accumTransSet = do
@@ -384,11 +388,11 @@ pathToTransaction graph currentTransaction targetTransaction accumTransSet = do
384 if transactionId targetTransaction == transactionId currentTransaction then
388 if transactionId targetTransaction == transactionId currentTransaction then
385 Right accumTransSet
389 Right accumTransSet
387− currentTransChildren <- mapM (`transactionForId` graph) (S.toList (transactionChildIds currentTransaction))
391+ currentTransChildren <- childTransactions currentTransaction graph
388 if null currentTransChildren then
392 if null currentTransChildren then
389 Left (FailedToFindTransactionError targetId)
393 Left (FailedToFindTransactionError targetId)
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)
392 let realErrors = filter (/= FailedToFindTransactionError targetId) (lefts searches)
396 let realErrors = filter (/= FailedToFindTransactionError targetId) (lefts searches)
393 paths = rights searches
397 paths = rights searches
394 if not (null realErrors) then -- found some real errors
398 if not (null realErrors) then -- found some real errors
@@ -399,7 +403,7 @@ pathToTransaction graph currentTransaction targetTransaction accumTransSet = do
399 Right (S.unions paths)
403 Right (S.unions paths)
401mergeTransactions :: UTCTime -> TransactionId -> TransactionId -> MergeStrategy -> (HeadName, HeadName) -> TransactionGraph -> Either RelationalError (DisconnectedTransaction, TransactionGraph)
405mergeTransactions :: 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
403 let transactionForHeadErr name = case transactionForHead name graph of
407 let transactionForHeadErr name = case transactionForHead name graph of
404 Nothing -> Left (NoSuchHeadNameError name)
408 Nothing -> Left (NoSuchHeadNameError name)
405 Just t -> Right t
409 Just t -> Right t
@@ -409,16 +413,16 @@ mergeTransactions stamp newId parentId mergeStrategy (headNameA, headNameB) grap
409 let subHeads = M.filterWithKey (\k _ -> k `elem` [headNameA, headNameB]) (transactionHeadsForGraph graph)
413 let subHeads = M.filterWithKey (\k _ -> k `elem` [headNameA, headNameB]) (transactionHeadsForGraph graph)
410 subGraph <- subGraphOfFirstCommonAncestor graph subHeads transA transB S.empty
414 subGraph <- subGraphOfFirstCommonAncestor graph subHeads transA transB S.empty
411 subGraph' <- filterSubGraph subGraph subHeads
415 subGraph' <- filterSubGraph subGraph subHeads
412− case createMergeTransaction stamp newId mergeStrategy subGraph' (transA, transB) of
416+ case createMergeTransaction stamp' newId mergeStrategy subGraph' (transA, transB) of
413 Left err -> Left (MergeTransactionError err)
417 Left err -> Left (MergeTransactionError err)
414 Right mergedTrans -> case checkConstraints (concreteDatabaseContext mergedTrans) of
418 Right mergedTrans -> case checkConstraints (concreteDatabaseContext mergedTrans) of
415 Left err -> Left err
419 Left err -> Left err
416 Right _ -> case headNameForTransaction disconParent graph of
420 Right _ -> case headNameForTransaction disconParent graph of
417 Nothing -> Left (TransactionIsNotAHeadError parentId)
421 Nothing -> Left (TransactionIsNotAHeadError parentId)
418 Just headName -> do
422 Just headName -> do
419− (newTrans, newGraph) <- addTransactionToGraph headName mergedTrans ??? graph
423+ (newTrans, newGraph) <- addTransactionToGraph headName mergedTrans graph
420 let newGraph' = TransactionGraph (transactionHeadsForGraph newGraph) (transactionsForGraph newGraph)
424 let newGraph' = TransactionGraph (transactionHeadsForGraph newGraph) (transactionsForGraph newGraph)
421− newDiscon = DisconnectedTransaction newId (schemas newTrans) False
425+ newDiscon = Discon.freshTransaction newId (schemas newTrans)
422 pure (newDiscon, newGraph')
426 pure (newDiscon, newGraph')
424--TEMPORARY COPY/PASTE
428--TEMPORARY COPY/PASTE
@@ -426,7 +430,7 @@ showTransactionStructureX :: Transaction -> TransactionGraph -> String
426showTransactionStructureX trans graph = headInfo ++ " " ++ show (transactionId trans) ++ " " ++ parentTransactionsInfo
430showTransactionStructureX trans graph = headInfo ++ " " ++ show (transactionId trans) ++ " " ++ parentTransactionsInfo
428 headInfo = maybe "" show (headNameForTransaction trans graph)
432 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
430 Left err -> show err
434 Left err -> show err
431 Right parentTransSet -> concat $ S.toList $ S.map (show . transactionId) parentTransSet
435 Right parentTransSet -> concat $ S.toList $ S.map (show . transactionId) parentTransSet
@@ -446,7 +450,7 @@ filterSubGraph graph heads = Right $ TransactionGraph newHeads newTransSet
447--helper function for commonalities in union merge
451--helper function for commonalities in union merge
448createUnionMergeTransaction :: UTCTime -> TransactionId -> MergeStrategy -> TransactionGraph -> (Transaction, Transaction) -> Either MergeError Transaction
452createUnionMergeTransaction :: 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
450 let contextA = concreteDatabaseContext t1
454 let contextA = concreteDatabaseContext t1
451 contextB = concreteDatabaseContext t2
455 contextB = concreteDatabaseContext t2
@@ -474,7 +478,10 @@ createUnionMergeTransaction stamp newId strategy graph (t1,t2) = do
474 typeConstructorMapping = types
478 typeConstructorMapping = types
476 newSchemas = Schemas newContext (subschemas t1)
480 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)
479lookupTransaction :: TransactionGraph -> TransactionIdLookup -> Either RelationalError Transaction
486lookupTransaction :: TransactionGraph -> TransactionIdLookup -> Either RelationalError Transaction
480lookupTransaction graph (TransactionIdLookup tid) = transactionForId tid graph
487lookupTransaction graph (TransactionIdLookup tid) = transactionForId tid graph
@@ -491,11 +498,11 @@ backtrackGraph :: TransactionGraph -> TransactionId -> TransactionIdHeadBacktrac
491-- tilde, step back one parent link- if a choice must be made, choose the "first" link arbitrarily
498-- tilde, step back one parent link- if a choice must be made, choose the "first" link arbitrarily
492backtrackGraph graph currentTid (TransactionIdHeadParentBacktrack steps) = do
499backtrackGraph graph currentTid (TransactionIdHeadParentBacktrack steps) = do
493 trans <- transactionForId currentTid graph
500 trans <- transactionForId currentTid graph
494− let parents = S.toAscList (transactionParentIds trans)
501+ let parentIds' = S.toList (parentIds trans)
495− if length parents < 1 then
502+ if length parentIds' < 1 then
496 Left RootTransactionTraversalError
503 Left RootTransactionTraversalError
498− parentTrans <- transactionForId (head parents) graph
505+ parentTrans <- transactionForId (head parentIds') graph
499 if steps == 1 then
506 if steps == 1 then
500 pure (transactionId parentTrans)
507 pure (transactionId parentTrans)
@@ -503,44 +510,44 @@ backtrackGraph graph currentTid (TransactionIdHeadParentBacktrack steps) = do
504backtrackGraph graph currentTid (TransactionIdHeadBranchBacktrack steps) = do
511backtrackGraph graph currentTid (TransactionIdHeadBranchBacktrack steps) = do
505 trans <- transactionForId currentTid graph
512 trans <- transactionForId currentTid graph
506− let parents = transactionParentIds trans
513+ let parentIds' = parentIds trans
507− if S.size parents < 1 then
514+ if S.size parentIds' < 1 then
508 Left RootTransactionTraversalError
515 Left RootTransactionTraversalError
509− else if S.size parents < steps then
516+ else if S.size parentIds' < steps then
510− Left (ParentCountTraversalError (S.size parents) steps)
517+ Left (ParentCountTraversalError (S.size parentIds') steps)
512− pure (S.elemAt (steps - 1) parents)
519+ pure (S.elemAt (steps - 1) parentIds')
514−backtrackGraph graph currentTid btrack@(TransactionStampHeadBacktrack stamp) = do
521+backtrackGraph graph currentTid btrack@(TransactionStampHeadBacktrack stamp') = do
515 trans <- transactionForId currentTid graph
522 trans <- transactionForId currentTid graph
516− let parents = transactionParentIds trans
523+ let parentIds' = parentIds trans
517− if transactionTimestamp trans <= stamp then
524+ if timestamp trans <= stamp' then
518 pure currentTid
525 pure currentTid
519− else if S.null parents then
526+ else if S.null parentIds' then
520 Left RootTransactionTraversalError
527 Left RootTransactionTraversalError
522− let arbitraryParent = head (S.toList parents) in
529+ let arbitraryParent = head (S.toList parentIds') in
523 backtrackGraph graph arbitraryParent btrack
530 backtrackGraph graph arbitraryParent btrack
525-- | 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.
532-- | 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.
526--this is not a GraphOp because it combines multiple graph operations
533--this is not a GraphOp because it combines multiple graph operations
527autoMergeToHead :: UTCTime -> (TransactionId, TransactionId, TransactionId) -> DisconnectedTransaction -> HeadName -> MergeStrategy -> TransactionGraph -> Either RelationalError (DisconnectedTransaction, TransactionGraph)
534autoMergeToHead :: 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
529 let tempBranchName = "mergebranch_" <> U.toText tempBranchTransId
536 let tempBranchName = "mergebranch_" <> U.toText tempBranchTransId
530 --create the temp branch
537 --create the temp branch
531− (discon', graph') <- evalGraphOp stamp tempBranchTransId discon graph (Branch tempBranchName)
538+ (discon', graph') <- evalGraphOp stamp' tempBranchTransId discon graph (Branch tempBranchName)
533 --commit to the new branch- possible future optimization: don't require fsync for this- create a temp commit type
540 --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
536 --jump to merge head
543 --jump to merge head
537− (discon''', graph''') <- evalGraphOp stamp tempBranchTransId discon'' graph'' (JumpToHead mergeToHeadName)
544+ (discon''', graph''') <- evalGraphOp stamp' tempBranchTransId discon'' graph'' (JumpToHead mergeToHeadName)
539 --create the merge
546 --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)
542 --delete the temp branch
549 --delete the temp branch
543− (discon''''', graph''''') <- evalGraphOp stamp tempBranchTransId discon'''' graph'''' (DeleteBranch tempBranchName)
550+ (discon''''', graph''''') <- evalGraphOp stamp' tempBranchTransId discon'''' graph'''' (DeleteBranch tempBranchName)
545 let rel = runReader (evalRelationalExpr (RelationVariable "s" ())) (mkRelationalExprState $ D.concreteDatabaseContext discon'''')
552 let rel = runReader (evalRelationalExpr (RelationVariable "s" ())) (mkRelationalExprState $ D.concreteDatabaseContext discon'''')
546 traceShowM rel
553 traceShowM rel