@@ -15,6 +15,7 @@ import qualified Data.Set as S
15import Control.Monad.State hiding (join)
15import Control.Monad.State hiding (join)
16import Data.Maybe
16import Data.Maybe
17import Data.Either
17import Data.Either
18+import Data.Typeable (cast)
19--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
20--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
20evalRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
21evalRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
@@ -22,11 +23,11 @@ evalRelationalExpr (RelationVariable name) = do
22 relvarTable <- liftM relationVariables get
23 relvarTable <- liftM relationVariables get
23 return $ case M.lookup name relvarTable of
24 return $ case M.lookup name relvarTable of
24 Just res -> Right res
25 Just res -> Right res
25− Nothing -> Left $ RelVarNotDefinedError name
26+ Nothing -> Left $ RelVarNotDefinedError name
27evalRelationalExpr (Project attrNames expr) = do
28evalRelationalExpr (Project attrNames expr) = do
28 rel <- evalRelationalExpr expr
29 rel <- evalRelationalExpr expr
29− case rel of
30+ case rel of
30 Right rel2 -> return $ project attrNames rel2
31 Right rel2 -> return $ project attrNames rel2
31 Left err -> return $ Left err
32 Left err -> return $ Left err
@@ -47,71 +48,71 @@ evalRelationalExpr (Join exprA exprB) = do
47 Right relA2 -> case relB of
48 Right relA2 -> case relB of
48 Left err -> return $ Left err
49 Left err -> return $ Left err
49 Right relB2 -> return $ join relA2 relB2
50 Right relB2 -> return $ join relA2 relB2
51evalRelationalExpr (MakeStaticRelation attributeSet tupleSet) = do
52evalRelationalExpr (MakeStaticRelation attributeSet tupleSet) = do
52 case mkRelation attributeSet tupleSet of
53 case mkRelation attributeSet tupleSet of
53 Right rel -> return $ Right rel
54 Right rel -> return $ Right rel
54 Left err -> return $ Left err
55 Left err -> return $ Left err
56evalRelationalExpr (ExistingRelation rel) = return (Right rel)
57evalRelationalExpr (ExistingRelation rel) = return (Right rel)
58evalRelationalExpr (Rename oldAttrName newAttrName relExpr) = do
59evalRelationalExpr (Rename oldAttrName newAttrName relExpr) = do
59 evald <- evalRelationalExpr relExpr
60 evald <- evalRelationalExpr relExpr
60 case evald of
61 case evald of
61 Right rel -> return $ rename oldAttrName newAttrName rel
62 Right rel -> return $ rename oldAttrName newAttrName rel
62 Left err -> return $ Left err
63 Left err -> return $ Left err
64evalRelationalExpr (Group oldAttrNameSet newAttrName relExpr) = do
65evalRelationalExpr (Group oldAttrNameSet newAttrName relExpr) = do
65 evald <- evalRelationalExpr relExpr
66 evald <- evalRelationalExpr relExpr
66− case evald of
67+ case evald of
67 Right rel -> return $ group oldAttrNameSet newAttrName rel
68 Right rel -> return $ group oldAttrNameSet newAttrName rel
68 Left err -> return $ Left err
69 Left err -> return $ Left err
70evalRelationalExpr (Ungroup attrName relExpr) = do
71evalRelationalExpr (Ungroup attrName relExpr) = do
71 evald <- evalRelationalExpr relExpr
72 evald <- evalRelationalExpr relExpr
72 case evald of
73 case evald of
73 Right rel -> return $ ungroup attrName rel
74 Right rel -> return $ ungroup attrName rel
74 Left err -> return $ Left err
75 Left err -> return $ Left err
76evalRelationalExpr (Restrict predicateExpr relExpr) = do
77evalRelationalExpr (Restrict predicateExpr relExpr) = do
77 evald <- evalRelationalExpr relExpr
78 evald <- evalRelationalExpr relExpr
78 context <- get
79 context <- get
79− case evald of
80+ case evald of
80 Left err -> return $ Left err
81 Left err -> return $ Left err
81 Right rel -> case predicateRestrictionFilter context (attributes rel) predicateExpr of
82 Right rel -> case predicateRestrictionFilter context (attributes rel) predicateExpr of
82 Left err -> return $ Left err
83 Left err -> return $ Left err
83 Right filterfunc -> return $ restrict filterfunc rel
84 Right filterfunc -> return $ restrict filterfunc rel
85evalRelationalExpr (Equals relExprA relExprB) = do
86evalRelationalExpr (Equals relExprA relExprB) = do
86 evaldA <- evalRelationalExpr relExprA
87 evaldA <- evalRelationalExpr relExprA
87 evaldB <- evalRelationalExpr relExprB
88 evaldB <- evalRelationalExpr relExprB
88 case evaldA of
89 case evaldA of
89 Left err -> return $ Left err
90 Left err -> return $ Left err
90− Right relA -> case evaldB of
91+ Right relA -> case evaldB of
91 Left err -> return $ Left err
92 Left err -> return $ Left err
92 Right relB -> return $ Right $ if relA == relB then relationTrue else relationFalse
93 Right relB -> return $ Right $ if relA == relB then relationTrue else relationFalse
94--warning: copy-pasta from above- refactor
95--warning: copy-pasta from above- refactor
95evalRelationalExpr (NotEquals relExprA relExprB) = do
96evalRelationalExpr (NotEquals relExprA relExprB) = do
96 evaldA <- evalRelationalExpr relExprA
97 evaldA <- evalRelationalExpr relExprA
97 evaldB <- evalRelationalExpr relExprB
98 evaldB <- evalRelationalExpr relExprB
98 case evaldA of
99 case evaldA of
99 Left err -> return $ Left err
100 Left err -> return $ Left err
100− Right relA -> case evaldB of
101+ Right relA -> case evaldB of
101 Left err -> return $ Left err
102 Left err -> return $ Left err
102 Right relB -> return $ Right $ if relA /= relB then relationTrue else relationFalse
103 Right relB -> return $ Right $ if relA /= relB then relationTrue else relationFalse
104−-- extending a relation adds a single attribute with the results of the per-tuple expression evaluated
105+-- extending a relation adds a single attribute with the results of the per-tuple expression evaluated
105−evalRelationalExpr (Extend tupleExpression relExpr) = do
106+evalRelationalExpr (Extend tupleExpression relExpr) = do
106 evald <- evalRelationalExpr relExpr
107 evald <- evalRelationalExpr relExpr
107 context <- get
108 context <- get
108− case evald of
109+ case evald of
109 Left err -> return $ Left err
110 Left err -> return $ Left err
110 Right rel -> do
111 Right rel -> do
111 case tupleExpressionProcessor rel tupleExpression context of
112 case tupleExpressionProcessor rel tupleExpression context of
112 Left err -> return $ Left err
113 Left err -> return $ Left err
113 Right (newAttrs, tupProc) -> return $ relMogrify tupProc newAttrs rel
114 Right (newAttrs, tupProc) -> return $ relMogrify tupProc newAttrs rel
115emptyDatabaseContext :: DatabaseContext
116emptyDatabaseContext :: DatabaseContext
116emptyDatabaseContext = DatabaseContext { inclusionDependencies = M.empty,
117emptyDatabaseContext = DatabaseContext { inclusionDependencies = M.empty,
117 relationVariables = M.empty,
118 relationVariables = M.empty,
@@ -126,8 +127,8 @@ basicDatabaseContext = DatabaseContext { inclusionDependencies = M.empty,
128dateExamples :: DatabaseContext
129dateExamples :: DatabaseContext
129−dateExamples = DatabaseContext { inclusionDependencies = dateIncDeps,
130+dateExamples = DatabaseContext { inclusionDependencies = dateIncDeps,
130− relationVariables = M.union (relationVariables basicDatabaseContext) dateRelVars,
131+ relationVariables = M.union (relationVariables basicDatabaseContext) dateRelVars,
131 atomFunctions = basicAtomFunctions}
132 atomFunctions = basicAtomFunctions}
133 dateRelVars = M.fromList [("S", suppliers),
134 dateRelVars = M.fromList [("S", suppliers),
@@ -141,77 +142,77 @@ dateExamples = DatabaseContext { inclusionDependencies = dateIncDeps,
141 ("SP_pkey", simplePKey ["S#", "P#"] "SP")
142 ("SP_pkey", simplePKey ["S#", "P#"] "SP")
143 simplePKey attrNames relvarName = inclusionDependencyForKey (AttributeNames $ S.fromList attrNames) (RelationVariable relvarName)
144 simplePKey attrNames relvarName = inclusionDependencyForKey (AttributeNames $ S.fromList attrNames) (RelationVariable relvarName)
145−suppliersRel :: Relation
146+suppliersRel :: Relation
146suppliersRel = case mkRelationFromList attrs atomMatrix of
147suppliersRel = case mkRelationFromList attrs atomMatrix of
147 Left _ -> undefined
148 Left _ -> undefined
148 Right rel -> rel
149 Right rel -> rel
150− attrs = A.attributesFromList [Attribute "S#" StringAtomType,
151+ attrs = A.attributesFromList [Attribute "S#" stringAtomType,
151− Attribute "SNAME" StringAtomType,
152+ Attribute "SNAME" stringAtomType,
152− Attribute "STATUS" IntAtomType,
153+ Attribute "STATUS" intAtomType,
153− Attribute "CITY" StringAtomType]
154+ Attribute "CITY" stringAtomType]
154 atomMatrix = [
155 atomMatrix = [
155− [StringAtom "S1", StringAtom "Smith", IntAtom 20, StringAtom "London"],
156+ [stringAtom "S1", stringAtom "Smith", intAtom 20, stringAtom "London"],
156− [StringAtom "S2", StringAtom "Jones", IntAtom 10, StringAtom "Paris"],
157+ [stringAtom "S2", stringAtom "Jones", intAtom 10, stringAtom "Paris"],
157− [StringAtom "S3", StringAtom "Blake", IntAtom 30, StringAtom "Paris"],
158+ [stringAtom "S3", stringAtom "Blake", intAtom 30, stringAtom "Paris"],
158− [StringAtom "S4", StringAtom "Clark", IntAtom 20, StringAtom "London"],
159+ [stringAtom "S4", stringAtom "Clark", intAtom 20, stringAtom "London"],
159− [StringAtom "S5", StringAtom "Adams", IntAtom 30, StringAtom "Athens"]]
160+ [stringAtom "S5", stringAtom "Adams", intAtom 30, stringAtom "Athens"]]
161supplierProductsRel :: Relation
162supplierProductsRel :: Relation
162supplierProductsRel = case mkRelationFromList attrs matrix of
163supplierProductsRel = case mkRelationFromList attrs matrix of
163 Left _ -> undefined
164 Left _ -> undefined
164 Right rel -> rel
165 Right rel -> rel
166− attrs = A.attributesFromList [Attribute "S#" StringAtomType,
167+ attrs = A.attributesFromList [Attribute "S#" stringAtomType,
167− Attribute "P#" StringAtomType,
168+ Attribute "P#" stringAtomType,
168− Attribute "QTY" IntAtomType]
169+ Attribute "QTY" intAtomType]
169 matrix = [
170 matrix = [
170− [StringAtom "S1", StringAtom "P1", IntAtom 300],
171+ [stringAtom "S1", stringAtom "P1", intAtom 300],
171− [StringAtom "S1", StringAtom "P2", IntAtom 200],
172+ [stringAtom "S1", stringAtom "P2", intAtom 200],
172− [StringAtom "S1", StringAtom "P3", IntAtom 400],
173+ [stringAtom "S1", stringAtom "P3", intAtom 400],
173− [StringAtom "S1", StringAtom "P4", IntAtom 200],
174+ [stringAtom "S1", stringAtom "P4", intAtom 200],
174− [StringAtom "S1", StringAtom "P5", IntAtom 100],
175+ [stringAtom "S1", stringAtom "P5", intAtom 100],
175− [StringAtom "S1", StringAtom "P6", IntAtom 100],
176+ [stringAtom "S1", stringAtom "P6", intAtom 100],
176− [StringAtom "S2", StringAtom "P1", IntAtom 300],
177+ [stringAtom "S2", stringAtom "P1", intAtom 300],
177− [StringAtom "S2", StringAtom "P2", IntAtom 400],
178+ [stringAtom "S2", stringAtom "P2", intAtom 400],
178− [StringAtom "S3", StringAtom "P2", IntAtom 200],
179+ [stringAtom "S3", stringAtom "P2", intAtom 200],
179− [StringAtom "S4", StringAtom "P2", IntAtom 200],
180+ [stringAtom "S4", stringAtom "P2", intAtom 200],
180− [StringAtom "S4", StringAtom "P4", IntAtom 300],
181+ [stringAtom "S4", stringAtom "P4", intAtom 300],
181− [StringAtom "S4", StringAtom "P5", IntAtom 400]
182+ [stringAtom "S4", stringAtom "P5", intAtom 400]
184−productsRel :: Relation
185+productsRel :: Relation
185productsRel = case mkRelationFromList attrs matrix of
186productsRel = case mkRelationFromList attrs matrix of
186 Left _ -> undefined
187 Left _ -> undefined
187 Right rel -> rel
188 Right rel -> rel
189− attrs = A.attributesFromList [Attribute "P#" StringAtomType,
190+ attrs = A.attributesFromList [Attribute "P#" stringAtomType,
190− Attribute "PNAME" StringAtomType,
191+ Attribute "PNAME" stringAtomType,
191− Attribute "COLOR" StringAtomType,
192+ Attribute "COLOR" stringAtomType,
192− Attribute "WEIGHT" IntAtomType,
193+ Attribute "WEIGHT" intAtomType,
193− Attribute "CITY" StringAtomType]
194+ Attribute "CITY" stringAtomType]
194− matrix = [
195+ matrix = [
195− [StringAtom "P1", StringAtom "Nut", StringAtom "Red", IntAtom 12, StringAtom "London"],
196+ [stringAtom "P1", stringAtom "Nut", stringAtom "Red", intAtom 12, stringAtom "London"],
196− [StringAtom "P2", StringAtom "Bolt", StringAtom "Green", IntAtom 17, StringAtom "Paris"],
197+ [stringAtom "P2", stringAtom "Bolt", stringAtom "Green", intAtom 17, stringAtom "Paris"],
197− [StringAtom "P3", StringAtom "Screw", StringAtom "Blue", IntAtom 17, StringAtom "Oslo"],
198+ [stringAtom "P3", stringAtom "Screw", stringAtom "Blue", intAtom 17, stringAtom "Oslo"],
198− [StringAtom "P4", StringAtom "Screw", StringAtom "Red", IntAtom 14, StringAtom "London"],
199+ [stringAtom "P4", stringAtom "Screw", stringAtom "Red", intAtom 14, stringAtom "London"],
199− [StringAtom "P5", StringAtom "Cam", StringAtom "Blue", IntAtom 12, StringAtom "Paris"],
200+ [stringAtom "P5", stringAtom "Cam", stringAtom "Blue", intAtom 12, stringAtom "Paris"],
200− [StringAtom "P6", StringAtom "Cog", StringAtom "Red", IntAtom 19, StringAtom "London"]
201+ [stringAtom "P6", stringAtom "Cog", stringAtom "Red", intAtom 19, stringAtom "London"]
203−--helper function to process relation variable creation/assignment
204+--helper function to process relation variable creation/assignment
204setRelVar :: RelVarName -> Relation -> DatabaseState (Maybe RelationalError)
205setRelVar :: RelVarName -> Relation -> DatabaseState (Maybe RelationalError)
205−setRelVar relVarName rel = do
206+setRelVar relVarName rel = do
206 currentContext <- get
207 currentContext <- get
207 let newRelVars = M.insert relVarName rel $ relationVariables currentContext
208 let newRelVars = M.insert relVarName rel $ relationVariables currentContext
208 let potentialContext = DatabaseContext (inclusionDependencies currentContext) newRelVars (atomFunctions currentContext)
209 let potentialContext = DatabaseContext (inclusionDependencies currentContext) newRelVars (atomFunctions currentContext)
209 case checkConstraints potentialContext of
210 case checkConstraints potentialContext of
210 Just err -> return $ Just err
211 Just err -> return $ Just err
211− Nothing -> do
212+ Nothing -> do
212 put potentialContext
213 put potentialContext
213 return Nothing
214 return Nothing
215-- 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
216-- 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
216deleteRelVar :: RelVarName -> DatabaseState (Maybe RelationalError)
217deleteRelVar :: RelVarName -> DatabaseState (Maybe RelationalError)
217deleteRelVar relVarName = do
218deleteRelVar relVarName = do
@@ -223,31 +224,31 @@ deleteRelVar relVarName = do
223evalContextExpr :: DatabaseExpr -> DatabaseState (Maybe RelationalError)
224evalContextExpr :: DatabaseExpr -> DatabaseState (Maybe RelationalError)
224evalContextExpr (Define relVarName attrs) = do
225evalContextExpr (Define relVarName attrs) = do
225 relvars <- liftM relationVariables get
226 relvars <- liftM relationVariables get
226− case M.member relVarName relvars of
227+ case M.member relVarName relvars of
227 True -> return (Just (RelVarAlreadyDefinedError relVarName))
228 True -> return (Just (RelVarAlreadyDefinedError relVarName))
228 False -> setRelVar relVarName emptyRelation
229 False -> setRelVar relVarName emptyRelation
230 emptyRelation = Relation attrs emptyTupleSet
231 emptyRelation = Relation attrs emptyTupleSet
232evalContextExpr (Undefine relVarName) = do
233evalContextExpr (Undefine relVarName) = do
233 deleteRelVar relVarName
234 deleteRelVar relVarName
235evalContextExpr (Assign relVarName expr) = do
236evalContextExpr (Assign relVarName expr) = do
236 -- in the future, it would be nice to get types from the RelationalExpr instead of needing to evaluate it
237 -- in the future, it would be nice to get types from the RelationalExpr instead of needing to evaluate it
237 relVarTable <- liftM relationVariables get
238 relVarTable <- liftM relationVariables get
238 let existingRelVar = M.lookup relVarName relVarTable
239 let existingRelVar = M.lookup relVarName relVarTable
239− value <- evalRelationalExpr expr
240+ value <- evalRelationalExpr expr
240− case value of
241+ case value of
241 Left err -> return $ Just err
242 Left err -> return $ Just err
242− Right rel -> case existingRelVar of
243+ Right rel -> case existingRelVar of
243 Nothing -> setRelVar relVarName rel
244 Nothing -> setRelVar relVarName rel
244 Just existingRel -> let expectedAttributes = attributes existingRel
245 Just existingRel -> let expectedAttributes = attributes existingRel
245 foundAttributes = attributes rel in
246 foundAttributes = attributes rel in
246− if A.attributesEqual expectedAttributes foundAttributes then
247+ if A.attributesEqual expectedAttributes foundAttributes then
247 setRelVar relVarName rel
248 setRelVar relVarName rel
249 return $ Just (RelVarAssignmentTypeMismatchError expectedAttributes foundAttributes)
250 return $ Just (RelVarAssignmentTypeMismatchError expectedAttributes foundAttributes)
251evalContextExpr (Insert relVarName relExpr) = evalContextExpr $ Assign relVarName (Union relExpr (RelationVariable relVarName))
252evalContextExpr (Insert relVarName relExpr) = evalContextExpr $ Assign relVarName (Union relExpr (RelationVariable relVarName))
253--assign empty rel until restriction is implemented
254--assign empty rel until restriction is implemented
@@ -256,16 +257,16 @@ evalContextExpr (Delete relVarName predicate) = do
256 case updatedRel of
257 case updatedRel of
257 Left err -> return $ Just err
258 Left err -> return $ Just err
258 Right rel -> setRelVar relVarName rel
259 Right rel -> setRelVar relVarName rel
260--union of restricted+updated portion and the unrestricted+unupdated portion
261--union of restricted+updated portion and the unrestricted+unupdated portion
261evalContextExpr (Update relVarName attrAssignments restrictionPredicateExpr) = do
262evalContextExpr (Update relVarName attrAssignments restrictionPredicateExpr) = do
262 currstate <- get
263 currstate <- get
263− let relVarTable = relationVariables currstate
264+ let relVarTable = relationVariables currstate
264 case M.lookup relVarName relVarTable of
265 case M.lookup relVarName relVarTable of
265 Nothing -> return $ Just (RelVarNotDefinedError relVarName)
266 Nothing -> return $ Just (RelVarNotDefinedError relVarName)
266 Just rel -> case predicateRestrictionFilter currstate (attributes rel) restrictionPredicateExpr of
267 Just rel -> case predicateRestrictionFilter currstate (attributes rel) restrictionPredicateExpr of
267 Left err -> return $ Just err
268 Left err -> return $ Just err
268− Right predicateFunc -> do
269+ Right predicateFunc -> do
269 case makeUpdatedRel rel of
270 case makeUpdatedRel rel of
270 Left err -> return $ Just err
271 Left err -> return $ Just err
271 Right updatedRel -> setRelVar relVarName updatedRel
272 Right updatedRel -> setRelVar relVarName updatedRel
@@ -289,8 +290,8 @@ evalContextExpr (AddInclusionDependency newDepName newDep) = do
289 Nothing -> do
290 Nothing -> do
290 put potentialContext
291 put potentialContext
291 return Nothing
292 return Nothing
293−evalContextExpr (RemoveInclusionDependency depName) = do
294+evalContextExpr (RemoveInclusionDependency depName) = do
294 currContext <- get
295 currContext <- get
295 let currDeps = inclusionDependencies currContext
296 let currDeps = inclusionDependencies currContext
296 newDeps = M.delete depName currDeps
297 newDeps = M.delete depName currDeps
@@ -307,13 +308,13 @@ evalContextExpr (MultipleExpr exprs) = do
307 case catMaybes evald of
308 case catMaybes evald of
308 [] -> return $ Nothing
309 [] -> return $ Nothing
309 err:_ -> return $ Just err
310 err:_ -> return $ Just err
311−-- restrict relvar to get affected tuples, update tuples, delete restriction from relvar, relvar = relvar union updated tuples
312+-- restrict relvar to get affected tuples, update tuples, delete restriction from relvar, relvar = relvar union updated tuples
312--evalRelVarExpr (Update relVarName updateMap) = do
313--evalRelVarExpr (Update relVarName updateMap) = do
314--run verification on all constraints
315--run verification on all constraints
315checkConstraints :: DatabaseContext -> Maybe RelationalError
316checkConstraints :: DatabaseContext -> Maybe RelationalError
316−checkConstraints context = case failures of
317+checkConstraints context = case failures of
317 [] -> Nothing
318 [] -> Nothing
318 l:_ -> Just l
319 l:_ -> Just l
@@ -321,13 +322,13 @@ checkConstraints context = case failures of
321 deps = inclusionDependencies context
322 deps = inclusionDependencies context
322 eval expr = runState (evalRelationalExpr expr) context
323 eval expr = runState (evalRelationalExpr expr) context
323 checkIncDep depName (InclusionDependency subsetExpr supersetExpr) = case evaldSub of
324 checkIncDep depName (InclusionDependency subsetExpr supersetExpr) = case evaldSub of
324− (Left err, _) -> Just err
325+ (Left err, _) -> Just err
325 (Right relSub, _) -> case evaldSuper of
326 (Right relSub, _) -> case evaldSuper of
326 (Left err, _) -> Just err
327 (Left err, _) -> Just err
327 (Right relSuper, _) -> case union relSub relSuper of
328 (Right relSuper, _) -> case union relSub relSuper of
328 Left err -> Just err
329 Left err -> Just err
329− Right resultRel -> if resultRel == relSuper then
330+ Right resultRel -> if resultRel == relSuper then
330− Nothing
331+ Nothing
332 Just $ InclusionDependencyCheckError depName
333 Just $ InclusionDependencyCheckError depName
@@ -339,32 +340,32 @@ checkConstraint :: InclusionDependency -> DatabaseState (Maybe RelationalError)
339checkConstraint (InclusionDependency name subDep superDep) = do
340checkConstraint (InclusionDependency name subDep superDep) = do
340 evalSub <- evalRelationalExpr subDep
341 evalSub <- evalRelationalExpr subDep
341 evalSuper <- evalRelationalExpr superDep
342 evalSuper <- evalRelationalExpr superDep
342− case evalSub of
343+ case evalSub of
343 Left err -> Just err
344 Left err -> Just err
344− Right relSub
345+ Right relSub
345 result <- liftM2 union evalSub evalSuper
346 result <- liftM2 union evalSub evalSuper
346 return $ Nothing
347 return $ Nothing
349-- the type of a relational expression is equal to the relation attribute set returned from executing the relational expression; therefore, the type can be cheaply derived by evaluating a relational expression and ignoring and tuple processing
350-- the type of a relational expression is equal to the relation attribute set returned from executing the relational expression; therefore, the type can be cheaply derived by evaluating a relational expression and ignoring and tuple processing
350-- furthermore, the type of a relational expression is the resultant header of the evaluated empty-tupled relation
351-- furthermore, the type of a relational expression is the resultant header of the evaluated empty-tupled relation
352typeForRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
353typeForRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
353typeForRelationalExpr expr = do
354typeForRelationalExpr expr = do
354 currstate <- get
355 currstate <- get
355 --replace the relationVariables context element with a cloned set of relation devoid of tuples
356 --replace the relationVariables context element with a cloned set of relation devoid of tuples
356 put $ contextWithEmptyTupleSets currstate
357 put $ contextWithEmptyTupleSets currstate
357 evalRelationalExpr expr
358 evalRelationalExpr expr
359−--returns a database context with all tuples removed
360+--returns a database context with all tuples removed
360--this is useful for type checking and optimization
361--this is useful for type checking and optimization
361contextWithEmptyTupleSets :: DatabaseContext -> DatabaseContext
362contextWithEmptyTupleSets :: DatabaseContext -> DatabaseContext
362contextWithEmptyTupleSets contextIn = DatabaseContext incDeps relVars funcs
363contextWithEmptyTupleSets contextIn = DatabaseContext incDeps relVars funcs
364− incDeps = inclusionDependencies contextIn
365+ incDeps = inclusionDependencies contextIn
365 relVars = M.map (\rel -> Relation (attributes rel) emptyTupleSet) (relationVariables contextIn)
366 relVars = M.map (\rel -> Relation (attributes rel) emptyTupleSet) (relationVariables contextIn)
366 funcs = atomFunctions contextIn
367 funcs = atomFunctions contextIn
368{- used for restrictions- take the restrictionpredicate and return the corresponding filter function -}
369{- used for restrictions- take the restrictionpredicate and return the corresponding filter function -}
369predicateRestrictionFilter :: DatabaseContext -> Attributes -> RestrictionPredicateExpr -> Either RelationalError (RelationTuple -> Bool)
370predicateRestrictionFilter :: DatabaseContext -> Attributes -> RestrictionPredicateExpr -> Either RelationalError (RelationTuple -> Bool)
370predicateRestrictionFilter context attrs (AndPredicate expr1 expr2) = do
371predicateRestrictionFilter context attrs (AndPredicate expr1 expr2) = do
@@ -376,9 +377,9 @@ predicateRestrictionFilter context attrs (OrPredicate expr1 expr2) = do
376 expr1v <- predicateRestrictionFilter context attrs expr1
377 expr1v <- predicateRestrictionFilter context attrs expr1
377 expr2v <- predicateRestrictionFilter context attrs expr2
378 expr2v <- predicateRestrictionFilter context attrs expr2
378 return $ \x -> expr1v x || expr2v x
379 return $ \x -> expr1v x || expr2v x
380predicateRestrictionFilter _ _ TruePredicate = Right $ \_ -> True
381predicateRestrictionFilter _ _ TruePredicate = Right $ \_ -> True
382predicateRestrictionFilter context attrs (NotPredicate expr) = do
383predicateRestrictionFilter context attrs (NotPredicate expr) = do
383 exprv <- predicateRestrictionFilter context attrs expr
384 exprv <- predicateRestrictionFilter context attrs expr
384 return $ \x -> not (exprv x)
385 return $ \x -> not (exprv x)
@@ -386,12 +387,12 @@ predicateRestrictionFilter context attrs (NotPredicate expr) = do
386predicateRestrictionFilter context _ (RelationalExprPredicate relExpr) = case runState (evalRelationalExpr relExpr) context of
387predicateRestrictionFilter context _ (RelationalExprPredicate relExpr) = case runState (evalRelationalExpr relExpr) context of
387 (Left err, _) -> Left err
388 (Left err, _) -> Left err
388 (Right rel, _) -> if rel == relationTrue then
389 (Right rel, _) -> if rel == relationTrue then
389− Right $ \_ -> True
390+ Right $ \_ -> True
390 else if rel == relationFalse then
391 else if rel == relationFalse then
391− Right $ \_ -> False
392+ Right $ \_ -> False
393 Left $ PredicateExpressionError "Relational restriction filter must evaluate to 'true' or 'false'"
394 Left $ PredicateExpressionError "Relational restriction filter must evaluate to 'true' or 'false'"
395predicateRestrictionFilter context attrs (AttributeEqualityPredicate attrName atomExpr) = do
396predicateRestrictionFilter context attrs (AttributeEqualityPredicate attrName atomExpr) = do
396 attr <- A.attributeForName attrName attrs
397 attr <- A.attributeForName attrName attrs
397 atomExprType <- typeFromAtomExpr attrs context atomExpr
398 atomExprType <- typeFromAtomExpr attrs context atomExpr
@@ -400,20 +401,20 @@ predicateRestrictionFilter context attrs (AttributeEqualityPredicate attrName at
401 Right $ \tupleIn -> case atomForAttributeName attrName tupleIn of
402 Right $ \tupleIn -> case atomForAttributeName attrName tupleIn of
402 Left _ -> False
403 Left _ -> False
403− Right atomIn ->
404+ Right atomIn ->
404 case evalAtomExpr tupleIn context atomExpr of
405 case evalAtomExpr tupleIn context atomExpr of
405 Left _ -> False
406 Left _ -> False
406 Right atomCmp -> atomCmp == atomIn
407 Right atomCmp -> atomCmp == atomIn
408−-- in the future, it would be useful to do typechecking on the attribute and atom expr filters in advance
409+-- in the future, it would be useful to do typechecking on the attribute and atom expr filters in advance
409−predicateRestrictionFilter context attrs (AtomExprPredicate atomExpr) = do
410+predicateRestrictionFilter context attrs (AtomExprPredicate atomExpr) = do
410 aType <- typeFromAtomExpr attrs context atomExpr
411 aType <- typeFromAtomExpr attrs context atomExpr
411− if aType /= BoolAtomType then
412+ if aType /= boolAtomType then
412− Left $ AtomTypeMismatchError aType BoolAtomType
413+ Left $ AtomTypeMismatchError aType boolAtomType
414 Right (\tupleIn -> case evalAtomExpr tupleIn context atomExpr of
415 Right (\tupleIn -> case evalAtomExpr tupleIn context atomExpr of
415 Left _ -> False
416 Left _ -> False
416− Right boolAtomValue -> boolAtomValue == BoolAtom True)
417+ Right boolAtomValue -> boolAtomValue == Atom True)
418tupleExprCheckNewAttrName :: AttributeName -> Relation -> Either RelationalError Relation
419tupleExprCheckNewAttrName :: AttributeName -> Relation -> Either RelationalError Relation
419tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName rel then
420tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName rel then
@@ -422,7 +423,7 @@ tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName
422 Right rel
423 Right rel
424tupleExpressionProcessor :: Relation -> TupleExpr -> DatabaseContext -> Either RelationalError (Attributes, RelationTuple -> RelationTuple)
425tupleExpressionProcessor :: Relation -> TupleExpr -> DatabaseContext -> Either RelationalError (Attributes, RelationTuple -> RelationTuple)
425−tupleExpressionProcessor relIn
426+tupleExpressionProcessor relIn
426 (AttributeTupleExpr newAttrName atomExpr) context = do
427 (AttributeTupleExpr newAttrName atomExpr) context = do
427 _ <- tupleExprCheckNewAttrName newAttrName relIn
428 _ <- tupleExprCheckNewAttrName newAttrName relIn
428 atomExprType <- typeFromAtomExpr (attributes relIn) context atomExpr
429 atomExprType <- typeFromAtomExpr (attributes relIn) context atomExpr
@@ -445,12 +446,12 @@ evalAtomExpr tupIn context (FunctionAtomExpr funcName arguments) = do
445 return $ (atomFunc func) evaldArgs
446 return $ (atomFunc func) evaldArgs
446evalAtomExpr _ context (RelationAtomExpr relExpr) = do
447evalAtomExpr _ context (RelationAtomExpr relExpr) = do
447 relAtom <- evalState (evalRelationalExpr relExpr) context
448 relAtom <- evalState (evalRelationalExpr relExpr) context
448− return $ RelationAtom relAtom
449+ return $ Atom relAtom
450typeFromAtomExpr :: Attributes -> DatabaseContext -> AtomExpr -> Either RelationalError AtomType
451typeFromAtomExpr :: Attributes -> DatabaseContext -> AtomExpr -> Either RelationalError AtomType
451typeFromAtomExpr attrs _ (AttributeAtomExpr attrName) = A.atomTypeForAttributeName attrName attrs
452typeFromAtomExpr attrs _ (AttributeAtomExpr attrName) = A.atomTypeForAttributeName attrName attrs
452typeFromAtomExpr _ _ (NakedAtomExpr atom) = Right (atomTypeForAtom atom)
453typeFromAtomExpr _ _ (NakedAtomExpr atom) = Right (atomTypeForAtom atom)
453−typeFromAtomExpr _ context (FunctionAtomExpr funcName _) = do
454+typeFromAtomExpr _ context (FunctionAtomExpr funcName _) = do
454 let funcs = atomFunctions context
455 let funcs = atomFunctions context
455 func <- atomFunctionForName funcName funcs
456 func <- atomFunctionForName funcName funcs
456 return $ last (atomFuncType func)
457 return $ last (atomFuncType func)
@@ -481,49 +482,62 @@ verifyAtomExprTypes _ context (RelationAtomExpr relationExpr) expectedType = do
481 (Left err, _) -> Left err
482 (Left err, _) -> Left err
482 (Right relType, _) -> atomTypeVerify expectedType (RelationAtomType (attributes relType))
483 (Right relType, _) -> atomTypeVerify expectedType (RelationAtomType (attributes relType))
485+--not safe to use without upfront type-checking
486+castRelation :: Atom -> Relation
487+castRelation (Atom atom) = case cast atom of
489+ Nothing -> error "castRelation failure"
491+unsafeCast :: (Atomable a) => Atom -> a
492+unsafeCast (Atom atom) = case cast atom of
494+ Nothing -> error "unsafeCast failed"
484basicAtomFunctions :: AtomFunctions
496basicAtomFunctions :: AtomFunctions
485basicAtomFunctions = HS.fromList [
497basicAtomFunctions = HS.fromList [
486 --match on any relation type
498 --match on any relation type
487− AtomFunction "add" [IntAtomType, IntAtomType, IntAtomType] (\(i1:i2:_) -> (\(IntAtom a) (IntAtom b) -> IntAtom (a + b)) i1 i2),
499+ AtomFunction { atomFuncName = "add",
500+ atomFuncType = [intAtomType, intAtomType, intAtomType],
501+ atomFunc = (\(i1:i2:_) -> Atom $ ((unsafeCast i1)::Int) + unsafeCast i2)},
488 AtomFunction { atomFuncName = "id",
502 AtomFunction { atomFuncName = "id",
489 atomFuncType = [AnyAtomType, AnyAtomType],
503 atomFuncType = [AnyAtomType, AnyAtomType],
490 atomFunc = (\(x:_) -> x)},
504 atomFunc = (\(x:_) -> x)},
491 AtomFunction { atomFuncName = "sum",
505 AtomFunction { atomFuncName = "sum",
492− atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
506+ atomFuncType = foldAtomFuncType intAtomType intAtomType,
493− atomFunc = (\((RelationAtom relIn):_) -> relationSum relIn)},
507+ atomFunc = (\(relAtom:_) -> relationSum $ unsafeCast relAtom)},
494 AtomFunction { atomFuncName = "count",
508 AtomFunction { atomFuncName = "count",
495− atomFuncType = foldAtomFuncType AnyAtomType IntAtomType,
509+ atomFuncType = foldAtomFuncType AnyAtomType intAtomType,
496− atomFunc = (\((RelationAtom relIn):_) -> relationCount relIn)},
510+ atomFunc = (\((relIn):_) -> relationCount (castRelation relIn))},
497 AtomFunction { atomFuncName = "max",
511 AtomFunction { atomFuncName = "max",
498− atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
512+ atomFuncType = foldAtomFuncType intAtomType intAtomType,
499− atomFunc = (\((RelationAtom relIn):_) -> relationMax relIn)},
513+ atomFunc = (\((relIn):_) -> relationMax (castRelation relIn))},
500 AtomFunction { atomFuncName = "min",
514 AtomFunction { atomFuncName = "min",
501− atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
515+ atomFuncType = foldAtomFuncType intAtomType intAtomType,
502− atomFunc = (\((RelationAtom relIn):_) -> relationMin relIn)},
516+ atomFunc = (\((relIn):_) -> relationMin (castRelation relIn))},
503 AtomFunction { atomFuncName = "lt",
517 AtomFunction { atomFuncName = "lt",
504− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
518+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
505 atomFunc = intAtomFuncLessThan False},
519 atomFunc = intAtomFuncLessThan False},
506 AtomFunction { atomFuncName = "lte",
520 AtomFunction { atomFuncName = "lte",
507− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
521+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
508 atomFunc = intAtomFuncLessThan True},
522 atomFunc = intAtomFuncLessThan True},
509 AtomFunction { atomFuncName = "gte",
523 AtomFunction { atomFuncName = "gte",
510− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
524+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
511 atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan False},
525 atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan False},
512 AtomFunction { atomFuncName = "gt",
526 AtomFunction { atomFuncName = "gt",
513− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
527+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
514 atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan True},
528 atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan True},
515 AtomFunction { atomFuncName = "not",
529 AtomFunction { atomFuncName = "not",
516− atomFuncType = [BoolAtomType, BoolAtomType],
530+ atomFuncType = [boolAtomType, boolAtomType],
517 atomFunc = boolAtomNot}
531 atomFunc = boolAtomNot}
520intAtomFuncLessThan :: Bool -> [Atom] -> Atom
534intAtomFuncLessThan :: Bool -> [Atom] -> Atom
521−intAtomFuncLessThan equality (iatom1:iatom2:_) = (\(IntAtom i1) (IntAtom i2) -> BoolAtom $ i1 `op` i2) iatom1 iatom2
535+intAtomFuncLessThan equality (iatom1:iatom2:_) = (\i1 i2 -> Atom $ ((unsafeCast i1)::Int) `op` unsafeCast i2) iatom1 iatom2
523 op = if equality then (<=) else (<)
537 op = if equality then (<=) else (<)
524−intAtomFuncLessThan _ _= BoolAtom False
538+intAtomFuncLessThan _ _= Atom False
526boolAtomNot :: [Atom] -> Atom
540boolAtomNot :: [Atom] -> Atom
527−boolAtomNot (BoolAtom bool:_) = BoolAtom $ not bool
541+boolAtomNot (bool:_) = Atom $ not (unsafeCast bool)
528−boolAtomNot _ = BoolAtom False
542+boolAtomNot _ = Atom False