@@ -367,8 +367,9 @@ evalRelationalExpr (Extend tupleExpression relExpr) = do
367setRelVar :: RelVarName -> GraphRefRelationalExpr -> DatabaseContextEvalMonad ()
367setRelVar :: RelVarName -> GraphRefRelationalExpr -> DatabaseContextEvalMonad ()
368setRelVar relVarName relExpr = do
368setRelVar relVarName relExpr = do
369 currentContext <- getStateContext
369 currentContext <- getStateContext
370− --prevent recursive relvar definition
370+ --prevent recursive relvar definition by resolving references to relvars in previous states
371+ relExpr' <- resolve relExpr
371− let newRelVars = M.insert relVarName relExpr $ relationVariables currentContext
372+ let newRelVars = M.insert relVarName relExpr' $ relationVariables currentContext
372 potentialContext = currentContext { relationVariables = newRelVars }
373 potentialContext = currentContext { relationVariables = newRelVars }
373 --optimization: if the relexpr is unchanged, skip the update
374 --optimization: if the relexpr is unchanged, skip the update
374 if M.lookup relVarName (relationVariables currentContext) == Just relExpr then
375 if M.lookup relVarName (relationVariables currentContext) == Just relExpr then
@@ -1544,3 +1545,71 @@ relVarByName rvName = do
1544 Nothing -> throwError (RelVarNotDefinedError rvName)
1545 Nothing -> throwError (RelVarNotDefinedError rvName)
1545 Just gfexpr -> pure gfexpr
1546 Just gfexpr -> pure gfexpr
1548+-- | resolve UncommittedTransactionMarker whenever possible- this is important in the DatabaseContext in order to mitigate self-referencing loops for updates
1549+class ResolveGraphRefTransactionMarker a where
1550+ resolve :: a -> DatabaseContextEvalMonad a
1553+instance ResolveGraphRefTransactionMarker GraphRefRelationalExpr where
1554+ resolve (MakeRelationFromExprs mAttrs tupleExprs) =
1555+ MakeRelationFromExprs mAttrs <$> resolve tupleExprs
1556+ resolve orig@MakeStaticRelation{} = pure orig
1557+ resolve orig@ExistingRelation{} = pure orig
1558+ resolve orig@(RelationVariable rvName UncommittedContextMarker) = do
1559+ rvMap <- relationVariables <$> getStateContext
1560+ case M.lookup rvName rvMap of
1561+ Nothing -> pure orig
1562+ Just resolvedRv -> resolve resolvedRv
1563+ resolve orig@RelationVariable{} = pure orig
1564+ resolve (Project attrNames relExpr) = Project <$> resolve attrNames <*> resolve relExpr
1565+ resolve (Union exprA exprB) = Union <$> resolve exprA <*> resolve exprB
1566+ resolve (Join exprA exprB) = Join <$> resolve exprA <*> resolve exprB
1567+ resolve (Rename attrA attrB expr) = Rename attrA attrB <$> resolve expr
1568+ resolve (Difference exprA exprB) = Difference <$> resolve exprA <*> resolve exprB
1569+ resolve (Group namesA nameB expr) = Group <$> resolve namesA <*> pure nameB <*> resolve expr
1570+ resolve (Ungroup nameA expr) = Ungroup nameA <$> resolve expr
1571+ resolve (Restrict restrictExpr relExpr) = Restrict <$> resolve restrictExpr <*> resolve relExpr
1572+ resolve (Equals exprA exprB) = Equals <$> resolve exprA <*> resolve exprB
1573+ resolve (NotEquals exprA exprB) = NotEquals <$> resolve exprA <*> resolve exprB
1574+ resolve (Extend extendExpr relExpr) = Extend <$> resolve extendExpr <*> resolve relExpr
1575+ resolve (With withExprs relExpr) = With <$> mapM (\(nam, expr) -> (,) <$> resolve nam <*> resolve expr) withExprs <*> resolve relExpr
1577+instance ResolveGraphRefTransactionMarker GraphRefTupleExprs where
1578+ resolve (TupleExprs marker tupleExprs) =
1579+ TupleExprs marker <$> mapM resolve tupleExprs
1581+instance ResolveGraphRefTransactionMarker GraphRefTupleExpr where
1582+ resolve (TupleExpr tupMap) = do
1583+ tupMap' <- mapM (\(attrName, expr) -> (,) attrName <$> resolve expr ) (M.toList tupMap)
1584+ pure (TupleExpr (M.fromList tupMap'))
1586+instance ResolveGraphRefTransactionMarker GraphRefAttributeNames where
1587+ resolve orig@AttributeNames{} = pure orig
1588+ resolve orig@InvertedAttributeNames{} = pure orig
1589+ resolve (UnionAttributeNames namesA namesB) = UnionAttributeNames <$> resolve namesA <*> resolve namesB
1590+ resolve (IntersectAttributeNames namesA namesB) = IntersectAttributeNames <$> resolve namesA <*> resolve namesB
1591+ resolve (RelationalExprAttributeNames expr) = RelationalExprAttributeNames <$> resolve expr
1593+instance ResolveGraphRefTransactionMarker GraphRefRestrictionPredicateExpr where
1594+ resolve TruePredicate = pure TruePredicate
1595+ resolve (AndPredicate exprA exprB) = AndPredicate <$> resolve exprA <*> resolve exprB
1596+ resolve (OrPredicate exprA exprB) = OrPredicate <$> resolve exprA <*> resolve exprB
1597+ resolve (NotPredicate expr) = NotPredicate <$> resolve expr
1598+ resolve (RelationalExprPredicate expr) = RelationalExprPredicate <$> resolve expr
1599+ resolve (AtomExprPredicate expr) = AtomExprPredicate <$> resolve expr
1600+ resolve (AttributeEqualityPredicate nam expr)= AttributeEqualityPredicate nam <$> resolve expr
1602+instance ResolveGraphRefTransactionMarker GraphRefExtendTupleExpr where
1603+ resolve (AttributeExtendTupleExpr nam atomExpr) = AttributeExtendTupleExpr nam <$> resolve atomExpr
1605+instance ResolveGraphRefTransactionMarker GraphRefWithNameExpr where
1606+ resolve orig@WithNameExpr{} = pure orig -- match uncommitted marker?
1608+instance ResolveGraphRefTransactionMarker GraphRefAtomExpr where
1609+ resolve orig@AttributeAtomExpr{} = pure orig
1610+ resolve orig@NakedAtomExpr{} = pure orig
1611+ resolve (FunctionAtomExpr nam atomExprs marker) =
1612+ FunctionAtomExpr nam <$> mapM resolve atomExprs <*> pure marker
1613+ resolve (RelationAtomExpr expr) = RelationAtomExpr <$> resolve expr
1614+ resolve (ConstructedAtomExpr dConsName atomExprs marker) =
1615+ ConstructedAtomExpr dConsName <$> mapM resolve atomExprs <*> pure marker