on master help sign in
resolve TupleExprs within their own transaction contexts
584b01dAgentM
src/lib/ProjectM36/Error.hs+1
@@ -100,6 +100,7 @@ data RelationalError = NoSuchAttributeNamesError (S.Set AttributeName)
100 | NonConcreteSchemaPlanError
100 | NonConcreteSchemaPlanError
101
101
102 | NoUncommittedContextInEvalError
102 | NoUncommittedContextInEvalError
103+ | TupleExprsReferenceMultipleMarkersError
103
104
104 | MultipleErrors [RelationalError]
105 | MultipleErrors [RelationalError]
105 deriving (Show,Eq,Generic,Binary,Typeable, NFData)
106 deriving (Show,Eq,Generic,Binary,Typeable, NFData)
src/lib/ProjectM36/GraphRefRelationalExpr.hs+19−17
@@ -1,32 +1,31 @@
1module ProjectM36.GraphRefRelationalExpr where
1module ProjectM36.GraphRefRelationalExpr where
2--evaluate relational expressions across the entire transaction graph to support cross-transaction referencing
2--evaluate relational expressions across the entire transaction graph to support cross-transaction referencing
3import ProjectM36.Base
3import ProjectM36.Base
4−import ProjectM36.Error
5import qualified Data.Set as S
4import qualified Data.Set as S
6
5
7−-- core evaluation function- all other relational expr forms compile to GraphRefRelationalExpr
6+--import Debug.Trace
8−eval :: GraphRefRelationalExpr -> TransactionGraph -> Either RelationalError Relation
9−eval = undefined
10−{-eval (MakeRelationFromExprs mAttrExprs tupleExprs) graph = do
11− mAttrs <- case mAttrExprs of
12− Just _ ->
13− Just . A.attributesFromList <$> mapM (evalAttrExpr tConss) (fromMaybe [] mAttrExprs)
14− Nothing -> pure Nothing
15− tuples <- mapM (evalTupleExpr mAttrs) tupleExprs
16− let attrs = fromMaybe firstTupleAttrs mAttrs
17− firstTupleAttrs = if null tuples then A.emptyAttributes else tupleAttributes (head tuples)
18− mkRelation attrs (RelationTupleSet tuples)
19−
20−
21−-}
22
7
23data SingularTransactionRef = SingularTransactionRef GraphRefTransactionMarker |
8data SingularTransactionRef = SingularTransactionRef GraphRefTransactionMarker |
24 MultipleTransactionsRef |
9 MultipleTransactionsRef |
25 NoTransactionsRef
10 NoTransactionsRef
26 deriving (Eq, Show)
11 deriving (Eq, Show)
12+
13+instance Semigroup SingularTransactionRef where
14+ NoTransactionsRef <> x = x
15+ MultipleTransactionsRef <> _ = MultipleTransactionsRef
16+ SingularTransactionRef tidA <> s@(SingularTransactionRef tidB) =
17+ if tidA == tidB then
18+ s
19+ else
20+ MultipleTransactionsRef
21+ s@SingularTransactionRef{} <> NoTransactionsRef = s
22+ _ <> MultipleTransactionsRef = MultipleTransactionsRef
23+
24+instance Monoid SingularTransactionRef where
25+ mempty = NoTransactionsRef
27
26
28-- | return `Just transid` if this GraphRefRelationalExpr refers to just one transaction in the graph. This is useful for determining if certain optimizations can apply.
27-- | return `Just transid` if this GraphRefRelationalExpr refers to just one transaction in the graph. This is useful for determining if certain optimizations can apply.
29−singularTransaction :: GraphRefRelationalExpr -> SingularTransactionRef
28+singularTransaction :: Foldable t => t GraphRefTransactionMarker -> SingularTransactionRef
30singularTransaction expr =
29singularTransaction expr =
31 if S.null transSet then
30 if S.null transSet then
32 NoTransactionsRef
31 NoTransactionsRef
@@ -44,3 +43,6 @@ inSameTransaction exprA exprB = case (stA, stB) of
44 _ -> Nothing
43 _ -> Nothing
45 where stA = singularTransaction exprA
44 where stA = singularTransaction exprA
46 stB = singularTransaction exprB
45 stB = singularTransaction exprB
46+
47+singularTransactions :: (Foldable f, Foldable t) => f (t GraphRefTransactionMarker) -> SingularTransactionRef
48+singularTransactions fs = foldMap singularTransaction fs
src/lib/ProjectM36/RelationalExpression.hs+12−5
@@ -15,6 +15,7 @@ import ProjectM36.DataTypes.Primitive
15import ProjectM36.AtomFunction
15import ProjectM36.AtomFunction
16import ProjectM36.DatabaseContextFunction
16import ProjectM36.DatabaseContextFunction
17import ProjectM36.Arbitrary
17import ProjectM36.Arbitrary
18+import ProjectM36.GraphRefRelationalExpr
18import ProjectM36.Transaction
19import ProjectM36.Transaction
19import qualified ProjectM36.Attribute as A
20import qualified ProjectM36.Attribute as A
20import qualified Data.Map as M
21import qualified Data.Map as M
@@ -111,7 +112,7 @@ mergeTuplesIntoGraphRefRelationalExprEnv tupIn e =
111 new_elems = Just (Left newTuple)
112 new_elems = Just (Left newTuple)
112 mergedTupMap = M.union (tupleToMap tupIn) (tupleToMap (envTuple e))
113 mergedTupMap = M.union (tupleToMap tupIn) (tupleToMap (envTuple e))
113 newTuple = mkRelationTupleFromMap mergedTupMap
114 newTuple = mkRelationTupleFromMap mergedTupMap
114−
115+
115mergeAttributesIntoGraphRefRelationalExprEnv :: Attributes -> GraphRefRelationalExprEnv -> GraphRefRelationalExprEnv
116mergeAttributesIntoGraphRefRelationalExprEnv :: Attributes -> GraphRefRelationalExprEnv -> GraphRefRelationalExprEnv
116mergeAttributesIntoGraphRefRelationalExprEnv attrsIn e = e { gre_extra = newattrs }
117mergeAttributesIntoGraphRefRelationalExprEnv attrsIn e = e { gre_extra = newattrs }
117 where
118 where
@@ -185,7 +186,7 @@ gfDatabaseContextForMarker (TransactionMarker transId) = concreteDatabaseContext
185gfDatabaseContextForMarker UncommittedContextMarker = do
186gfDatabaseContextForMarker UncommittedContextMarker = do
186 mctx <- gre_context <$> askEnv
187 mctx <- gre_context <$> askEnv
187 case mctx of
188 case mctx of
188− Nothing -> throwError NoUncommittedContextInEvalError
189+ Nothing -> throwError (traceStack "relexpr" NoUncommittedContextInEvalError)
189 Just ctx -> pure ctx
190 Just ctx -> pure ctx
190
191
191runGraphRefRelationalExprM :: GraphRefRelationalExprEnv -> GraphRefRelationalExprM a -> Either RelationalError a
192runGraphRefRelationalExprM :: GraphRefRelationalExprEnv -> GraphRefRelationalExprM a -> Either RelationalError a
@@ -1131,6 +1132,7 @@ evalGraphRefAttrExpr (NakedAttributeExpr attr) = pure attr
1131
1132
1132-- for tuple type concrete resolution (Nothing ==> Maybe Int) when the attributes hint is Nothing, we need to first process all the tuples, then extract the concrete types on a per-attribute basis, then reprocess the tuples to include the concrete types
1133-- for tuple type concrete resolution (Nothing ==> Maybe Int) when the attributes hint is Nothing, we need to first process all the tuples, then extract the concrete types on a per-attribute basis, then reprocess the tuples to include the concrete types
1133evalGraphRefTupleExprs :: Maybe Attributes -> [GraphRefTupleExpr] -> GraphRefRelationalExprM [RelationTuple]
1134evalGraphRefTupleExprs :: Maybe Attributes -> [GraphRefTupleExpr] -> GraphRefRelationalExprM [RelationTuple]
1135+evalGraphRefTupleExprs _ [] = pure []
1134evalGraphRefTupleExprs mAttrs tupleExprs = do
1136evalGraphRefTupleExprs mAttrs tupleExprs = do
1135 tuples <- mapM (evalGraphRefTupleExpr mAttrs) tupleExprs
1137 tuples <- mapM (evalGraphRefTupleExpr mAttrs) tupleExprs
1136 finalAttrs <- case mAttrs of
1138 finalAttrs <- case mAttrs of
@@ -1150,8 +1152,13 @@ evalGraphRefTupleExprs mAttrs tupleExprs = do
1150 Left _ -> accAttr
1152 Left _ -> accAttr
1151 Right val -> val) (zip (V.toList $ tupleAttributes tup) acc)) (V.toList $ tupleAttributes headTuple) tailTuples
1153 Right val -> val) (zip (V.toList $ tupleAttributes tup) acc)) (V.toList $ tupleAttributes headTuple) tailTuples
1152 pure (A.attributesFromList mostResolvedTypes)
1154 pure (A.attributesFromList mostResolvedTypes)
1153− --is it OK to get the tConsMap like this and use it uniformly across the tuples- couldn't the tuple expressions use types from other parts of the graph? Maybe it's OK because this is only used
1155+ --strategy: if all the tuple expr transaction markers refer to one location, then we can pass the type constructor mapping from that location, otherwise, we cannot assume that the types are the same
1156+ tConsMap <- case singularTransactions tupleExprs of
1157+ SingularTransactionRef commonTransId -> do
1154− tConsMap <- typeConstructorMapping <$> gfDatabaseContextForMarker UncommittedContextMarker
1158+ typeConstructorMapping <$> gfDatabaseContextForMarker commonTransId
1159+ NoTransactionsRef -> pure [] --no custom type constructors are referenced, so no tConsMap is needed
1160+ -- if there are multiple transaction markers in the TupleExprs, then we can't assume a single type constructor mapping- this could be improved in the future, but if all the tuples are fully resolved, then we don't need further resolution
1161+ _ -> throwError TupleExprsReferenceMultipleMarkersError
1155 lift $ except $ validateAttributes tConsMap finalAttrs
1162 lift $ except $ validateAttributes tConsMap finalAttrs
1156 mapM (\tup -> lift $ except $ resolveTypesInTuple finalAttrs tConsMap tup) tuples
1163 mapM (\tup -> lift $ except $ resolveTypesInTuple finalAttrs tConsMap tup) tuples
1157
1164
@@ -1386,7 +1393,7 @@ typeForGraphRefRelationalExpr expr@(With withs _) = do
1386 case M.lookup macroName rvs of
1393 case M.lookup macroName rvs of
1387 Just _ -> lift $ except $ Left (RelVarAlreadyDefinedError macroName) --this error does not include the transaction marker, but should be good enough to identify the cause
1394 Just _ -> lift $ except $ Left (RelVarAlreadyDefinedError macroName) --this error does not include the transaction marker, but should be good enough to identify the cause
1388 Nothing -> pure ()
1395 Nothing -> pure ()
1389− mapM checkMacroName (map fst withs)
1396+ mapM_ checkMacroName (map fst withs)
1390 typeForGraphRefRelationalExpr expr'
1397 typeForGraphRefRelationalExpr expr'
1391
1398
1392evalGraphRefAttributeNames :: GraphRefAttributeNames -> GraphRefRelationalExpr -> GraphRefRelationalExprM (S.Set AttributeName)
1399evalGraphRefAttributeNames :: GraphRefAttributeNames -> GraphRefRelationalExpr -> GraphRefRelationalExprM (S.Set AttributeName)