@@ -1,154 +1,80 @@
2module RelationExpr where
1module RelationExpr where
3import Relation
2import Relation
4import RelationTuple
3import RelationTuple
4+import RelationTupleSet
5import RelationType
5import RelationType
6import RelationalError
6import RelationalError
7−import qualified Data.Set as S
8import qualified Data.Map as M
7import qualified Data.Map as M
9import qualified Data.HashSet as HS
8import qualified Data.HashSet as HS
10import Control.Monad.State hiding (join)
9import Control.Monad.State hiding (join)
12−type RelVarContext = M.Map String Relation
11+--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
14−type AtomName = String
16−data RelationalExpr where
17− MakeStaticRelation :: Attributes -> RelationTupleSet -> RelationalExpr
18− --MakeFunctionalRelation (creates a relation from a tuple-generating function, potentially infinite)
19− --in Tutorial D, relational variables pick up the type of the first relation assigned to them
20− --relational variables should also be able to be explicitly-typed like in Haskell
21− RelationVariable :: String -> RelationalExpr
22− Project :: S.Set AttributeName -> RelationalExpr -> RelationalExpr
23− Union :: RelationalExpr -> RelationalExpr -> RelationalExpr
24− Join :: RelationalExpr -> RelationalExpr -> RelationalExpr
25− MultipleExpr :: [RelationalExpr] -> RelationalExpr
26− Rename :: AttributeName -> AttributeName -> RelationalExpr -> RelationalExpr
27− Group :: S.Set AttributeName -> AttributeName -> RelationalExpr -> RelationalExpr
28− Ungroup :: AttributeName -> RelationalExpr -> RelationalExpr
29− --Restrict :: RExpr.RestrictionExpr -> RelationalExpr -> RelationalExpr
31− --nominal relational expressions- the following operations could also be deemed non-relational, but I allow them to return relational expressions regardless- maybe this doesn't make sense since they should only be allowed as top-level commands
32− Define :: String -> Attributes -> RelationalExpr
33− Assign :: String -> RelationalExpr -> RelationalExpr
34− Insert :: String -> RelationalExpr -> RelationalExpr
35− Delete :: String -> RelationalExpr -- needs restriction support
36− Update :: String -> M.Map String Atom -> RelationalExpr -- needs restriction support
38−{- maybe break this into multiple steps:
39−1. check relational types for match (attribute counts) (typechecking step
40−2. create an execution plan (another system of nodes, another GADT)
45−type RelVarState a = State RelVarContext a
47−--helper function to process relation variable creation/assignment
48−setRelVar :: String -> Relation -> RelVarState (Either RelationalError Relation)
49−setRelVar relVarName rel = do
51− put $ M.insert relVarName rel relVars
54−eval :: RelationalExpr -> RelVarState (Either RelationalError Relation)
12+evalRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
56−--define a relvar by creating an empty-tupled relation
57−eval (Define relVarName attributes) = do
59− case M.member relVarName relvars of
60− True -> return (Left (RelvarAlreadyDefined relVarName))
61− False -> setRelVar relVarName emptyRelation
63− emptyRelation = Relation attributes HS.empty
65−eval (Assign relVarName expr) = do
67− -- in the future, it would be nice to get types from the RelationalExpr instead of needing to evaluate it
68− let existingRelVar = M.lookup relVarName relVarTable
71− Left err -> return $ Left err
72− Right rel -> case existingRelVar of
73− Nothing -> setRelVar relVarName rel
74− Just existingRel -> if attributes existingRel == attributes rel then
75− setRelVar relVarName rel
77− return $ Left RelvarAssignmentTypeMismatch
80−eval (RelationVariable name) = do
13+evalRelationalExpr (RelationVariable name) = do
81− relvarTable <- get
14+ relvarTable <- liftM relationVariables get
82 return $ case M.lookup name relvarTable of
15 return $ case M.lookup name relvarTable of
83 Just res -> Right res
16 Just res -> Right res
84− Nothing -> Left $ RelvarNotDefinedError name
17+ Nothing -> Left $ RelVarNotDefinedError name
86−eval (Project attrNameSet expr) = do
19+evalRelationalExpr (Project attrNameSet expr) = do
87− rel <- eval expr
20+ rel <- evalRelationalExpr expr
88 case rel of
21 case rel of
89 Right rel -> return $ project attrNameSet rel
22 Right rel -> return $ project attrNameSet rel
90 Left err -> return $ Left err
23 Left err -> return $ Left err
92−eval (Union exprA exprB) = do
25+evalRelationalExpr (Union exprA exprB) = do
93− relA <- eval exprA
26+ relA <- evalRelationalExpr exprA
94− relB <- eval exprB
27+ relB <- evalRelationalExpr exprB
95 case relA of
28 case relA of
96 Left err -> return $ Left err
29 Left err -> return $ Left err
97 Right relA -> case relB of
30 Right relA -> case relB of
98 Left err -> return $ Left err
31 Left err -> return $ Left err
99 Right relB -> return $ union relA relB
32 Right relB -> return $ union relA relB
101−eval (Join exprA exprB) = do
34+evalRelationalExpr (Join exprA exprB) = do
102− relA <- eval exprA
35+ relA <- evalRelationalExpr exprA
103− relB <- eval exprB
36+ relB <- evalRelationalExpr exprB
104 case relA of
37 case relA of
105 Left err -> return $ Left err
38 Left err -> return $ Left err
106 Right relA -> case relB of
39 Right relA -> case relB of
107 Left err -> return $ Left err
40 Left err -> return $ Left err
108 Right relB -> return $ join relA relB
41 Right relB -> return $ join relA relB
110−eval (MultipleExpr exprs) = do
111− evald <- mapM eval exprs
114−eval (MakeStaticRelation attributes tupleSet) = do
43+evalRelationalExpr (MakeStaticRelation attributes tupleSet) = do
115 case mkRelation attributes tupleSet of
44 case mkRelation attributes tupleSet of
116 Right rel -> return $ Right rel
45 Right rel -> return $ Right rel
117 Left err -> return $ Left err
46 Left err -> return $ Left err
119−eval (Rename oldAttrName newAttrName relExpr) = do
48+evalRelationalExpr (Rename oldAttrName newAttrName relExpr) = do
120− evald <- eval relExpr
49+ evald <- evalRelationalExpr relExpr
121 case evald of
50 case evald of
122 Right rel -> return $ rename oldAttrName newAttrName rel
51 Right rel -> return $ rename oldAttrName newAttrName rel
123 Left err -> return $ Left err
52 Left err -> return $ Left err
125−eval (Group oldAttrNameSet newAttrName relExpr) = do
54+evalRelationalExpr (Group oldAttrNameSet newAttrName relExpr) = do
126− evald <- eval relExpr
55+ evald <- evalRelationalExpr relExpr
127 case evald of
56 case evald of
128 Right rel -> return $ group oldAttrNameSet newAttrName rel
57 Right rel -> return $ group oldAttrNameSet newAttrName rel
129 Left err -> return $ Left err
58 Left err -> return $ Left err
131−eval (Ungroup attrName relExpr) = do
60+evalRelationalExpr (Ungroup attrName relExpr) = do
132− evald <- eval relExpr
61+ evald <- evalRelationalExpr relExpr
133 case evald of
62 case evald of
134 Right rel -> return $ ungroup attrName rel
63 Right rel -> return $ ungroup attrName rel
135 Left err -> return $ Left err
64 Left err -> return $ Left err
137−eval (Insert relVarName relExpr) = do
66+emptyDatabaseContext :: DatabaseContext
138− evald <- eval $ Assign relVarName (Union relExpr (RelationVariable relVarName))
67+emptyDatabaseContext = DatabaseContext { inclusionDependencies = HS.empty,
139− case evald of
68+ relationVariables = M.empty}
140− Right rel -> return $ evald
69+
141− Left err -> return $ Left err
70+basicDatabaseContext :: DatabaseContext
142−
71+basicDatabaseContext = DatabaseContext { inclusionDependencies = HS.empty,
143−emptyRelVarContext :: RelVarContext
144−emptyRelVarContext = M.empty
146−basicRelVarContext :: RelVarContext
147−basicRelVarContext = M.fromList [("true", relationTrue),
72+ relationVariables = M.fromList [("true", relationTrue),
148− ("false", relationFalse)]
73+ ("false", relationFalse)]}
150−dateExamples :: RelVarContext
75+dateExamples :: DatabaseContext
151−dateExamples = M.union basicRelVarContext dateRelVars
76+dateExamples = DatabaseContext { inclusionDependencies = HS.empty, -- add foreign key relationships
77+ relationVariables = M.union (relationVariables basicDatabaseContext) dateRelVars }
153 dateRelVars = M.fromList [("S", suppliers),
79 dateRelVars = M.fromList [("S", suppliers),
154 ("P", products),
80 ("P", products),
@@ -212,3 +138,57 @@ supplierProductsRel = case mkRelation attributes tupleSet of
212 M.fromList [("S#", StringAtom "S4"), ("P#", StringAtom "P4"), ("QTY", IntAtom 300)],
138 M.fromList [("S#", StringAtom "S4"), ("P#", StringAtom "P4"), ("QTY", IntAtom 300)],
213 M.fromList [("S#", StringAtom "S4"), ("P#", StringAtom "P5"), ("QTY", IntAtom 400)]
139 M.fromList [("S#", StringAtom "S4"), ("P#", StringAtom "P5"), ("QTY", IntAtom 400)]
142+--helper function to process relation variable creation/assignment
143+setRelVar :: String -> Relation -> DatabaseState (Maybe RelationalError)
144+setRelVar relVarName rel = do
146+ let newRelVars = M.insert relVarName rel $ relationVariables state
147+ put $ DatabaseContext (inclusionDependencies state) newRelVars
150+evalContextExpr :: DatabaseExpr -> DatabaseState (Maybe RelationalError)
151+evalContextExpr (Define relVarName attrs) = do
152+ relvars <- liftM relationVariables get
153+ case M.member relVarName relvars of
154+ True -> return (Just (RelVarAlreadyDefinedError relVarName))
155+ False -> setRelVar relVarName emptyRelation
157+ emptyRelation = Relation attrs HS.empty
159+evalContextExpr (Assign relVarName expr) = do
160+ -- in the future, it would be nice to get types from the RelationalExpr instead of needing to evaluate it
161+ relVarTable <- liftM relationVariables get
162+ let existingRelVar = M.lookup relVarName relVarTable
163+ value <- evalRelationalExpr expr
165+ Left err -> return $ Just err
166+ Right rel -> case existingRelVar of
167+ Nothing -> setRelVar relVarName rel
168+ Just existingRel -> if attributes existingRel == attributes rel then
169+ setRelVar relVarName rel
171+ return $ Just RelVarAssignmentTypeMismatchError
173+evalContextExpr (Insert relVarName relExpr) = evalContextExpr $ Assign relVarName (Union relExpr (RelationVariable relVarName))
175+--assign empty rel until restriction is implemented
176+evalContextExpr (Delete relVarName) = do
177+ relVarTable <- liftM relationVariables get
178+ case M.lookup relVarName relVarTable of
179+ Nothing -> return $ Just (RelVarNotDefinedError relVarName)
180+ Just rel -> setRelVar relVarName (Relation (attributes rel) emptyTupleSet)
182+evalContextExpr (Update relVarName attrAssignments) = undefined
184+evalContextExpr (AddInclusionDependency dep) = undefined
186+evalContextExpr (MultipleExpr exprs) = do
187+ evald <- mapM evalContextExpr exprs
190+-- restrict relvar to get affected tuples, update tuples, delete restriction from relvar, relvar = relvar union updated tuples
191+--evalRelVarExpr (Update relVarName updateMap) = do