@@ -13,7 +13,6 @@ import qualified Data.HashSet as HS
13import Control.Monad.State hiding (join)
13import Control.Monad.State hiding (join)
14import Data.Maybe
14import Data.Maybe
15import Data.Either
15import Data.Either
18--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
17--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
19evalRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
18evalRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
@@ -77,7 +76,7 @@ evalRelationalExpr (Restrict predicateExpr relExpr) = do
77 context <- get
76 context <- get
78 case evald of
77 case evald of
79 Left err -> return $ Left err
78 Left err -> return $ Left err
80− Right rel -> case predicateRestrictionFilter context predicateExpr of
79+ Right rel -> case predicateRestrictionFilter context (attributes rel) predicateExpr of
81 Left err -> return $ Left err
80 Left err -> return $ Left err
82 Right filterfunc -> return $ restrict filterfunc rel
81 Right filterfunc -> return $ restrict filterfunc rel
@@ -167,7 +166,7 @@ supplierProductsRel = case mkRelationFromList attrs matrix of
168productsRel :: Relation
167productsRel :: Relation
169productsRel = case mkRelationFromList attrs matrix of
168productsRel = case mkRelationFromList attrs matrix of
170− Left err -> traceShow (show err) undefined
169+ Left _ -> undefined
171 Right rel -> rel
170 Right rel -> rel
173 attrs = A.attributesFromList [Attribute "P#" StringAtomType,
172 attrs = A.attributesFromList [Attribute "P#" StringAtomType,
@@ -242,20 +241,20 @@ evalContextExpr (Delete relVarName predicate) = do
242evalContextExpr (Update relVarName attrAssignments restrictionPredicateExpr) = do
241evalContextExpr (Update relVarName attrAssignments restrictionPredicateExpr) = do
243 currstate <- get
242 currstate <- get
244 let relVarTable = relationVariables currstate
243 let relVarTable = relationVariables currstate
245− case predicateRestrictionFilter currstate restrictionPredicateExpr of
246− Left err -> return $ Just err
247− Right predicateFunc -> do
248− case M.lookup relVarName relVarTable of
244+ case M.lookup relVarName relVarTable of
249− Nothing -> return $ Just (RelVarNotDefinedError relVarName)
245+ Nothing -> return $ Just (RelVarNotDefinedError relVarName)
246+ Just rel -> case predicateRestrictionFilter currstate (attributes rel) restrictionPredicateExpr of
247+ Left err -> return $ Just err
248+ Right predicateFunc -> do
250− Just rel -> case makeUpdatedRel rel of
249+ case makeUpdatedRel rel of
251− Left err -> return $ Just err
250+ Left err -> return $ Just err
252− Right updatedRel -> setRelVar relVarName updatedRel
251+ Right updatedRel -> setRelVar relVarName updatedRel
254− makeUpdatedRel relin = do
253+ makeUpdatedRel relin = do
255− restrictedPortion <- restrict predicateFunc relin
254+ restrictedPortion <- restrict predicateFunc relin
256− unrestrictedPortion <- restrict (not . predicateFunc) relin
255+ unrestrictedPortion <- restrict (not . predicateFunc) relin
257− updatedPortion <- relMap (updateTuple attrAssignments) restrictedPortion
256+ updatedPortion <- relMap (updateTuple attrAssignments) restrictedPortion
258− union updatedPortion unrestrictedPortion
257+ union updatedPortion unrestrictedPortion
260evalContextExpr (AddInclusionDependency dep) = do
259evalContextExpr (AddInclusionDependency dep) = do
261 currstate <- get
260 currstate <- get
@@ -328,24 +327,24 @@ contextWithEmptyTupleSets contextIn = DatabaseContext incDeps relVars funcs
328 funcs = atomFunctions contextIn
327 funcs = atomFunctions contextIn
330{- used for restrictions- take the restrictionpredicate and return the corresponding filter function -}
329{- used for restrictions- take the restrictionpredicate and return the corresponding filter function -}
331−predicateRestrictionFilter :: DatabaseContext -> RestrictionPredicateExpr -> Either RelationalError (RelationTuple -> Bool)
330+predicateRestrictionFilter :: DatabaseContext -> Attributes -> RestrictionPredicateExpr -> Either RelationalError (RelationTuple -> Bool)
332−predicateRestrictionFilter context (AndPredicate expr1 expr2) = do
331+predicateRestrictionFilter context attrs (AndPredicate expr1 expr2) = do
333− expr1v <- predicateRestrictionFilter context expr1
332+ expr1v <- predicateRestrictionFilter context attrs expr1
334− expr2v <- predicateRestrictionFilter context expr2
333+ expr2v <- predicateRestrictionFilter context attrs expr2
335 return $ \x -> expr1v x && expr2v x
334 return $ \x -> expr1v x && expr2v x
337−predicateRestrictionFilter context (OrPredicate expr1 expr2) = do
336+predicateRestrictionFilter context attrs (OrPredicate expr1 expr2) = do
338− expr1v <- predicateRestrictionFilter context expr1
337+ expr1v <- predicateRestrictionFilter context attrs expr1
339− expr2v <- predicateRestrictionFilter context expr2
338+ expr2v <- predicateRestrictionFilter context attrs expr2
340 return $ \x -> expr1v x || expr2v x
339 return $ \x -> expr1v x || expr2v x
342−predicateRestrictionFilter _ TruePredicate = Right $ \_ -> True
341+predicateRestrictionFilter _ _ TruePredicate = Right $ \_ -> True
344−predicateRestrictionFilter context (NotPredicate expr) = do
343+predicateRestrictionFilter context attrs (NotPredicate expr) = do
345− exprv <- predicateRestrictionFilter context expr
344+ exprv <- predicateRestrictionFilter context attrs expr
346 return $ \x -> not (exprv x)
345 return $ \x -> not (exprv x)
348−predicateRestrictionFilter context (RelationalExprPredicate relExpr) = case runState (evalRelationalExpr relExpr) context of
347+predicateRestrictionFilter context _ (RelationalExprPredicate relExpr) = case runState (evalRelationalExpr relExpr) context of
349 (Left err, _) -> Left err
348 (Left err, _) -> Left err
350 (Right rel, _) -> if rel == relationTrue then
349 (Right rel, _) -> if rel == relationTrue then
351 Right $ \_ -> True
350 Right $ \_ -> True
@@ -354,12 +353,22 @@ predicateRestrictionFilter context (RelationalExprPredicate relExpr) = case runS
355 Left $ PredicateExpressionError "Relational restriction filter must evaluate to 'true' or 'false'"
354 Left $ PredicateExpressionError "Relational restriction filter must evaluate to 'true' or 'false'"
357−predicateRestrictionFilter context (AttributeEqualityPredicate attrName atomexpr) = Right $ \tupleIn -> case atomForAttributeName attrName tupleIn of
356+predicateRestrictionFilter context _ (AttributeEqualityPredicate attrName atomexpr) = Right $ \tupleIn -> case atomForAttributeName attrName tupleIn of
358 Left _ -> False
357 Left _ -> False
359 Right atomIn ->
358 Right atomIn ->
360 case evalAtomExpr tupleIn context atomexpr of
359 case evalAtomExpr tupleIn context atomexpr of
361 Left _ -> False
360 Left _ -> False
362 Right atomCmp -> atomCmp == atomIn
361 Right atomCmp -> atomCmp == atomIn
363+-- in the future, it would be useful to do typechecking on the attribute and atom expr filters in advance
364+predicateRestrictionFilter context attrs (AtomExprPredicate atomExpr) = do
365+ aType <- typeFromAtomExpr attrs context atomExpr
366+ if aType /= BoolAtomType then
367+ Left $ AtomTypeMismatchError aType BoolAtomType
369+ Right (\tupleIn -> case evalAtomExpr tupleIn context atomExpr of
371+ Right boolAtomValue -> boolAtomValue == BoolAtom True)
364tupleExprCheckNewAttrName :: AttributeName -> Relation -> Either RelationalError Relation
373tupleExprCheckNewAttrName :: AttributeName -> Relation -> Either RelationalError Relation
365tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName rel then
374tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName rel then
@@ -445,6 +454,30 @@ basicAtomFunctions = HS.fromList [
445 atomFunc = (\((RelationAtom relIn):_) -> relationMax relIn)},
454 atomFunc = (\((RelationAtom relIn):_) -> relationMax relIn)},
446 AtomFunction { atomFuncName = "min",
455 AtomFunction { atomFuncName = "min",
447 atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
456 atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
448− atomFunc = (\((RelationAtom relIn):_) -> relationMin relIn)}
457+ atomFunc = (\((RelationAtom relIn):_) -> relationMin relIn)},
449−
458+ AtomFunction { atomFuncName = "lt",
459+ atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
460+ atomFunc = intAtomFuncLessThan False},
461+ AtomFunction { atomFuncName = "lte",
462+ atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
463+ atomFunc = intAtomFuncLessThan True},
464+ AtomFunction { atomFuncName = "gte",
465+ atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
466+ atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan False},
467+ AtomFunction { atomFuncName = "gt",
468+ atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
469+ atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan True},
470+ AtomFunction { atomFuncName = "not",
471+ atomFuncType = [BoolAtomType, BoolAtomType],
472+ atomFunc = boolAtomNot}
475+intAtomFuncLessThan :: Bool -> [Atom] -> Atom
476+intAtomFuncLessThan equality (iatom1:iatom2:_) = (\(IntAtom i1) (IntAtom i2) -> BoolAtom $ i1 `op` i2) iatom1 iatom2
478+ op = if equality then (<=) else (<)
479+intAtomFuncLessThan _ _= BoolAtom False
481+boolAtomNot :: [Atom] -> Atom
482+boolAtomNot (BoolAtom bool:_) = BoolAtom $ not bool
483+boolAtomNot _ = BoolAtom False