@@ -1,7 +1,4 @@
1{-# LANGUAGE ScopedTypeVariables #-}
1{-# LANGUAGE ScopedTypeVariables #-}
2−{-# LANGUAGE FlexibleInstances #-}
3−{-# LANGUAGE FlexibleContexts #-}
4−{-# LANGUAGE OverloadedStrings #-}
5module ProjectM36.RelationalExpression where
2module ProjectM36.RelationalExpression where
6import ProjectM36.Relation
3import ProjectM36.Relation
7import ProjectM36.Tuple
4import ProjectM36.Tuple
@@ -16,38 +13,32 @@ import ProjectM36.DataTypes.Primitive
16import ProjectM36.AtomFunction
13import ProjectM36.AtomFunction
17import ProjectM36.DatabaseContextFunction
14import ProjectM36.DatabaseContextFunction
18import ProjectM36.Arbitrary
15import ProjectM36.Arbitrary
19−import ProjectM36.GraphRefRelationalExpr
20import ProjectM36.Transaction
16import ProjectM36.Transaction
21import qualified ProjectM36.Attribute as A
17import qualified ProjectM36.Attribute as A
22import qualified Data.Map as M
18import qualified Data.Map as M
23import qualified Data.HashSet as HS
19import qualified Data.HashSet as HS
24import qualified Data.Set as S
20import qualified Data.Set as S
25−import Control.Monad.State hiding (join)
21+import Control.Monad.RWS.Strict as RWS hiding (join)
26−import Data.Bifunctor (second)
22+import Control.Monad.Trans.Class (lift)
23+import Control.Exception
27import Data.Maybe
24import Data.Maybe
28import Data.Either
25import Data.Either
29import Data.Char (isUpper)
26import Data.Char (isUpper)
31−import qualified Data.List.NonEmpty as NE
32−import Data.Functor.Identity
33import qualified Data.Text as T
27import qualified Data.Text as T
34import qualified Data.Vector as V
28import qualified Data.Vector as V
35import qualified ProjectM36.TypeConstructorDef as TCD
29import qualified ProjectM36.TypeConstructorDef as TCD
36−import qualified Control.Monad.RWS.Strict as RWS
37−import Control.Monad.RWS.Strict (RWST, execRWST, runRWST)
38import Control.Monad.Except hiding (join)
30import Control.Monad.Except hiding (join)
39import Control.Monad.Trans.Except (except)
31import Control.Monad.Trans.Except (except)
40import Control.Monad.Reader as R hiding (join)
32import Control.Monad.Reader as R hiding (join)
41import ProjectM36.NormalizeExpr
33import ProjectM36.NormalizeExpr
42import ProjectM36.WithNameExpr
34import ProjectM36.WithNameExpr
43import Test.QuickCheck
35import Test.QuickCheck
44−import qualified Data.Functor.Foldable as Fold
36+import GHC
45−import Control.Applicative
46−#ifdef PM36_HASKELL_SCRIPTING
47−import GHC hiding (getContext)
48−import Control.Exception
49import GHC.Paths
37import GHC.Paths
50−#endif
38+import Data.Time.Clock
39+import Data.Time.Calendar
40+import qualified Data.List.NonEmpty as NE
41+import Data.Functor.Identity
52data DatabaseContextExprDetails = CountUpdatedTuples
43data DatabaseContextExprDetails = CountUpdatedTuples
@@ -75,6 +66,7 @@ mkDatabaseContextEvalState context = DatabaseContextEvalState {
75data RelationalExprEnv = RelationalExprEnv {
66data RelationalExprEnv = RelationalExprEnv {
76 re_context :: DatabaseContext,
67 re_context :: DatabaseContext,
77 re_graph :: TransactionGraph,
68 re_graph :: TransactionGraph,
69+ re_currentTransId :: TransactionId,
78 re_extra :: Maybe (Either RelationTuple Attributes)
70 re_extra :: Maybe (Either RelationTuple Attributes)
@@ -94,29 +86,36 @@ runRelationalExprM :: RelationalExprEnv -> RelationalExprM a -> Either Relationa
94runRelationalExprM env m = runIdentity (runExceptT (runReaderT m env))
86runRelationalExprM env m = runIdentity (runExceptT (runReaderT m env))
96reGraph :: RelationalExprM TransactionGraph
88reGraph :: RelationalExprM TransactionGraph
89+reGraph = re_graph <$> R.ask
91+currentTrans :: RelationalExprM Transaction
93+ tid <- re_currentTransId <$> R.ask
97−reGraph = asks re_graph
94+ graph <- re_graph <$> R.ask
95+ lift $ except $ transactionForId tid graph
99−reContext :: RelationalExprM DatabaseContext
97+reTransId :: RelationalExprM TransactionId
100−reContext = asks re_context
98+reTransId = re_currentTransId <$> R.ask
102−mkRelationalExprEnv :: DatabaseContext -> TransactionGraph -> RelationalExprEnv
100+mkRelationalExprEnv :: DatabaseContext -> TransactionId -> TransactionGraph -> RelationalExprEnv
103−mkRelationalExprEnv ctx graph =
101+mkRelationalExprEnv ctx currentTransId graph =
104 RelationalExprEnv
102 RelationalExprEnv
105 { re_context = ctx,
103 { re_context = ctx,
106 re_graph = graph,
104 re_graph = graph,
105+ re_currentTransId = currentTransId,
107 re_extra = Nothing }
106 re_extra = Nothing }
109askEnv :: GraphRefRelationalExprM GraphRefRelationalExprEnv
108askEnv :: GraphRefRelationalExprM GraphRefRelationalExprEnv
110askEnv = R.ask
109askEnv = R.ask
112mergeTuplesIntoGraphRefRelationalExprEnv :: RelationTuple -> GraphRefRelationalExprEnv -> GraphRefRelationalExprEnv
111mergeTuplesIntoGraphRefRelationalExprEnv :: RelationTuple -> GraphRefRelationalExprEnv -> GraphRefRelationalExprEnv
113−mergeTuplesIntoGraphRefRelationalExprEnv tupIn env =
112+mergeTuplesIntoGraphRefRelationalExprEnv tupIn e =
114− env { gre_extra = new_elems }
113+ e{ gre_extra = new_elems }
116 new_elems = Just (Left newTuple)
115 new_elems = Just (Left newTuple)
117− mergedTupMap = M.union (tupleToMap tupIn) (tupleToMap (envTuple env))
116+ mergedTupMap = M.union (tupleToMap tupIn) (tupleToMap (envTuple e))
118 newTuple = mkRelationTupleFromMap mergedTupMap
117 newTuple = mkRelationTupleFromMap mergedTupMap
120mergeAttributesIntoGraphRefRelationalExprEnv :: Attributes -> GraphRefRelationalExprEnv -> GraphRefRelationalExprEnv
119mergeAttributesIntoGraphRefRelationalExprEnv :: Attributes -> GraphRefRelationalExprEnv -> GraphRefRelationalExprEnv
121mergeAttributesIntoGraphRefRelationalExprEnv attrsIn e = e { gre_extra = newattrs }
120mergeAttributesIntoGraphRefRelationalExprEnv attrsIn e = e { gre_extra = newattrs }
@@ -142,12 +141,12 @@ data DatabaseContextEvalEnv = DatabaseContextEvalEnv
144mkDatabaseContextEvalEnv :: TransactionId -> TransactionGraph -> DatabaseContextEvalEnv
143mkDatabaseContextEvalEnv :: TransactionId -> TransactionGraph -> DatabaseContextEvalEnv
145−mkDatabaseContextEvalEnv = DatabaseContextEvalEnv
144+mkDatabaseContextEvalEnv tid graph = DatabaseContextEvalEnv tid graph
147type DatabaseContextEvalMonad a = RWST DatabaseContextEvalEnv () DatabaseContextEvalState (ExceptT RelationalError Identity) a
146type DatabaseContextEvalMonad a = RWST DatabaseContextEvalEnv () DatabaseContextEvalState (ExceptT RelationalError Identity) a
149runDatabaseContextEvalMonad :: DatabaseContext -> DatabaseContextEvalEnv -> DatabaseContextEvalMonad () -> Either RelationalError DatabaseContextEvalState
148runDatabaseContextEvalMonad :: DatabaseContext -> DatabaseContextEvalEnv -> DatabaseContextEvalMonad () -> Either RelationalError DatabaseContextEvalState
150−runDatabaseContextEvalMonad ctx env m = runIdentity (runExceptT (fst <$> execRWST m env freshEnv))
149+runDatabaseContextEvalMonad ctx env m = runIdentity (runExceptT (fst <$> (execRWST m env freshEnv)))
152 freshEnv = mkDatabaseContextEvalState ctx
151 freshEnv = mkDatabaseContextEvalState ctx
@@ -160,20 +159,18 @@ dbcGraph = dce_graph <$> RWS.ask
161dbcRelationalExprEnv :: DatabaseContextEvalMonad RelationalExprEnv
160dbcRelationalExprEnv :: DatabaseContextEvalMonad RelationalExprEnv
162dbcRelationalExprEnv =
161dbcRelationalExprEnv =
163− mkRelationalExprEnv <$> getStateContext <*> dbcGraph
162+ mkRelationalExprEnv <$> getStateContext <*> dbcTransId <*> dbcGraph
165getStateContext :: DatabaseContextEvalMonad DatabaseContext
164getStateContext :: DatabaseContextEvalMonad DatabaseContext
166−getStateContext = gets dbc_context
165+getStateContext = dbc_context <$> get
168putStateContext :: DatabaseContext -> DatabaseContextEvalMonad ()
167putStateContext :: DatabaseContext -> DatabaseContextEvalMonad ()
169putStateContext ctx' = do
168putStateContext ctx' = do
171− put (s {dbc_context = ctx', dbc_dirty = True})
170+ put (s {dbc_context = ctx'})
173−-- | The context is optionally passed down along in cases where the current context is uncommitted.
174data GraphRefRelationalExprEnv =
172data GraphRefRelationalExprEnv =
175 GraphRefRelationalExprEnv {
173 GraphRefRelationalExprEnv {
176− gre_context :: Maybe DatabaseContext,
177 gre_graph :: TransactionGraph,
174 gre_graph :: TransactionGraph,
178 gre_extra :: Maybe (Either RelationTuple Attributes)
175 gre_extra :: Maybe (Either RelationTuple Attributes)
@@ -185,26 +182,17 @@ gfTransForId tid = do
185 graph <- gfGraph
182 graph <- gfGraph
186 lift $ except $ transactionForId tid graph
183 lift $ except $ transactionForId tid graph
188−gfDatabaseContextForMarker :: GraphRefTransactionMarker -> GraphRefRelationalExprM DatabaseContext
189−gfDatabaseContextForMarker (TransactionMarker transId) = concreteDatabaseContext <$> gfTransForId transId
190−gfDatabaseContextForMarker UncommittedContextMarker = do
191− mctx <- gre_context <$> askEnv
193− Nothing -> throwError NoUncommittedContextInEvalError
194− Just ctx -> pure ctx
196runGraphRefRelationalExprM :: GraphRefRelationalExprEnv -> GraphRefRelationalExprM a -> Either RelationalError a
185runGraphRefRelationalExprM :: GraphRefRelationalExprEnv -> GraphRefRelationalExprM a -> Either RelationalError a
197runGraphRefRelationalExprM env m = runIdentity (runExceptT (runReaderT m env))
186runGraphRefRelationalExprM env m = runIdentity (runExceptT (runReaderT m env))
199−freshGraphRefRelationalExprEnv :: Maybe DatabaseContext -> TransactionGraph -> GraphRefRelationalExprEnv
188+freshGraphRefRelationalExprEnv :: TransactionGraph -> GraphRefRelationalExprEnv
200−freshGraphRefRelationalExprEnv mctx graph = GraphRefRelationalExprEnv {
189+freshGraphRefRelationalExprEnv graph = GraphRefRelationalExprEnv {
202 gre_graph = graph,
190 gre_graph = graph,
203 gre_extra = Nothing
191 gre_extra = Nothing
206gfGraph :: GraphRefRelationalExprM TransactionGraph
194gfGraph :: GraphRefRelationalExprM TransactionGraph
207−gfGraph = asks gre_graph
195+gfGraph = gre_graph <$> R.ask
209envContext :: RelationalExprEnv -> DatabaseContext
197envContext :: RelationalExprEnv -> DatabaseContext
210envContext = re_context
198envContext = re_context
@@ -212,27 +200,173 @@ envContext = re_context
212setEnvContext :: RelationalExprEnv -> DatabaseContext -> RelationalExprEnv
200setEnvContext :: RelationalExprEnv -> DatabaseContext -> RelationalExprEnv
213setEnvContext e ctx = e { re_context = ctx }
201setEnvContext e ctx = e { re_context = ctx }
204+--full evaluation down the graph
205+eval :: RelationalExpr -> RelationalExprState (Either RelationalError Relation)
208+ eGfExpr <- processRelationalExpr expr
210+ Left err -> pure (Left err)
211+ Right gfExpr -> pure $ evalGraphRefRelationalExpr gfExpr (re_graph env)
214+--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
215+evalRelationalExpr :: RelationalExpr -> RelationalExprState (Either RelationalError GraphRefRelationalExpr)
216+evalRelationalExpr (RelationVariable name _) = do
217+ relvarTable <- fmap (relationVariables . envContext) askEnv
218+ return $ case M.lookup name relvarTable of
219+ Just res -> Right res
220+ Nothing -> Left $ RelVarNotDefinedError name
222+evalRelationalExpr (Project attrNames expr) = do
223+ eAttrNameSet <- evalAttributeNames attrNames expr
224+ case eAttrNameSet of
225+ Left err -> pure (Left err)
226+ Right attrNameSet -> do
227+ rel <- evalRelationalExpr expr
229+ Right rel2 -> pure $ Right (Project (AttributeNames attrNameSet) rel2)
230+ Left err -> pure $ Left err
232+evalRelationalExpr (Union exprA exprB) = do
233+ relA <- evalRelationalExpr exprA
234+ relB <- evalRelationalExpr exprB
236+ Left err -> return $ Left err
237+ Right relA2 -> case relB of
238+ Left err -> return $ Left err
239+ Right relB2 -> return $ Right (Union relA2 relB2)
241+evalRelationalExpr (Join exprA exprB) = do
242+ relA <- evalRelationalExpr exprA
243+ relB <- evalRelationalExpr exprB
245+ Left err -> return $ Left err
246+ Right relA2 -> case relB of
247+ Left err -> return $ Left err
248+ Right relB2 -> return $ Right (Join relA2 relB2)
250+evalRelationalExpr (Difference exprA exprB) = do
251+ relA <- evalRelationalExpr exprA
252+ relB <- evalRelationalExpr exprB
254+ Left err -> return $ Left err
255+ Right relA2 -> case relB of
256+ Left err -> return $ Left err
257+ Right relB2 -> return $ Right (Difference relA2 relB2)
259+evalRelationalExpr (MakeStaticRelation attributeSet tupleSet) =
260+ case mkRelation attributeSet tupleSet of
261+ Right rel -> return $ Right (ExistingRelation rel)
262+ Left err -> return $ Left err
264+evalRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do
265+ currentContext <- fmap envContext askEnv
266+ let tConss = typeConstructorMapping currentContext
267+ -- 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
269+ mAttrs <- case mAttrExprs of
271+ Just . A.attributesFromList <$> mapM evalGraphRefAttrExpr (fromMaybe [] mAttrExprs)
272+ Nothing -> pure Nothing
273+ tuples <- mapM (liftE . evalTupleExpr mAttrs) tupleExprs
274+ let attrs = fromMaybe firstTupleAttrs mAttrs
275+ firstTupleAttrs = if null tuples then A.emptyAttributes else tupleAttributes (head tuples)
276+ expr <- either throwE pure (mkRelation attrs (RelationTupleSet tuples))
277+ pure (ExistingRelation expr)
279+evalRelationalExpr (ExistingRelation rel) = pure (Right (ExistingRelation rel))
281+evalRelationalExpr (Rename oldAttrName newAttrName relExpr) = do
282+ evald <- evalRelationalExpr relExpr
284+ Right expr -> return $ Right (Rename oldAttrName newAttrName expr)
285+ Left err -> return $ Left err
287+evalRelationalExpr (Group oldAttrNames newAttrName relExpr) = do
288+ eOldAttrNameSet <- evalAttributeNames oldAttrNames relExpr
289+ case eOldAttrNameSet of
290+ Left err -> pure (Left err)
291+ Right oldAttrNameSet -> do
292+ evald <- evalRelationalExpr relExpr
294+ Right expr -> return $ Right (Group (AttributeNames oldAttrNameSet) newAttrName expr)
295+ Left err -> return $ Left err
297+evalRelationalExpr (Ungroup attrName relExpr) = do
298+ evald <- evalRelationalExpr relExpr
300+ Right expr -> return $ Right (Ungroup attrName expr)
301+ Left err -> return $ Left err
303+evalRelationalExpr (Restrict predicateExpr relExpr) = do
304+ evald <- evalRelationalExpr relExpr
305+ pred <- processRestrictionPredicateExpr predicateExpr
307+ Left err -> return $ Left err
309+ pure $ Right (Restrict pred expr)
311+evalRelationalExpr (Equals relExprA relExprB) = do
312+ evaldA <- evalRelationalExpr relExprA
313+ evaldB <- evalRelationalExpr relExprB
315+ Left err -> return $ Left err
316+ Right exprA -> case evaldB of
317+ Left err -> return $ Left err
318+ Right exprB -> return $ Right (Equals exprA exprB)
320+evalRelationalExpr (With views mainExpr) = do
323+ let addScopedView ctx (vname,vexpr) = if vname `M.member` relationVariables ctx then
324+ Left (RelVarAlreadyDefinedError vname)
326+ case runState (evalDatabaseContextExpr (Assign vname vexpr)) (freshDatabaseState ctx) of
327+ (Left err,_) -> Left err
328+ (Right (), (ctx',_,_)) -> Right ctx'
330+ case foldM addScopedView (stateElemsContext rstate) views of
331+ Left err -> return $ Left err
333+ let evalMainExpr expr = runReader (evalRelationalExpr expr) (RelationalExprEnv ctx'')
334+ case evalMainExpr mainExpr of
335+ Left err -> return $ Left err
336+ Right rel -> return $ Right rel
338+--warning: copy-pasta from above- refactor
339+evalRelationalExpr (NotEquals relExprA relExprB) = do
340+ evaldA <- evalRelationalExpr relExprA
341+ evaldB <- evalRelationalExpr relExprB
343+ Left err -> return $ Left err
344+ Right exprA -> case evaldB of
345+ Left err -> return $ Left err
346+ Right exprB -> return $ Right (NotEquals exprA exprB)
348+-- extending a relation adds a single attribute with the results of the per-tuple expression evaluated
349+evalRelationalExpr (Extend tupleExpression relExpr) = do
350+ eExpr <- evalRelationalExpr relExpr
352+ Left err -> pure (Left err)
354+ tupProc <- processExtendTupleExpr tupleExpression
355+ pure (Right (Extend tupProc expr))
215--helper function to process relation variable creation/assignment
357--helper function to process relation variable creation/assignment
216setRelVar :: RelVarName -> GraphRefRelationalExpr -> DatabaseContextEvalMonad ()
358setRelVar :: RelVarName -> GraphRefRelationalExpr -> DatabaseContextEvalMonad ()
217setRelVar relVarName relExpr = do
359setRelVar relVarName relExpr = do
218 currentContext <- getStateContext
361 currentContext <- getStateContext
219− --prevent recursive relvar definition by resolving references to relvars in previous states
220− relExpr' <- resolve relExpr
221− let newRelVars = M.insert relVarName relExpr' $ relationVariables currentContext
362+ let newRelVars = M.insert relVarName relExpr $ relationVariables currentContext
222 potentialContext = currentContext { relationVariables = newRelVars }
363 potentialContext = currentContext { relationVariables = newRelVars }
223− --optimization: if the relexpr is unchanged, skip the update
224− if M.lookup relVarName (relationVariables currentContext) == Just relExpr then
227− --determine when to check constraints
364+ --determine when to check constraints
228− graph <- dbcGraph
365+ graph <- dbcGraph
229− tid <- dbcTransId
366+ tid <- dbcTransId
230− case checkConstraints potentialContext tid graph of
367+ case checkConstraints potentialContext tid graph of
231− Left err -> dbErr err
368+ Left err -> dbErr err
232− Right _ -> putStateContext potentialContext
369+ Right _ -> putStateContext potentialContext
234−--fast-path insertion- we already know that the previous relvar validated correctly, so we can validate just the relation that is being inserted for attribute matches- without this, even a single tuple relation inserted causes the entire relation to be re-validated unnecessarily
235−--insertIntoRelVar :: RelVarName -> GraphRefRelationalExpr -> DatabaseContextEvalMonad ()
237-- it is not an error to delete a relvar which does not exist, just like it is not an error to insert a pre-existing tuple into a relation
371-- it is not an error to delete a relvar which does not exist, just like it is not an error to insert a pre-existing tuple into a relation
238deleteRelVar :: RelVarName -> DatabaseContextEvalMonad ()
372deleteRelVar :: RelVarName -> DatabaseContextEvalMonad ()
@@ -251,17 +385,19 @@ evalGraphRefDatabaseContextExpr :: GraphRefDatabaseContextExpr -> DatabaseContex
251evalGraphRefDatabaseContextExpr NoOperation = pure ()
385evalGraphRefDatabaseContextExpr NoOperation = pure ()
253evalGraphRefDatabaseContextExpr (Define relVarName attrExprs) = do
387evalGraphRefDatabaseContextExpr (Define relVarName attrExprs) = do
254− context <- getStateContext
255 relvars <- fmap relationVariables getStateContext
388 relvars <- fmap relationVariables getStateContext
256 tConss <- fmap typeConstructorMapping getStateContext
389 tConss <- fmap typeConstructorMapping getStateContext
257 graph <- dbcGraph
390 graph <- dbcGraph
258 let eAttrs = runGraphRefRelationalExprM gfEnv (mapM evalGraphRefAttrExpr attrExprs)
391 let eAttrs = runGraphRefRelationalExprM gfEnv (mapM evalGraphRefAttrExpr attrExprs)
259− gfEnv = freshGraphRefRelationalExprEnv (Just context) graph
392+ gfEnv = freshGraphRefRelationalExprEnv graph
260 case eAttrs of
393 case eAttrs of
261− Left err -> dbErr err
394+ Left err -> dbErr err
262 Right attrsList -> do
395 Right attrsList -> do
263− lift $ except $ validateAttributes tConss (A.attributesFromList attrsList)
396+ let atomTypeErrs = lefts $ map ((`validateAtomType` tConss) . A.atomType) attrsList
397+ if not (null atomTypeErrs) then
398+ dbErr (someErrors atomTypeErrs)
264− case M.member relVarName relvars of
400+ case M.member relVarName relvars of
265 True -> dbErr (RelVarAlreadyDefinedError relVarName)
401 True -> dbErr (RelVarAlreadyDefinedError relVarName)
266 False -> setRelVar relVarName (ExistingRelation emptyRelation)
402 False -> setRelVar relVarName (ExistingRelation emptyRelation)
@@ -274,17 +410,13 @@ evalGraphRefDatabaseContextExpr (Assign relVarName expr) = do
274 graph <- re_graph <$> dbcRelationalExprEnv
410 graph <- re_graph <$> dbcRelationalExprEnv
275 context <- getStateContext
411 context <- getStateContext
276 let existingRelVar = M.lookup relVarName (relationVariables context)
412 let existingRelVar = M.lookup relVarName (relationVariables context)
277− reEnv = freshGraphRefRelationalExprEnv (Just context) graph
278− eNewExprType = runGraphRefRelationalExprM reEnv (typeForGraphRefRelationalExpr expr)
279 case existingRelVar of
413 case existingRelVar of
280 Nothing -> do
414 Nothing -> do
281− case runGraphRefRelationalExprM reEnv (typeForGraphRefRelationalExpr expr) of
282− Left err -> dbErr err
284− lift $ except $ validateAttributes (typeConstructorMapping context) (attributes reltype)
285− setRelVar relVarName expr
415+ setRelVar relVarName expr
286 Just existingRel -> do
416 Just existingRel -> do
287 let eExpectedType = runGraphRefRelationalExprM reEnv (typeForGraphRefRelationalExpr existingRel)
417 let eExpectedType = runGraphRefRelationalExprM reEnv (typeForGraphRefRelationalExpr existingRel)
418+ eNewExprType = runGraphRefRelationalExprM reEnv (typeForGraphRefRelationalExpr expr)
419+ reEnv = freshGraphRefRelationalExprEnv graph
288 case eExpectedType of
420 case eExpectedType of
289 Left err -> dbErr err
421 Left err -> dbErr err
290 Right expectedType ->
422 Right expectedType ->
@@ -292,53 +424,44 @@ evalGraphRefDatabaseContextExpr (Assign relVarName expr) = do
292 Left err -> dbErr err
424 Left err -> dbErr err
293 Right newExprType -> do
425 Right newExprType -> do
294 if newExprType == expectedType then do
426 if newExprType == expectedType then do
295− lift $ except $ validateAttributes (typeConstructorMapping context) (attributes newExprType)
296 setRelVar relVarName expr
427 setRelVar relVarName expr
298 dbErr (RelationTypeMismatchError (attributes expectedType) (attributes newExprType))
429 dbErr (RelationTypeMismatchError (attributes expectedType) (attributes newExprType))
300evalGraphRefDatabaseContextExpr (Insert relVarName relExpr) = do
431evalGraphRefDatabaseContextExpr (Insert relVarName relExpr) = do
301− gfExpr <- relVarByName relVarName
432+ transId <- dbcTransId
302− let optExpr = applyUnionCollapse (Union
305− evalGraphRefDatabaseContextExpr (Assign relVarName optExpr)
433+ evalGraphRefDatabaseContextExpr (Assign relVarName
435+ (RelationVariable relVarName transId)
307evalGraphRefDatabaseContextExpr (Delete relVarName predicate) = do
438evalGraphRefDatabaseContextExpr (Delete relVarName predicate) = do
308− gfExpr <- relVarByName relVarName
439+ transId <- dbcTransId
440+ let rv = RelationVariable relVarName transId
309− let optExpr = applyRestrictionCollapse (Restrict (NotPredicate predicate) gfExpr)
441+ setRelVar relVarName (Restrict (NotPredicate predicate) rv)
310− setRelVar relVarName optExpr
312--union of restricted+updated portion and the unrestricted+unupdated portion
443--union of restricted+updated portion and the unrestricted+unupdated portion
313evalGraphRefDatabaseContextExpr (Update relVarName atomExprMap pred') = do
444evalGraphRefDatabaseContextExpr (Update relVarName atomExprMap pred') = do
314− rvExpr <- relVarByName relVarName
315− graph <- re_graph <$> dbcRelationalExprEnv
316 context <- getStateContext
445 context <- getStateContext
317− let reEnv = freshGraphRefRelationalExprEnv (Just context) graph
446+ transId <- dbcTransId
318− --get the current attributes name in the relvar to ensure that we don't conflict when renaming
447+ graph <- dbcGraph
319− eExprType = runGraphRefRelationalExprM reEnv (typeForGraphRefRelationalExpr rvExpr)
448+ let relVarMap = relationVariables context
320− exprType' <- case eExprType of
449+ case M.lookup relVarName relVarMap of
321− Left err -> throwError err
450+ Nothing -> dbErr (RelVarNotDefinedError relVarName)
322− Right t -> pure t
451+ Just _ -> do
323− let unrestrictedPortion = Restrict (NotPredicate pred') rvExpr
452+ let unrestrictedPortion = Restrict (NotPredicate pred') rv
324− tmpAttr = tmpAttrC 1
453+ rv = RelationVariable relVarName transId
325− tmpAttrC :: Int -> AttributeName -> AttributeName
454+ tmpAttr attr = "_tmp_" <> attr --this could certainly be improved to verify that there is no attribute name conflict
327− let tmpAttrName = "_tmp_" <> T.pack (show c) <> attr in
328− if tmpAttrName `S.member` A.attributeNameSet (attributes exprType') then
332− updateAttr nam atomExpr = Extend (AttributeExtendTupleExpr (tmpAttr nam) atomExpr)
455+ updateAttr nam atomExpr = Extend (AttributeExtendTupleExpr (tmpAttr nam) atomExpr)
333− projectAndRename attr expr = Rename (tmpAttr attr) attr (Project (InvertedAttributeNames (S.singleton attr)) expr)
456+ projectAndRename attr expr = Rename (tmpAttr attr) attr (Project (InvertedAttributeNames (S.singleton attr)) expr)
334− restrictedPortion = Restrict pred' rvExpr
457+ --TODO restrictedPortion = Restrict pred'
335− updated = foldr (\(oldname, atomExpr) accum ->
458+ updated = foldr (\(oldname, atomExpr) accum ->
336− let procAtomExpr = runProcessExprM UncommittedContextMarker (processAtomExpr atomExpr) in
459+ let procAtomExpr = runProcessExprM transId graph (processAtomExpr atomExpr) in
337 updateAttr oldname procAtomExpr accum
460 updateAttr oldname procAtomExpr accum
338− ) restrictedPortion (M.toList atomExprMap)
461+ ) rv (M.toList atomExprMap)
339 -- the atomExprMap could reference other attributes, so we must perform multi-pass folds
462 -- the atomExprMap could reference other attributes, so we must perform multi-pass folds
340− updatedPortion = foldr projectAndRename updated (M.keys atomExprMap)
463+ updatedPortion = foldr projectAndRename updated (M.keys atomExprMap)
341− setRelVar relVarName (Union unrestrictedPortion updatedPortion)
464+ setRelVar relVarName (Union unrestrictedPortion updatedPortion)
343evalGraphRefDatabaseContextExpr (AddInclusionDependency newDepName newDep) = do
466evalGraphRefDatabaseContextExpr (AddInclusionDependency newDepName newDep) = do
344 currContext <- getStateContext
467 currContext <- getStateContext
@@ -350,8 +473,6 @@ evalGraphRefDatabaseContextExpr (AddInclusionDependency newDepName newDep) = do
350 dbErr (InclusionDependencyNameInUseError newDepName)
473 dbErr (InclusionDependencyNameInUseError newDepName)
352 let potentialContext = currContext { inclusionDependencies = newDeps }
475 let potentialContext = currContext { inclusionDependencies = newDeps }
353− -- if the potential context passes all constraints, then save it
354− -- potential optimization: validate only the new constraint- all old constraints must already hold
355 case checkConstraints potentialContext transId graph of
476 case checkConstraints potentialContext transId graph of
356 Left err -> dbErr err
477 Left err -> dbErr err
357 Right _ ->
478 Right _ ->
@@ -396,9 +517,9 @@ evalGraphRefDatabaseContextExpr (AddTypeConstructor tConsDef dConsDefList) = do
396 let oldTypes = typeConstructorMapping currentContext
517 let oldTypes = typeConstructorMapping currentContext
397 tConsName = TCD.name tConsDef
518 tConsName = TCD.name tConsDef
398 -- validate that the constructor's types exist
519 -- validate that the constructor's types exist
399− case validateTypeConstructorDef tConsDef dConsDefList oldTypes of
520+ case validateTypeConstructorDef tConsDef dConsDefList of
400− Left err -> throwError err
521+ errs@(_:_) -> dbErr (someErrors errs)
401− Right () | T.null tConsName || not (isUpper (T.head tConsName)) -> dbErr (InvalidAtomTypeName tConsName)
522+ [] | T.null tConsName || not (isUpper (T.head tConsName)) -> dbErr (InvalidAtomTypeName tConsName)
402 | isJust (findTypeConstructor tConsName oldTypes) -> dbErr (AtomTypeNameInUseError tConsName)
523 | isJust (findTypeConstructor tConsName oldTypes) -> dbErr (AtomTypeNameInUseError tConsName)
403 | otherwise -> do
524 | otherwise -> do
404 let newTypes = oldTypes ++ [(tConsDef, dConsDefList)]
525 let newTypes = oldTypes ++ [(tConsDef, dConsDefList)]
@@ -414,10 +535,15 @@ evalGraphRefDatabaseContextExpr (RemoveTypeConstructor tConsName) = do
414 let newTypes = filter (\(tCons, _) -> TCD.name tCons /= tConsName) oldTypes
535 let newTypes = filter (\(tCons, _) -> TCD.name tCons /= tConsName) oldTypes
415 putStateContext $ currentContext { typeConstructorMapping = newTypes }
536 putStateContext $ currentContext { typeConstructorMapping = newTypes }
417−evalGraphRefDatabaseContextExpr (MultipleExpr exprs) =
538+evalGraphRefDatabaseContextExpr (MultipleExpr _) = do
418 --the multiple expressions must pass the same context around- not the old unmodified context
539 --the multiple expressions must pass the same context around- not the old unmodified context
419− mapM_ evalGraphRefDatabaseContextExpr exprs
541+{- evald <- forM exprs (\expr -> evalGraphRefDatabaseContextExpr expr)
420−
542+ --some lifting magic needed here
545+ errs -> dbErr (someErrors errs)
421evalGraphRefDatabaseContextExpr (RemoveAtomFunction funcName) = do
547evalGraphRefDatabaseContextExpr (RemoveAtomFunction funcName) = do
422 currentContext <- getStateContext
548 currentContext <- getStateContext
423 let atomFuncs = atomFunctions currentContext
549 let atomFuncs = atomFunctions currentContext
@@ -446,9 +572,9 @@ evalGraphRefDatabaseContextExpr (ExecuteDatabaseContextFunction funcName atomArg
446 context <- getStateContext
572 context <- getStateContext
447 graph <- dbcGraph
573 graph <- dbcGraph
448 --resolve atom arguments
574 --resolve atom arguments
449− let eAtomTypes = mapM (runGraphRefRelationalExprM gfEnv . typeForGraphRefAtomExpr emptyAttributes) atomArgExprs
575+ let eAtomTypes = mapM (\atomExpr -> runGraphRefRelationalExprM gfEnv (typeForGraphRefAtomExpr emptyAttributes atomExpr)) atomArgExprs
450 eFunc = databaseContextFunctionForName funcName (dbcFunctions context)
576 eFunc = databaseContextFunctionForName funcName (dbcFunctions context)
451− gfEnv = freshGraphRefRelationalExprEnv (Just context) graph
577+ gfEnv = freshGraphRefRelationalExprEnv graph
452 case eFunc of
578 case eFunc of
453 Left err -> dbErr err
579 Left err -> dbErr err
454 Right func -> do
580 Right func -> do
@@ -461,13 +587,12 @@ evalGraphRefDatabaseContextExpr (ExecuteDatabaseContextFunction funcName atomArg
461 case eAtomTypes of
587 case eAtomTypes of
462 Left err -> dbErr err
588 Left err -> dbErr err
463 Right atomTypes -> do
589 Right atomTypes -> do
464− let mValidTypes = zipWith (\ expType actType
465− -> case atomTypeVerify expType actType of
590+ let mValidTypes = map (\(expType, actType) -> case atomTypeVerify expType actType of
466− Left err -> Just err
591+ Left err -> Just err
468− (dbcFuncType func) atomTypes
592+ Right _ -> Nothing) (zip (dbcFuncType func) atomTypes)
469 typeErrors = catMaybes mValidTypes
593 typeErrors = catMaybes mValidTypes
470− eAtomArgs = map (runGraphRefRelationalExprM gfEnv . evalGraphRefAtomExpr emptyTuple) atomArgExprs
594+ eAtomArgs = unimplemented
595+ --eAtomArgs = map (\arg -> runReader (evalAtomExpr emptyTuple arg) relExprState) atomArgExprs
471 if length (lefts eAtomArgs) > 1 then
596 if length (lefts eAtomArgs) > 1 then
472 dbErr (someErrors (lefts eAtomArgs))
597 dbErr (someErrors (lefts eAtomArgs))
473 else if not (null typeErrors) then
598 else if not (null typeErrors) then
@@ -476,6 +601,7 @@ evalGraphRefDatabaseContextExpr (ExecuteDatabaseContextFunction funcName atomArg
476 case evalDatabaseContextFunction func (rights eAtomArgs) context of
601 case evalDatabaseContextFunction func (rights eAtomArgs) context of
477 Left err -> dbErr err
602 Left err -> dbErr err
478 Right newContext -> putStateContext newContext
603 Right newContext -> putStateContext newContext
479data DatabaseContextIOEvalEnv = DatabaseContextIOEvalEnv
605data DatabaseContextIOEvalEnv = DatabaseContextIOEvalEnv
480 { dbcio_transId :: TransactionId,
606 { dbcio_transId :: TransactionId,
481 dbcio_graph :: TransactionGraph,
607 dbcio_graph :: TransactionGraph,
@@ -511,15 +637,10 @@ getDBCIOContext = dbc_context <$> RWS.get
511getDBCIORelationalExprEnv :: DatabaseContextIOEvalMonad RelationalExprEnv
637getDBCIORelationalExprEnv :: DatabaseContextIOEvalMonad RelationalExprEnv
512getDBCIORelationalExprEnv = do
638getDBCIORelationalExprEnv = do
513 context <- getDBCIOContext
639 context <- getDBCIOContext
514− mkRelationalExprEnv context . dbcio_graph <$> RWS.ask
641+ pure $ mkRelationalExprEnv context (dbcio_transId env) (dbcio_graph env)
516evalGraphRefDatabaseContextIOExpr :: GraphRefDatabaseContextIOExpr -> DatabaseContextIOEvalMonad (Either RelationalError ())
643evalGraphRefDatabaseContextIOExpr :: GraphRefDatabaseContextIOExpr -> DatabaseContextIOEvalMonad (Either RelationalError ())
517−#if !defined(PM36_HASKELL_SCRIPTING)
518−evalGraphRefDatabaseContextIOExpr AddAtomFunction{} = pure (Left (ScriptError ScriptCompilationDisabledError))
519−evalGraphRefDatabaseContextIOExpr AddDatabaseContextFunction{} = pure (Left (ScriptError ScriptCompilationDisabledError))
520−evalGraphRefDatabaseContextIOExpr LoadAtomFunctions{} = pure (Left (ScriptError ScriptCompilationDisabledError))
521−evalGraphRefDatabaseContextIOExpr LoadDatabaseContextFunctions{} = pure (Left (ScriptError ScriptCompilationDisabledError))
523evalGraphRefDatabaseContextIOExpr (AddAtomFunction funcName funcType script) = do
644evalGraphRefDatabaseContextIOExpr (AddAtomFunction funcName funcType script) = do
524 eScriptSession <- requireScriptSession
645 eScriptSession <- requireScriptSession
525 currentContext <- getDBCIOContext
646 currentContext <- getDBCIOContext
@@ -553,6 +674,7 @@ evalGraphRefDatabaseContextIOExpr (AddAtomFunction funcName funcType script) = d
553 Right eContext -> case eContext of
674 Right eContext -> case eContext of
554 Left err -> pure (Left err)
675 Left err -> pure (Left err)
555 Right context' -> putDBCIOContext context'
676 Right context' -> putDBCIOContext context'
556evalGraphRefDatabaseContextIOExpr (AddDatabaseContextFunction funcName funcType script) = do
678evalGraphRefDatabaseContextIOExpr (AddDatabaseContextFunction funcName funcType script) = do
557 eScriptSession <- requireScriptSession
679 eScriptSession <- requireScriptSession
558 currentContext <- getDBCIOContext
680 currentContext <- getDBCIOContext
@@ -594,6 +716,7 @@ evalGraphRefDatabaseContextIOExpr (AddDatabaseContextFunction funcName funcType
594 Right eContext -> case eContext of
716 Right eContext -> case eContext of
595 Left err -> pure (Left err)
717 Left err -> pure (Left err)
596 Right context' -> putDBCIOContext context'
718 Right context' -> putDBCIOContext context'
597evalGraphRefDatabaseContextIOExpr (LoadAtomFunctions modName funcName modPath) = do
720evalGraphRefDatabaseContextIOExpr (LoadAtomFunctions modName funcName modPath) = do
598 currentContext <- getDBCIOContext
721 currentContext <- getDBCIOContext
599 eLoadFunc <- liftIO $ loadAtomFunctions (T.unpack modName) (T.unpack funcName) modPath
722 eLoadFunc <- liftIO $ loadAtomFunctions (T.unpack modName) (T.unpack funcName) modPath
@@ -610,7 +733,7 @@ evalGraphRefDatabaseContextIOExpr (LoadDatabaseContextFunctions modName funcName
610 Right dbcListFunc -> let newContext = currentContext { dbcFunctions = mergedFuncs }
733 Right dbcListFunc -> let newContext = currentContext { dbcFunctions = mergedFuncs }
611 mergedFuncs = HS.union (dbcFunctions currentContext) (HS.fromList dbcListFunc)
734 mergedFuncs = HS.union (dbcFunctions currentContext) (HS.fromList dbcListFunc)
612 in putDBCIOContext newContext
735 in putDBCIOContext newContext
614evalGraphRefDatabaseContextIOExpr (CreateArbitraryRelation relVarName attrExprs range) = do
737evalGraphRefDatabaseContextIOExpr (CreateArbitraryRelation relVarName attrExprs range) = do
616 currentContext <- getDBCIOContext
739 currentContext <- getDBCIOContext
@@ -628,7 +751,7 @@ evalGraphRefDatabaseContextIOExpr (CreateArbitraryRelation relVarName attrExprs
628 case existingRelVar of
751 case existingRelVar of
629 Nothing -> pure $ Left (RelVarNotDefinedError relVarName)
752 Nothing -> pure $ Left (RelVarNotDefinedError relVarName)
630 Just existingRel -> do
753 Just existingRel -> do
631− let gfEnv = freshGraphRefRelationalExprEnv (Just currentContext) graph
754+ let gfEnv = freshGraphRefRelationalExprEnv graph
632 case runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr existingRel) of
755 case runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr existingRel) of
633 Left err -> pure (Left err)
756 Left err -> pure (Left err)
634 Right relType -> do
757 Right relType -> do
@@ -642,36 +765,44 @@ evalGraphRefDatabaseContextIOExpr (CreateArbitraryRelation relVarName attrExprs
642 Left err -> pure (Left err)
765 Left err -> pure (Left err)
643 Right dbstate' -> putDBCIOContext (dbc_context dbstate')
766 Right dbstate' -> putDBCIOContext (dbc_context dbstate')
769+updateTupleWithAtomExprs :: M.Map AttributeName AtomExpr -> DatabaseContext -> TransactionGraph -> RelationTuple -> Either RelationalError RelationTuple
770+updateTupleWithAtomExprs exprMap context graph tupIn = do
771+ --resolve all atom exprs
773+ atomsAssoc <- mapM (\(attrName, atomExpr) -> do
774+ let atom = unimplemented
775+ --atom <- runReader (evalAtomExpr tupIn atomExpr) (mkRelationalExprState context graph)
776+ pure (attrName, atom)
777+ ) (M.toList exprMap)
778+ pure (updateTupleWithAtoms (M.fromList atomsAssoc) tupIn)
645--run verification on all constraints
780--run verification on all constraints
646checkConstraints :: DatabaseContext -> TransactionId -> TransactionGraph -> Either RelationalError ()
781checkConstraints :: DatabaseContext -> TransactionId -> TransactionGraph -> Either RelationalError ()
647−checkConstraints context transId graph@(TransactionGraph graphHeads transSet) = do
782+checkConstraints context transId graph@(TransactionGraph graphHeads transSet) =
648 mapM_ (uncurry checkIncDep) (M.toList deps)
783 mapM_ (uncurry checkIncDep) (M.toList deps)
650 potentialGraph = TransactionGraph graphHeads (S.insert tempTrans transSet)
785 potentialGraph = TransactionGraph graphHeads (S.insert tempTrans transSet)
651 tempStamp = UTCTime { utctDay = fromGregorian 2000 1 1,
786 tempStamp = UTCTime { utctDay = fromGregorian 2000 1 1,
652 utctDayTime = secondsToDiffTime 0 }
787 utctDayTime = secondsToDiffTime 0 }
653 tempSchemas = Schemas context M.empty
788 tempSchemas = Schemas context M.empty
654− tempTrans = Transaction U.nil tempTransInfo tempSchemas
655− tempTransInfo = TransactionInfo { parents = transId NE.:| [],
789+ tempTrans = Transaction U.nil (TransactionInfo (transId NE.:| []) tempStamp) tempSchemas
660 deps = inclusionDependencies context
791 deps = inclusionDependencies context
661 -- no optimization available here, really? perhaps the optimizer should be passed down to here or the eval function should be passed through the environment
792 -- no optimization available here, really? perhaps the optimizer should be passed down to here or the eval function should be passed through the environment
662 checkIncDep depName (InclusionDependency subsetExpr supersetExpr) = do
793 checkIncDep depName (InclusionDependency subsetExpr supersetExpr) = do
663− let process = runProcessExprM UncommittedContextMarker
794+ let process = runProcessExprM transId graph
664 gfSubsetExpr = process (processRelationalExpr subsetExpr)
795 gfSubsetExpr = process (processRelationalExpr subsetExpr)
665 gfSupersetExpr = process (processRelationalExpr supersetExpr)
796 gfSupersetExpr = process (processRelationalExpr supersetExpr)
666 --if both expressions are of a single-attribute (such as with a simple foreign key), the names of the attributes are irrelevant (they need not match) because the expression is unambiguous, but special-casing this to rename the attribute automatically would not be orthogonal behavior and probably cause confusion. Instead, special case the error to make it clear.
797 --if both expressions are of a single-attribute (such as with a simple foreign key), the names of the attributes are irrelevant (they need not match) because the expression is unambiguous, but special-casing this to rename the attribute automatically would not be orthogonal behavior and probably cause confusion. Instead, special case the error to make it clear.
667− let gfEnv = freshGraphRefRelationalExprEnv (Just context) graph
798+ let gfEnv = freshGraphRefRelationalExprEnv graph
668 runGfRel = runGraphRefRelationalExprM gfEnv
799 runGfRel = runGraphRefRelationalExprM gfEnv
669 typeSub <- runGfRel (typeForGraphRefRelationalExpr gfSubsetExpr)
800 typeSub <- runGfRel (typeForGraphRefRelationalExpr gfSubsetExpr)
670 typeSuper <- runGfRel (typeForGraphRefRelationalExpr gfSupersetExpr)
801 typeSuper <- runGfRel (typeForGraphRefRelationalExpr gfSupersetExpr)
671 when (typeSub /= typeSuper) (Left (RelationTypeMismatchError (attributes typeSub) (attributes typeSuper)))
802 when (typeSub /= typeSuper) (Left (RelationTypeMismatchError (attributes typeSub) (attributes typeSuper)))
672 let checkExpr = Equals gfSupersetExpr (Union gfSubsetExpr gfSupersetExpr)
803 let checkExpr = Equals gfSupersetExpr (Union gfSubsetExpr gfSupersetExpr)
673 gfEvald = runGraphRefRelationalExprM gfEnv' (evalGraphRefRelationalExpr checkExpr)
804 gfEvald = runGraphRefRelationalExprM gfEnv' (evalGraphRefRelationalExpr checkExpr)
674− gfEnv' = freshGraphRefRelationalExprEnv (Just context) potentialGraph
805+ gfEnv' = freshGraphRefRelationalExprEnv potentialGraph
675 case gfEvald of
806 case gfEvald of
676 Left err -> Left err
807 Left err -> Left err
677 Right resultRel -> if resultRel == relationTrue then
808 Right resultRel -> if resultRel == relationTrue then
@@ -687,11 +818,20 @@ typeForRelationalExpr expr = do
687 --replace the relationVariables context element with a cloned set of relation devoid of tuples
818 --replace the relationVariables context element with a cloned set of relation devoid of tuples
688 --evalRelationalExpr could still return an existing relation with tuples, so strip them
819 --evalRelationalExpr could still return an existing relation with tuples, so strip them
689 graph <- reGraph
820 graph <- reGraph
690− context <- reContext
821+ transId <- reTransId
691− let gfExpr = runProcessExprM UncommittedContextMarker (processRelationalExpr expr)
822+ let gfExpr = runProcessExprM transId graph (processRelationalExpr expr)
692− gfEnv = freshGraphRefRelationalExprEnv (Just context) graph
823+ gfEnv = freshGraphRefRelationalExprEnv graph
693 runGf = runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr gfExpr)
824 runGf = runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr gfExpr)
694− lift $ except runGf
825+ lift $ except $ runGf
827+--returns a database context with all tuples removed
828+--this is useful for type checking and optimization
830+contextWithEmptyTupleSets :: DatabaseContext -> DatabaseContext
831+contextWithEmptyTupleSets contextIn = contextIn { relationVariables = relVars }
833+ relVars = M.map (\rel -> ExistingRelation (Relation (attributes rel) emptyTupleSet)) (relationVariables contextIn)
696liftE :: (Monad m) => m (Either a b) -> ExceptT a m b
836liftE :: (Monad m) => m (Either a b) -> ExceptT a m b
697liftE v = do
837liftE v = do
@@ -740,7 +880,7 @@ predicateRestrictionFilter _ (RelationalExprPredicate relExpr) = do
741predicateRestrictionFilter attrs (AttributeEqualityPredicate attrName atomExpr) = do
881predicateRestrictionFilter attrs (AttributeEqualityPredicate attrName atomExpr) = do
742 env <- askEnv
882 env <- askEnv
743− let attrs' = A.union attrs (envAttributes env)
883+ let attrs' = envAttributes env
744 ctxtup' = envTuple env
884 ctxtup' = envTuple env
745 atomExprType <- typeForGraphRefAtomExpr attrs' atomExpr
885 atomExprType <- typeForGraphRefAtomExpr attrs' atomExpr
746 attr <- lift $ except $ case A.attributeForName attrName attrs of
886 attr <- lift $ except $ case A.attributeForName attrName attrs of
@@ -784,7 +924,7 @@ tupleExprCheckNewAttrName attrName rel = if isRight (attributeForName attrName r
784 Right rel
924 Right rel
786extendGraphRefTupleExpressionProcessor :: Relation -> GraphRefExtendTupleExpr -> GraphRefRelationalExprM (Attributes, RelationTuple -> Either RelationalError RelationTuple)
926extendGraphRefTupleExpressionProcessor :: Relation -> GraphRefExtendTupleExpr -> GraphRefRelationalExprM (Attributes, RelationTuple -> Either RelationalError RelationTuple)
787−extendGraphRefTupleExpressionProcessor relIn (AttributeExtendTupleExpr newAttrName atomExpr) =
927+extendGraphRefTupleExpressionProcessor relIn (AttributeExtendTupleExpr newAttrName atomExpr) = do
788-- renv <- askEnv
928-- renv <- askEnv
789 -- check that the attribute name is not in use
929 -- check that the attribute name is not in use
790 case tupleExprCheckNewAttrName newAttrName relIn of
930 case tupleExprCheckNewAttrName newAttrName relIn of
@@ -794,60 +934,66 @@ extendGraphRefTupleExpressionProcessor relIn (AttributeExtendTupleExpr newAttrNa
794 atomExprType' <- verifyGraphRefAtomExprTypes relIn atomExpr atomExprType
934 atomExprType' <- verifyGraphRefAtomExprTypes relIn atomExpr atomExprType
795 let newAttrs = A.attributesFromList [Attribute newAttrName atomExprType']
935 let newAttrs = A.attributesFromList [Attribute newAttrName atomExprType']
796 newAndOldAttrs = A.addAttributes (attributes relIn) newAttrs
936 newAndOldAttrs = A.addAttributes (attributes relIn) newAttrs
798− pure (newAndOldAttrs, \tup -> do
937+ pure (newAndOldAttrs, \tup ->
799− let gfEnv = mergeTuplesIntoGraphRefRelationalExprEnv tup env
938+ --let substate = mergeTuplesIntoGraphRefRelationalExprEnv tup renv in
800− atom <- runGraphRefRelationalExprM gfEnv (evalGraphRefAtomExpr tup atomExpr)
939+ case unimplemented {-runReader (evalAtomExpr tup atomExpr) substate-} of
940+ Left err -> Left err
801− Right (tupleAtomExtend newAttrName atom tup)
941+ Right atom -> Right (tupleAtomExtend newAttrName atom tup)
804evalGraphRefAtomExpr :: RelationTuple -> GraphRefAtomExpr -> GraphRefRelationalExprM Atom
944evalGraphRefAtomExpr :: RelationTuple -> GraphRefAtomExpr -> GraphRefRelationalExprM Atom
805−evalGraphRefAtomExpr tupIn (AttributeAtomExpr attrName) =
945+evalGraphRefAtomExpr = unimplemented
947+evalAtomExpr :: RelationTuple -> AtomExpr -> RelationalExprM Atom
948+evalAtomExpr = unimplemented
806− case atomForAttributeName attrName tupIn of
951+evalAtomExpr tupIn (AttributeAtomExpr attrName) = case atomForAttributeName attrName tupIn of
807− Right atom -> pure atom
952+ Right atom -> pure (Right atom)
808− Left err@(NoSuchAttributeNamesError _) -> do
953+ err@(Left (NoSuchAttributeNamesError _)) -> do
809− env <- askEnv
954+ rstate <- ask
810− case gre_extra env of
955+ let stateTup = stateTuple rstate
811− Nothing -> throwError err
812− Just (Left ctxtup) -> lift $ except $ atomForAttributeName attrName ctxtup
956+ pure (atomForAttributeName attrName stateTup)
813− Just (Right _) -> throwError err
814− Left err -> throwError err
957+ Left err -> pure (Left err)
815−evalGraphRefAtomExpr _ (NakedAtomExpr atom) = pure atom
958+evalAtomExpr _ (NakedAtomExpr atom) = pure (Right atom)
816−evalGraphRefAtomExpr tupIn (FunctionAtomExpr funcName arguments tid) = do
959+evalAtomExpr tupIn (FunctionAtomExpr funcName arguments ()) = do
817− argTypes <- mapM (typeForGraphRefAtomExpr (tupleAttributes tupIn)) arguments
960+ argTypes <- mapM (typeFromAtomExpr (tupleAttributes tupIn)) arguments
818− context <- gfDatabaseContextForMarker tid
961+ context <- fmap stateElemsContext ask
819− let functions = atomFunctions context
963+ let functions = atomFunctions context
820− func <- lift $ except (atomFunctionForName funcName functions)
964+ func <- either throwE pure (atomFunctionForName funcName functions)
821− let expectedArgCount = length (atomFuncType func) - 1
965+ let expectedArgCount = length (atomFuncType func) - 1
822− actualArgCount = length argTypes
966+ actualArgCount = length argTypes
823− safeInit [] = [] -- different behavior from normal init
967+ safeInit [] = [] -- different behavior from normal init
824− safeInit xs = init xs
968+ safeInit xs = init xs
825− if expectedArgCount /= actualArgCount then
969+ if expectedArgCount /= actualArgCount then
826− throwError (FunctionArgumentCountMismatchError expectedArgCount actualArgCount)
970+ throwE (FunctionArgumentCountMismatchError expectedArgCount actualArgCount)
828 let zippedArgs = zip (safeInit (atomFuncType func)) argTypes
972 let zippedArgs = zip (safeInit (atomFuncType func)) argTypes
829− mapM_ (\(expType, actType) ->
973+ mapM_ (\(expType, eActType) -> do
974+ actType <- either throwE pure eActType
830− lift $ except (atomTypeVerify expType actType)) zippedArgs
975+ either throwE pure (atomTypeVerify expType actType)) zippedArgs
831− evaldArgs <- mapM (evalGraphRefAtomExpr tupIn) arguments
976+ evaldArgs <- mapM (liftE . evalAtomExpr tupIn) arguments
832 case evalAtomFunction func evaldArgs of
977 case evalAtomFunction func evaldArgs of
833− Left err -> throwError (AtomFunctionUserError err)
978+ Left err -> throwE (AtomFunctionUserError err)
834 Right result -> do
979 Right result -> do
835 --validate that the result matches the expected type
980 --validate that the result matches the expected type
836− _ <- lift $ except (atomTypeVerify (last (atomFuncType func)) (atomTypeForAtom result))
981+ _ <- either throwE pure (atomTypeVerify (last (atomFuncType func)) (atomTypeForAtom result))
837 pure result
982 pure result
838−evalGraphRefAtomExpr tupIn (RelationAtomExpr relExpr) = do
983+evalAtomExpr tupIn (RelationAtomExpr relExpr) = do
839 --merge existing state tuple context into new state tuple context to support an arbitrary number of levels, but new attributes trounce old attributes
984 --merge existing state tuple context into new state tuple context to support an arbitrary number of levels, but new attributes trounce old attributes
840− env <- ask
985+ rstate <- ask
841− let gfEnv = mergeTuplesIntoGraphRefRelationalExprEnv tupIn env
986+ runExceptT $ do
842− relAtom <- lift $ except $ runGraphRefRelationalExprM gfEnv (evalGraphRefRelationalExpr relExpr)
987+ let newState = mergeTuplesIntoRelationalExprState tupIn rstate
988+ relAtom <- either throwE pure (runReader (evalRelationalExpr relExpr) newState)
843− pure (RelationAtom relAtom)
989+ pure (RelationAtom relAtom)
844−evalGraphRefAtomExpr tupIn cons@(ConstructedAtomExpr dConsName dConsArgs _) = do --why is the tid unused here? suspicious
990+evalAtomExpr tupIn cons@(ConstructedAtomExpr dConsName dConsArgs ()) = runExceptT $ do
845− let mergeEnv = mergeTuplesIntoGraphRefRelationalExprEnv tupIn
991+ rstate <- lift ask
992+ let newState = mergeTuplesIntoRelationalExprState tupIn rstate
846− aType <- local mergeEnv (typeForGraphRefAtomExpr (tupleAttributes tupIn) cons)
993+ aType <- either throwE pure (runReader (typeFromAtomExpr (tupleAttributes tupIn) cons) newState)
847− argAtoms <- local mergeEnv $
994+ argAtoms <- mapM (\arg -> either throwE pure (runReader (evalAtomExpr tupIn arg) newState)) dConsArgs
848− mapM (evalGraphRefAtomExpr tupIn) dConsArgs
849 pure (ConstructedAtom dConsName aType argAtoms)
995 pure (ConstructedAtom dConsName aType argAtoms)
851typeForGraphRefAtomExpr :: Attributes -> GraphRefAtomExpr -> GraphRefRelationalExprM AtomType
997typeForGraphRefAtomExpr :: Attributes -> GraphRefAtomExpr -> GraphRefRelationalExprM AtomType
852typeForGraphRefAtomExpr attrs (AttributeAtomExpr attrName) = do
998typeForGraphRefAtomExpr attrs (AttributeAtomExpr attrName) = do
853 renv <- askEnv
999 renv <- askEnv
@@ -860,13 +1006,12 @@ typeForGraphRefAtomExpr attrs (AttributeAtomExpr attrName) = do
860 Right attr -> pure (A.atomType attr)
1006 Right attr -> pure (A.atomType attr)
861 Left _ -> case atomForAttributeName attrName envTup of
1007 Left _ -> case atomForAttributeName attrName envTup of
862 Right atom -> pure (atomTypeForAtom atom)
1008 Right atom -> pure (atomTypeForAtom atom)
863− Left _ -> --throwError (traceStack (show ("typeForGRAtomExpr", attrs, envTup)) err)
864− throwError err
1009+ Left _ -> throwError err
865 Left err -> throwError err
1010 Left err -> throwError err
867typeForGraphRefAtomExpr _ (NakedAtomExpr atom) = pure (atomTypeForAtom atom)
1012typeForGraphRefAtomExpr _ (NakedAtomExpr atom) = pure (atomTypeForAtom atom)
868typeForGraphRefAtomExpr attrs (FunctionAtomExpr funcName atomArgs transId) = do
1013typeForGraphRefAtomExpr attrs (FunctionAtomExpr funcName atomArgs transId) = do
869− funcs <- atomFunctions <$> gfDatabaseContextForMarker transId
1014+ funcs <- atomFunctions . concreteDatabaseContext <$> gfTransForId transId
870 case atomFunctionForName funcName funcs of
1015 case atomFunctionForName funcName funcs of
871 Left err -> throwError err
1016 Left err -> throwError err
872 Right func -> do
1017 Right func -> do
@@ -884,7 +1029,7 @@ typeForGraphRefAtomExpr attrs (RelationAtomExpr relExpr) = do
884typeForGraphRefAtomExpr attrs (ConstructedAtomExpr dConsName dConsArgs tid) =
1029typeForGraphRefAtomExpr attrs (ConstructedAtomExpr dConsName dConsArgs tid) =
886 argsTypes <- mapM (typeForGraphRefAtomExpr attrs) dConsArgs
1031 argsTypes <- mapM (typeForGraphRefAtomExpr attrs) dConsArgs
887− tConsMap <- typeConstructorMapping <$> gfDatabaseContextForMarker tid
1032+ tConsMap <- typeConstructorMapping . concreteDatabaseContext <$> gfTransForId tid
888 lift $ except $ atomTypeForDataConstructor tConsMap dConsName argsTypes
1033 lift $ except $ atomTypeForDataConstructor tConsMap dConsName argsTypes
890-- | Validate that the type of the AtomExpr matches the expected type.
1035-- | Validate that the type of the AtomExpr matches the expected type.
@@ -906,7 +1051,7 @@ verifyGraphRefAtomExprTypes relIn (AttributeAtomExpr attrName) expectedType = do
906verifyGraphRefAtomExprTypes _ (NakedAtomExpr atom) expectedType =
1051verifyGraphRefAtomExprTypes _ (NakedAtomExpr atom) expectedType =
907 lift $ except $ atomTypeVerify expectedType (atomTypeForAtom atom)
1052 lift $ except $ atomTypeVerify expectedType (atomTypeForAtom atom)
908verifyGraphRefAtomExprTypes relIn (FunctionAtomExpr funcName funcArgExprs tid) expectedType = do
1053verifyGraphRefAtomExprTypes relIn (FunctionAtomExpr funcName funcArgExprs tid) expectedType = do
909− context <- gfDatabaseContextForMarker tid
1054+ context <- concreteDatabaseContext <$> gfTransForId tid
910 let functions = atomFunctions context
1055 let functions = atomFunctions context
911 func <- lift $ except $ atomFunctionForName funcName functions
1056 func <- lift $ except $ atomFunctionForName funcName functions
912 let expectedArgTypes = atomFuncType func
1057 let expectedArgTypes = atomFuncType func
@@ -914,7 +1059,7 @@ verifyGraphRefAtomExprTypes relIn (FunctionAtomExpr funcName funcArgExprs tid) e
914 let handler :: RelationalError -> GraphRefRelationalExprM AtomType
1059 let handler :: RelationalError -> GraphRefRelationalExprM AtomType
915 handler (AtomTypeMismatchError expSubType actSubType) = throwError (AtomFunctionTypeError funcName argCount expSubType actSubType)
1060 handler (AtomTypeMismatchError expSubType actSubType) = throwError (AtomFunctionTypeError funcName argCount expSubType actSubType)
916 handler err = throwError err
1061 handler err = throwError err
917− verifyGraphRefAtomExprTypes relIn atomExpr expectedType2 `catchError` handler
1062+ verifyGraphRefAtomExprTypes relIn atomExpr expectedType2 `catchError` handler
918 funcArgTypes <- mapM funcArgVerifier $ zip3 funcArgExprs expectedArgTypes [1..]
1063 funcArgTypes <- mapM funcArgVerifier $ zip3 funcArgExprs expectedArgTypes [1..]
919 if length funcArgTypes /= length expectedArgTypes - 1 then
1064 if length funcArgTypes /= length expectedArgTypes - 1 then
920 throwError (AtomTypeCountError funcArgTypes expectedArgTypes)
1065 throwError (AtomTypeCountError funcArgTypes expectedArgTypes)
@@ -932,61 +1077,13 @@ verifyGraphRefAtomExprTypes rel cons@ConstructedAtomExpr{} expectedType = do
932-- | Look up the type's name and create a new attribute.
1077-- | Look up the type's name and create a new attribute.
933evalGraphRefAttrExpr :: GraphRefAttributeExpr -> GraphRefRelationalExprM Attribute
1078evalGraphRefAttrExpr :: GraphRefAttributeExpr -> GraphRefRelationalExprM Attribute
934evalGraphRefAttrExpr (AttributeAndTypeNameExpr attrName tCons transId) = do
1079evalGraphRefAttrExpr (AttributeAndTypeNameExpr attrName tCons transId) = do
935− tConsMap <- typeConstructorMapping <$> gfDatabaseContextForMarker transId
1080+ tConsMap <- typeConstructorMapping . concreteDatabaseContext <$> gfTransForId transId
936 aType <- lift $ except $ atomTypeForTypeConstructorValidate True tCons tConsMap M.empty
1081 aType <- lift $ except $ atomTypeForTypeConstructorValidate True tCons tConsMap M.empty
937 lift $ except $ validateAtomType aType tConsMap
1082 lift $ except $ validateAtomType aType tConsMap
938 pure $ Attribute attrName aType
1083 pure $ Attribute attrName aType
940evalGraphRefAttrExpr (NakedAttributeExpr attr) = pure attr
1085evalGraphRefAttrExpr (NakedAttributeExpr attr) = pure attr
942−-- 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
943−evalGraphRefTupleExprs :: Maybe Attributes -> GraphRefTupleExprs -> GraphRefRelationalExprM [RelationTuple]
944−evalGraphRefTupleExprs _ (TupleExprs _ []) = pure []
945−evalGraphRefTupleExprs mAttrs (TupleExprs fixedMarker tupleExprL) = do
946− tuples <- mapM (evalGraphRefTupleExpr mAttrs) tupleExprL
947− finalAttrs <- case mAttrs of
948− Just attrs -> pure attrs
951− [] -> pure emptyAttributes
952− (headTuple:tailTuples) -> do
953− --gather up resolved atom types or throw an error if an attribute cannot be made concrete from the inferred types- this could still fail if the type cannot be inferred (e.g. from [Nothing, Nothing])
955− processTupleAttrs (tupAttr, accAttr) =
956− --if the attribute is a constructedatomtype, we can recurse into it to potentially resolve type variables
957− if isResolvedAttribute accAttr && tupAttr == accAttr then
960− lift $ except $ resolveAttributes accAttr tupAttr
961− mostResolvedTypes <-
962− foldM (\acc tup -> do
963− let zipped = zip (V.toList . attributesVec $ tupleAttributes tup) acc
964− accNames = S.fromList $ map A.attributeName acc
965− tupNames = A.attributeNameSet (tupleAttributes tup)
966− attrNamesDiff = S.union (S.difference accNames tupNames) (S.difference tupNames accNames)
967− unless (null attrNamesDiff) (throwError (AttributeNamesMismatchError attrNamesDiff))
968− nextTupleAttrs <- mapM processTupleAttrs zipped
969− let diff = A.attributesDifference (A.attributesFromList nextTupleAttrs) (A.attributesFromList acc)
970− if diff == A.emptyAttributes then
973− throwError (TupleAttributeTypeMismatchError diff)
974− ) (V.toList . attributesVec $ tupleAttributes headTuple) tailTuples
975− pure (A.attributesFromList mostResolvedTypes)
976− --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
977− tConsMap <- case singularTransactions tupleExprL of
978− SingularTransactionRef commonTransId ->
979− typeConstructorMapping <$> gfDatabaseContextForMarker commonTransId
980− NoTransactionsRef ->
981− typeConstructorMapping <$> gfDatabaseContextForMarker fixedMarker
982− -- 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
983− _ -> throwError TupleExprsReferenceMultipleMarkersError
984− lift $ except $ validateAttributes tConsMap finalAttrs
985− mapM (lift . except . resolveTypesInTuple finalAttrs tConsMap) tuples
988−--resolveAttributes (Attribute "gonk" (ConstructedAtomType "Either" (fromList [("a",IntegerAtomType),("b",TypeVariableType "b")]))) (Attribute "gonk" (ConstructedAtomType "Either" (fromList [("a",TypeVariableType "a"),("b",TextAtomType)])))
990evalGraphRefTupleExpr :: Maybe Attributes -> GraphRefTupleExpr -> GraphRefRelationalExprM RelationTuple
1087evalGraphRefTupleExpr :: Maybe Attributes -> GraphRefTupleExpr -> GraphRefRelationalExprM RelationTuple
991evalGraphRefTupleExpr mAttrs (TupleExpr tupMap) = do
1088evalGraphRefTupleExpr mAttrs (TupleExpr tupMap) = do
992 -- 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
1089 -- 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
@@ -1011,12 +1108,62 @@ evalGraphRefTupleExpr mAttrs (TupleExpr tupMap) = do
1011 --verify that the attributes match
1108 --verify that the attributes match
1012 when (A.attributeNameSet finalAttrs /= A.attributeNameSet tupAttrs) $ throwError (TupleAttributeTypeMismatchError tupAttrs)
1109 when (A.attributeNameSet finalAttrs /= A.attributeNameSet tupAttrs) $ throwError (TupleAttributeTypeMismatchError tupAttrs)
1013 --we can't resolve types here- they have to be resolved at the atom level where the graph ref is held
1110 --we can't resolve types here- they have to be resolved at the atom level where the graph ref is held
1014− --tup' <- lift $ except (resolveTypesInTuple finalAttrs tConss (reorderTuple finalAttrs tup))
1111+-- tup' <- lift $ except (resolveTypesInTuple finalAttrs tConss (reorderTuple finalAttrs tup))
1015 let tup' = reorderTuple finalAttrs tup
1112 let tup' = reorderTuple finalAttrs tup
1016 --TODO: restore type resolution
1113 --TODO: restore type resolution
1017-- _ <- lift $ except (validateTuple tup' tConss)
1114-- _ <- lift $ except (validateTuple tup' tConss)
1018 pure tup'
1115 pure tup'
1118+evalAttributeNames :: AttributeNames -> RelationalExpr -> RelationalExprM (Either RelationalError (S.Set AttributeName))
1119+evalAttributeNames attrNames expr = do
1120+ eExprType <- typeForRelationalExpr expr
1122+ Left err -> throwError err
1123+ Right exprTyp -> do
1124+ let typeNameSet = S.fromList (V.toList (A.attributeNames (attributes exprTyp)))
1126+ AttributeNames names ->
1127+ case A.projectionAttributesForNames names (attributes exprTyp) of
1128+ Left err -> pure (Left err)
1129+ Right attrs -> pure (Right (S.fromList (V.toList (A.attributeNames attrs))))
1131+ InvertedAttributeNames names -> do
1132+ let nonExistentAttributeNames = A.attributeNamesNotContained names typeNameSet
1133+ if not (S.null nonExistentAttributeNames) then
1134+ pure (Left (AttributeNamesMismatchError nonExistentAttributeNames))
1136+ pure (Right (A.nonMatchingAttributeNameSet names typeNameSet))
1138+ UnionAttributeNames namesA namesB -> do
1139+ eNameSetA <- evalAttributeNames namesA expr
1141+ Left err -> pure (Left err)
1142+ Right nameSetA -> do
1143+ eNameSetB <- evalAttributeNames namesB expr
1145+ Left err -> pure (Left err)
1147+ pure (Right (S.union nameSetA nameSetB))
1149+ IntersectAttributeNames namesA namesB -> do
1150+ eNameSetA <- evalAttributeNames namesA expr
1152+ Left err -> pure (Left err)
1153+ Right nameSetA -> do
1154+ eNameSetB <- evalAttributeNames namesB expr
1156+ Left err -> pure (Left err)
1158+ pure (Right (S.intersection nameSetA nameSetB))
1160+ RelationalExprAttributeNames attrExpr -> do
1161+ eAttrExprType <- typeForRelationalExpr attrExpr
1162+ case eAttrExprType of
1163+ Left err -> pure (Left err)
1164+ Right attrExprType -> pure (Right (A.attributeNameSet (attributes attrExprType)))
1020--temporary implementation until we have a proper planner+executor
1167--temporary implementation until we have a proper planner+executor
1021evalGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefRelationalExprM Relation
1168evalGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefRelationalExprM Relation
1022evalGraphRefRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do
1169evalGraphRefRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do
@@ -1024,7 +1171,7 @@ evalGraphRefRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do
1024 Just _ ->
1171 Just _ ->
1025 Just . A.attributesFromList <$> mapM evalGraphRefAttrExpr (fromMaybe [] mAttrExprs)
1172 Just . A.attributesFromList <$> mapM evalGraphRefAttrExpr (fromMaybe [] mAttrExprs)
1026 Nothing -> pure Nothing
1173 Nothing -> pure Nothing
1027− tuples <- evalGraphRefTupleExprs mAttrs tupleExprs
1174+ tuples <- mapM (evalGraphRefTupleExpr mAttrs) tupleExprs
1028 let attrs = fromMaybe firstTupleAttrs mAttrs
1175 let attrs = fromMaybe firstTupleAttrs mAttrs
1029 firstTupleAttrs = if null tuples then A.emptyAttributes else tupleAttributes (head tuples)
1176 firstTupleAttrs = if null tuples then A.emptyAttributes else tupleAttributes (head tuples)
1030 lift $ except $ mkRelation attrs (RelationTupleSet tuples)
1177 lift $ except $ mkRelation attrs (RelationTupleSet tuples)
@@ -1032,7 +1179,7 @@ evalGraphRefRelationalExpr (MakeStaticRelation attributeSet tupleSet) =
1032 lift $ except $ mkRelation attributeSet tupleSet
1179 lift $ except $ mkRelation attributeSet tupleSet
1033evalGraphRefRelationalExpr (ExistingRelation rel) = pure rel
1180evalGraphRefRelationalExpr (ExistingRelation rel) = pure rel
1034evalGraphRefRelationalExpr (RelationVariable name tid) = do
1181evalGraphRefRelationalExpr (RelationVariable name tid) = do
1035− ctx <- gfDatabaseContextForMarker tid
1182+ ctx <- concreteDatabaseContext <$> gfTransForId tid
1036 case M.lookup name (relationVariables ctx) of
1183 case M.lookup name (relationVariables ctx) of
1037 Nothing -> throwError (RelVarNotDefinedError name)
1184 Nothing -> throwError (RelVarNotDefinedError name)
1038 Just rv -> evalGraphRefRelationalExpr rv
1185 Just rv -> evalGraphRefRelationalExpr rv
@@ -1078,7 +1225,7 @@ evalGraphRefRelationalExpr (Extend extendTupleExpr expr) = do
1078 rel <- evalGraphRefRelationalExpr expr
1225 rel <- evalGraphRefRelationalExpr expr
1079 (newAttrs, tupProc) <- extendGraphRefTupleExpressionProcessor rel extendTupleExpr
1226 (newAttrs, tupProc) <- extendGraphRefTupleExpressionProcessor rel extendTupleExpr
1080 lift $ except $ relMogrify tupProc newAttrs rel
1227 lift $ except $ relMogrify tupProc newAttrs rel
1081−evalGraphRefRelationalExpr expr@With{} =
1228+evalGraphRefRelationalExpr expr@With{} = do
1082 --strategy A: add relation variables to the contexts in the graph
1229 --strategy A: add relation variables to the contexts in the graph
1083 --strategy B: drop in macros in place (easier programmatically)
1230 --strategy B: drop in macros in place (easier programmatically)
1084 --strategy B implementation
1231 --strategy B implementation
@@ -1106,21 +1253,20 @@ typeForGraphRefRelationalExpr (ExistingRelation rel) = pure (emptyRelationWithAt
1106typeForGraphRefRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do
1253typeForGraphRefRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do
1107 mAttrs <- case mAttrExprs of
1254 mAttrs <- case mAttrExprs of
1108 Just attrExprs -> do
1255 Just attrExprs -> do
1109− attrs <- mapM evalGraphRefAttributeExpr attrExprs
1256+ attrs <- mapM (\e -> evalGraphRefAttributeExpr e) attrExprs
1110 pure (Just (attributesFromList attrs))
1257 pure (Just (attributesFromList attrs))
1111 Nothing -> pure Nothing
1258 Nothing -> pure Nothing
1112− tuples <- evalGraphRefTupleExprs mAttrs tupleExprs
1259+ tuples <- mapM (evalGraphRefTupleExpr mAttrs) tupleExprs
1113 let retAttrs = case tuples of
1260 let retAttrs = case tuples of
1114 (tup:_) -> tupleAttributes tup
1261 (tup:_) -> tupleAttributes tup
1115 [] -> fromMaybe A.emptyAttributes mAttrs
1262 [] -> fromMaybe A.emptyAttributes mAttrs
1116 pure $ emptyRelationWithAttrs retAttrs
1263 pure $ emptyRelationWithAttrs retAttrs
1118typeForGraphRefRelationalExpr (RelationVariable rvName tid) = do
1265typeForGraphRefRelationalExpr (RelationVariable rvName tid) = do
1119− relVars <- relationVariables <$> gfDatabaseContextForMarker tid
1266+ relVars <- relationVariables . concreteDatabaseContext <$> gfTransForId tid
1120 case M.lookup rvName relVars of
1267 case M.lookup rvName relVars of
1121 Nothing -> throwError (RelVarNotDefinedError rvName)
1268 Nothing -> throwError (RelVarNotDefinedError rvName)
1123− typeForGraphRefRelationalExpr rvExpr
1269+ Just rvExpr -> typeForGraphRefRelationalExpr rvExpr
1124typeForGraphRefRelationalExpr (Project attrNames expr) = do
1270typeForGraphRefRelationalExpr (Project attrNames expr) = do
1125 exprType' <- typeForGraphRefRelationalExpr expr
1271 exprType' <- typeForGraphRefRelationalExpr expr
1126 projectionAttrs <- evalGraphRefAttributeNames attrNames expr
1272 projectionAttrs <- evalGraphRefAttributeNames attrNames expr
@@ -1151,21 +1297,15 @@ typeForGraphRefRelationalExpr (Restrict pred' expr) = do
1151 expr' <- typeForGraphRefRelationalExpr expr
1297 expr' <- typeForGraphRefRelationalExpr expr
1152 filt <- predicateRestrictionFilter (attributes expr') pred'
1298 filt <- predicateRestrictionFilter (attributes expr') pred'
1153 lift $ except $ restrict filt expr'
1299 lift $ except $ restrict filt expr'
1154−typeForGraphRefRelationalExpr Equals{} =
1300+typeForGraphRefRelationalExpr Equals{} = do
1155 pure relationFalse
1301 pure relationFalse
1156−typeForGraphRefRelationalExpr NotEquals{} =
1302+typeForGraphRefRelationalExpr NotEquals{} = do
1157 pure relationFalse
1303 pure relationFalse
1158typeForGraphRefRelationalExpr (Extend extendTupleExpr expr) = do
1304typeForGraphRefRelationalExpr (Extend extendTupleExpr expr) = do
1159 rel <- typeForGraphRefRelationalExpr expr
1305 rel <- typeForGraphRefRelationalExpr expr
1160 evalGraphRefRelationalExpr (Extend extendTupleExpr (ExistingRelation rel))
1306 evalGraphRefRelationalExpr (Extend extendTupleExpr (ExistingRelation rel))
1161−typeForGraphRefRelationalExpr expr@(With withs _) = do
1307+typeForGraphRefRelationalExpr expr@With{} = do
1162 let expr' = substituteWithNameMacros [] expr
1308 let expr' = substituteWithNameMacros [] expr
1163− checkMacroName (WithNameExpr macroName tid) = do
1164− rvs <- relationVariables <$> gfDatabaseContextForMarker tid
1165− case M.lookup macroName rvs of
1166− Just _ -> lift $ except $ Left (RelVarAlreadyDefinedError macroName) --this error does not include the transaction marker, but should be good enough to identify the cause
1168− mapM_ (checkMacroName . fst) withs
1169 typeForGraphRefRelationalExpr expr'
1309 typeForGraphRefRelationalExpr expr'
1171evalGraphRefAttributeNames :: GraphRefAttributeNames -> GraphRefRelationalExpr -> GraphRefRelationalExprM (S.Set AttributeName)
1311evalGraphRefAttributeNames :: GraphRefAttributeNames -> GraphRefRelationalExpr -> GraphRefRelationalExprM (S.Set AttributeName)
@@ -1181,7 +1321,7 @@ evalGraphRefAttributeNames attrNames expr = do
1181 InvertedAttributeNames names -> do
1321 InvertedAttributeNames names -> do
1182 let nonExistentAttributeNames = A.attributeNamesNotContained names typeNameSet
1322 let nonExistentAttributeNames = A.attributeNamesNotContained names typeNameSet
1183 if not (S.null nonExistentAttributeNames) then
1323 if not (S.null nonExistentAttributeNames) then
1184− throwError $ AttributeNamesMismatchError nonExistentAttributeNames
1324+ throwError (AttributeNamesMismatchError nonExistentAttributeNames)
1186 pure (A.nonMatchingAttributeNameSet names typeNameSet)
1326 pure (A.nonMatchingAttributeNameSet names typeNameSet)
@@ -1201,7 +1341,7 @@ evalGraphRefAttributeNames attrNames expr = do
1202evalGraphRefAttributeExpr :: GraphRefAttributeExpr -> GraphRefRelationalExprM Attribute
1342evalGraphRefAttributeExpr :: GraphRefAttributeExpr -> GraphRefRelationalExprM Attribute
1203evalGraphRefAttributeExpr (AttributeAndTypeNameExpr attrName tCons tid) = do
1343evalGraphRefAttributeExpr (AttributeAndTypeNameExpr attrName tCons tid) = do
1204− tConsMap <- typeConstructorMapping <$> gfDatabaseContextForMarker tid
1344+ tConsMap <- typeConstructorMapping . concreteDatabaseContext <$> gfTransForId tid
1205 case atomTypeForTypeConstructorValidate True tCons tConsMap M.empty of
1345 case atomTypeForTypeConstructorValidate True tCons tConsMap M.empty of
1206 Left err -> throwError err
1346 Left err -> throwError err
1207 Right aType -> do
1347 Right aType -> do
@@ -1211,9 +1351,9 @@ evalGraphRefAttributeExpr (AttributeAndTypeNameExpr attrName tCons tid) = do
1211evalGraphRefAttributeExpr (NakedAttributeExpr attr) = pure attr
1351evalGraphRefAttributeExpr (NakedAttributeExpr attr) = pure attr
1213mkEmptyRelVars :: RelationVariables -> RelationVariables
1353mkEmptyRelVars :: RelationVariables -> RelationVariables
1214−mkEmptyRelVars = M.map mkEmptyRelVar
1354+mkEmptyRelVars rvMap = M.map mkEmptyRelVar rvMap
1216− mkEmptyRelVar expr@MakeRelationFromExprs{} = expr --do not truncate here because we might lose essential type information in emptying the tuples
1356+ mkEmptyRelVar (MakeRelationFromExprs mAttrs _) = MakeRelationFromExprs mAttrs []
1217 mkEmptyRelVar (MakeStaticRelation attrs _) = MakeStaticRelation attrs emptyTupleSet
1357 mkEmptyRelVar (MakeStaticRelation attrs _) = MakeStaticRelation attrs emptyTupleSet
1218 mkEmptyRelVar (ExistingRelation rel) = ExistingRelation (emptyRelationWithAttrs (attributes rel))
1358 mkEmptyRelVar (ExistingRelation rel) = ExistingRelation (emptyRelationWithAttrs (attributes rel))
1219 mkEmptyRelVar rv@RelationVariable{} = Restrict (NotPredicate TruePredicate) rv
1359 mkEmptyRelVar rv@RelationVariable{} = Restrict (NotPredicate TruePredicate) rv
@@ -1228,165 +1368,28 @@ mkEmptyRelVars = M.map mkEmptyRelVar
1228 mkEmptyRelVar (Equals exprA exprB) = Equals (mkEmptyRelVar exprA) (mkEmptyRelVar exprB)
1368 mkEmptyRelVar (Equals exprA exprB) = Equals (mkEmptyRelVar exprA) (mkEmptyRelVar exprB)
1229 mkEmptyRelVar (NotEquals exprA exprB) = NotEquals (mkEmptyRelVar exprA) (mkEmptyRelVar exprB)
1369 mkEmptyRelVar (NotEquals exprA exprB) = NotEquals (mkEmptyRelVar exprA) (mkEmptyRelVar exprB)
1230 mkEmptyRelVar (Extend extTuple expr) = Extend extTuple (mkEmptyRelVar expr)
1370 mkEmptyRelVar (Extend extTuple expr) = Extend extTuple (mkEmptyRelVar expr)
1231− mkEmptyRelVar (With macros expr) = With (map (second mkEmptyRelVar) macros) (mkEmptyRelVar expr)
1371+ mkEmptyRelVar (With macros expr) = With (map (\(rv, expr') -> (rv, mkEmptyRelVar expr')) macros) (mkEmptyRelVar expr)
1234dbErr :: RelationalError -> DatabaseContextEvalMonad ()
1374dbErr :: RelationalError -> DatabaseContextEvalMonad ()
1235dbErr err = lift (except (Left err))
1375dbErr err = lift (except (Left err))
1237-- | Return a Relation describing the relation variables.
1377-- | Return a Relation describing the relation variables.
1238−relationVariablesAsRelation :: DatabaseContext -> TransactionGraph -> Either RelationalError Relation
1378+relationVariablesAsRelation :: RelationVariables -> TransactionGraph -> Either RelationalError Relation
1239−relationVariablesAsRelation ctx graph = do
1379+relationVariablesAsRelation relVarMap graph = do
1240 let subrelAttrs = A.attributesFromList [Attribute "attribute" TextAtomType, Attribute "type" TextAtomType]
1380 let subrelAttrs = A.attributesFromList [Attribute "attribute" TextAtomType, Attribute "type" TextAtomType]
1241 attrs = A.attributesFromList [Attribute "name" TextAtomType,
1381 attrs = A.attributesFromList [Attribute "name" TextAtomType,
1242 Attribute "attributes" (RelationAtomType subrelAttrs)]
1382 Attribute "attributes" (RelationAtomType subrelAttrs)]
1243− relVars = relationVariables ctx
1244 mkRvDesc (rvName, gfExpr) = do
1383 mkRvDesc (rvName, gfExpr) = do
1245− let gfEnv = freshGraphRefRelationalExprEnv (Just ctx) graph
1384+ let gfEnv = freshGraphRefRelationalExprEnv graph
1246 gfType <- runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr gfExpr)
1385 gfType <- runGraphRefRelationalExprM gfEnv (typeForGraphRefRelationalExpr gfExpr)
1247 pure (rvName, gfType)
1386 pure (rvName, gfType)
1248− relVarToAtomList (rvName, rel) = [TextAtom rvName, attributesToRel (attributesVec (attributes rel))]
1387+ relVarToAtomList (rvName, rel) = [TextAtom rvName, attributesToRel (attributes rel)]
1249 attrAtoms a = [TextAtom (A.attributeName a), TextAtom (prettyAtomType (A.atomType a))]
1388 attrAtoms a = [TextAtom (A.attributeName a), TextAtom (prettyAtomType (A.atomType a))]
1250 attributesToRel attrl = case mkRelationFromList subrelAttrs (map attrAtoms (V.toList attrl)) of
1389 attributesToRel attrl = case mkRelationFromList subrelAttrs (map attrAtoms (V.toList attrl)) of
1251 Left err -> error ("relationVariablesAsRelation pooped " ++ show err)
1390 Left err -> error ("relationVariablesAsRelation pooped " ++ show err)
1252 Right rel -> RelationAtom rel
1391 Right rel -> RelationAtom rel
1253− rvs <- mapM mkRvDesc (M.toList relVars)
1392+ rvs <- mapM mkRvDesc (M.toList relVarMap)
1254 let tups = map relVarToAtomList rvs
1393 let tups = map relVarToAtomList rvs
1255 mkRelationFromList attrs tups
1394 mkRelationFromList attrs tups
1257−-- | An unoptimized variant of evalGraphRefRelationalExpr for testing.
1258−evalRelationalExpr :: RelationalExpr -> RelationalExprM Relation
1259−evalRelationalExpr expr = do
1261− context <- reContext
1262− let expr' = runProcessExprM UncommittedContextMarker (processRelationalExpr expr)
1263− gfEnv = freshGraphRefRelationalExprEnv (Just context) graph
1264− case runGraphRefRelationalExprM gfEnv (evalGraphRefRelationalExpr expr') of
1265− Left err -> throwError err
1266− Right rel -> pure rel
1268−class (MonadError RelationalError m, Monad m) => DatabaseContextM m where
1269− getContext :: m DatabaseContext
1271−instance DatabaseContextM (ReaderT GraphRefRelationalExprEnv (ExceptT RelationalError Identity)) where
1272− getContext = gfDatabaseContextForMarker UncommittedContextMarker
1274−instance DatabaseContextM (RWST DatabaseContextEvalEnv () DatabaseContextEvalState (ExceptT RelationalError Identity)) where
1275− getContext = getStateContext
1277−relVarByName :: DatabaseContextM m => RelVarName -> m GraphRefRelationalExpr
1278−relVarByName rvName = do
1279− relvars <- relationVariables <$> getContext
1280− case M.lookup rvName relvars of
1281− Nothing -> throwError (RelVarNotDefinedError rvName)
1282− Just gfexpr -> pure gfexpr
1284−-- | resolve UncommittedTransactionMarker whenever possible- this is important in the DatabaseContext in order to mitigate self-referencing loops for updates
1285−class ResolveGraphRefTransactionMarker a where
1286− resolve :: a -> DatabaseContextEvalMonad a
1289−instance ResolveGraphRefTransactionMarker GraphRefRelationalExpr where
1290− resolve (MakeRelationFromExprs mAttrs tupleExprs) =
1291− MakeRelationFromExprs mAttrs <$> resolve tupleExprs
1292− resolve orig@MakeStaticRelation{} = pure orig
1293− resolve orig@ExistingRelation{} = pure orig
1294− resolve orig@(RelationVariable rvName UncommittedContextMarker) = do
1295− rvMap <- relationVariables <$> getStateContext
1296− case M.lookup rvName rvMap of
1297− Nothing -> pure orig
1298− Just resolvedRv -> resolve resolvedRv
1299− resolve orig@RelationVariable{} = pure orig
1300− resolve (Project attrNames relExpr) = Project <$> resolve attrNames <*> resolve relExpr
1301− resolve (Union exprA exprB) = Union <$> resolve exprA <*> resolve exprB
1302− resolve (Join exprA exprB) = Join <$> resolve exprA <*> resolve exprB
1303− resolve (Rename attrA attrB expr) = Rename attrA attrB <$> resolve expr
1304− resolve (Difference exprA exprB) = Difference <$> resolve exprA <*> resolve exprB
1305− resolve (Group namesA nameB expr) = Group <$> resolve namesA <*> pure nameB <*> resolve expr
1306− resolve (Ungroup nameA expr) = Ungroup nameA <$> resolve expr
1307− resolve (Restrict restrictExpr relExpr) = Restrict <$> resolve restrictExpr <*> resolve relExpr
1308− resolve (Equals exprA exprB) = Equals <$> resolve exprA <*> resolve exprB
1309− resolve (NotEquals exprA exprB) = NotEquals <$> resolve exprA <*> resolve exprB
1310− resolve (Extend extendExpr relExpr) = Extend <$> resolve extendExpr <*> resolve relExpr
1311− resolve (With withExprs relExpr) = With <$> mapM (\(nam, expr) -> (,) <$> resolve nam <*> resolve expr) withExprs <*> resolve relExpr
1313−instance ResolveGraphRefTransactionMarker GraphRefTupleExprs where
1314− resolve (TupleExprs marker tupleExprs) =
1315− TupleExprs marker <$> mapM resolve tupleExprs
1317−instance ResolveGraphRefTransactionMarker GraphRefTupleExpr where
1318− resolve (TupleExpr tupMap) = do
1319− tupMap' <- mapM (\(attrName, expr) -> (,) attrName <$> resolve expr ) (M.toList tupMap)
1320− pure (TupleExpr (M.fromList tupMap'))
1322−instance ResolveGraphRefTransactionMarker GraphRefAttributeNames where
1323− resolve orig@AttributeNames{} = pure orig
1324− resolve orig@InvertedAttributeNames{} = pure orig
1325− resolve (UnionAttributeNames namesA namesB) = UnionAttributeNames <$> resolve namesA <*> resolve namesB
1326− resolve (IntersectAttributeNames namesA namesB) = IntersectAttributeNames <$> resolve namesA <*> resolve namesB
1327− resolve (RelationalExprAttributeNames expr) = RelationalExprAttributeNames <$> resolve expr
1329−instance ResolveGraphRefTransactionMarker GraphRefRestrictionPredicateExpr where
1330− resolve TruePredicate = pure TruePredicate
1331− resolve (AndPredicate exprA exprB) = AndPredicate <$> resolve exprA <*> resolve exprB
1332− resolve (OrPredicate exprA exprB) = OrPredicate <$> resolve exprA <*> resolve exprB
1333− resolve (NotPredicate expr) = NotPredicate <$> resolve expr
1334− resolve (RelationalExprPredicate expr) = RelationalExprPredicate <$> resolve expr
1335− resolve (AtomExprPredicate expr) = AtomExprPredicate <$> resolve expr
1336− resolve (AttributeEqualityPredicate nam expr)= AttributeEqualityPredicate nam <$> resolve expr
1338−instance ResolveGraphRefTransactionMarker GraphRefExtendTupleExpr where
1339− resolve (AttributeExtendTupleExpr nam atomExpr) = AttributeExtendTupleExpr nam <$> resolve atomExpr
1341−instance ResolveGraphRefTransactionMarker GraphRefWithNameExpr where
1342− resolve orig@WithNameExpr{} = pure orig -- match uncommitted marker?
1344−instance ResolveGraphRefTransactionMarker GraphRefAtomExpr where
1345− resolve orig@AttributeAtomExpr{} = pure orig
1346− resolve orig@NakedAtomExpr{} = pure orig
1347− resolve (FunctionAtomExpr nam atomExprs marker) =
1348− FunctionAtomExpr nam <$> mapM resolve atomExprs <*> pure marker
1349− resolve (RelationAtomExpr expr) = RelationAtomExpr <$> resolve expr
1350− resolve (ConstructedAtomExpr dConsName atomExprs marker) =
1351− ConstructedAtomExpr dConsName <$> mapM resolve atomExprs <*> pure marker
1353−--convert series of simple Union queries into MakeStaticRelation
1354−-- this is especially useful for long, nested applications of Union with simple tuples
1355−-- Union (MakeRelation x y) (MakeRelation x y') -> MakeRelation x (y + y')
1357−--MakeRelationFromExprs Nothing (TupleExprs UncommittedContextMarker [TupleExpr (fromList [("name", NakedAtomExpr (TextAtom "steve"))])])
1359−applyUnionCollapse :: GraphRefRelationalExpr -> GraphRefRelationalExpr
1360−applyUnionCollapse = Fold.cata opt
1362− opt :: RelationalExprBaseF GraphRefTransactionMarker GraphRefRelationalExpr -> GraphRefRelationalExpr
1363− opt (UnionF exprA exprB) | exprA == exprB = exprA
1365− exprA@(MakeRelationFromExprs mAttrs1 tupExprs1)
1366− exprB@(MakeRelationFromExprs mAttrs2 tupExprs2)) | tupExprs1 == tupExprs2 = MakeRelationFromExprs (mAttrs1 <|> mAttrs2) tupExprs1
1367− | tupExprsNull tupExprs1 = exprB
1368− | tupExprsNull tupExprs2 = exprA
1369− opt x = Fold.embed x
1370− tupExprsNull (TupleExprs _ []) = True
1371− tupExprsNull _ = False
1374−--UPDATE optimization- find matching where clause in "lower" levels of renaming
1375−--update x where y=1 set (x:=5,z:=10); update x where y=1 set(x:=6,z:=11)
1377−-- update x where y=1 set (x:=6,z:=11)
1378−-- future opt: match individual attributes update x where y=1 set (x:=5); update x where y=1 set (z:=11) => update x where y=1 set (x:=5,z:=11)
1380−--strategy: try to collapse the top-level update (union (restrict pred MakeRelationFromExpr) expr) if it contains the same predicate and resultant relation
1382−--DELETE optimization
1383−-- if a restriction matches a previous restriction, combine them
1384−-- O(1) since it only scans at the top level, critical in benchmarks generating redundant deletions
1385−applyRestrictionCollapse :: GraphRefRelationalExpr -> GraphRefRelationalExpr
1386−applyRestrictionCollapse orig@(Restrict npred@(NotPredicate _) expr) =
1388− orig'@(Restrict npred'@(NotPredicate _) _) | npred == npred' -> orig'
1390−applyRestrictionCollapse expr = expr