@@ -13,7 +13,6 @@ import qualified Data.HashSet as HS
1313import Control.Monad.State hiding (join)
1414import Data.Maybe
1515import Data.Either
16−import Debug.Trace
1716
1817--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
1918evalRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
@@ -77,7 +76,7 @@ evalRelationalExpr (Restrict predicateExpr relExpr) = do
7776 context <- get
7877 case evald of
7978 Left err -> return $ Left err
80− Right rel -> case predicateRestrictionFilter context predicateExpr of
79+ Right rel -> case predicateRestrictionFilter context (attributes rel) predicateExpr of
8180 Left err -> return $ Left err
8281 Right filterfunc -> return $ restrict filterfunc rel
8382
@@ -167,7 +166,7 @@ supplierProductsRel = case mkRelationFromList attrs matrix of
167166
168167productsRel :: Relation
169168productsRel = case mkRelationFromList attrs matrix of
170− Left err -> traceShow (show err) undefined
169+ Left _ -> undefined
171170 Right rel -> rel
172171 where
173172 attrs = A.attributesFromList [Attribute "P#" StringAtomType,
@@ -242,20 +241,20 @@ evalContextExpr (Delete relVarName predicate) = do
242241evalContextExpr (Update relVarName attrAssignments restrictionPredicateExpr) = do
243242 currstate <- get
244243 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
249− Nothing -> return $ Just (RelVarNotDefinedError relVarName)
250− Just rel -> case makeUpdatedRel rel of
251− Left err -> return $ Just err
252− Right updatedRel -> setRelVar relVarName updatedRel
253− where
254− makeUpdatedRel relin = do
255− restrictedPortion <- restrict predicateFunc relin
256− unrestrictedPortion <- restrict (not . predicateFunc) relin
257− updatedPortion <- relMap (updateTuple attrAssignments) restrictedPortion
258− union updatedPortion unrestrictedPortion
244+ case M.lookup relVarName relVarTable of
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
249+ case makeUpdatedRel rel of
250+ Left err -> return $ Just err
251+ Right updatedRel -> setRelVar relVarName updatedRel
252+ where
253+ makeUpdatedRel relin = do
254+ restrictedPortion <- restrict predicateFunc relin
255+ unrestrictedPortion <- restrict (not . predicateFunc) relin
256+ updatedPortion <- relMap (updateTuple attrAssignments) restrictedPortion
257+ union updatedPortion unrestrictedPortion
259258
260259evalContextExpr (AddInclusionDependency dep) = do
261260 currstate <- get
@@ -328,24 +327,24 @@ contextWithEmptyTupleSets contextIn = DatabaseContext incDeps relVars funcs
328327 funcs = atomFunctions contextIn
329328
330329{- used for restrictions- take the restrictionpredicate and return the corresponding filter function -}
331−predicateRestrictionFilter :: DatabaseContext -> RestrictionPredicateExpr -> Either RelationalError (RelationTuple -> Bool)
332−predicateRestrictionFilter context (AndPredicate expr1 expr2) = do
333− expr1v <- predicateRestrictionFilter context expr1
334− expr2v <- predicateRestrictionFilter context expr2
330+predicateRestrictionFilter :: DatabaseContext -> Attributes -> RestrictionPredicateExpr -> Either RelationalError (RelationTuple -> Bool)
331+predicateRestrictionFilter context attrs (AndPredicate expr1 expr2) = do
332+ expr1v <- predicateRestrictionFilter context attrs expr1
333+ expr2v <- predicateRestrictionFilter context attrs expr2
335334 return $ \x -> expr1v x && expr2v x
336335
337−predicateRestrictionFilter context (OrPredicate expr1 expr2) = do
338− expr1v <- predicateRestrictionFilter context expr1
339− expr2v <- predicateRestrictionFilter context expr2
336+predicateRestrictionFilter context attrs (OrPredicate expr1 expr2) = do
337+ expr1v <- predicateRestrictionFilter context attrs expr1
338+ expr2v <- predicateRestrictionFilter context attrs expr2
340339 return $ \x -> expr1v x || expr2v x
341340
342−predicateRestrictionFilter _ TruePredicate = Right $ \_ -> True
341+predicateRestrictionFilter _ _ TruePredicate = Right $ \_ -> True
343342
344−predicateRestrictionFilter context (NotPredicate expr) = do
345− exprv <- predicateRestrictionFilter context expr
343+predicateRestrictionFilter context attrs (NotPredicate expr) = do
344+ exprv <- predicateRestrictionFilter context attrs expr
346345 return $ \x -> not (exprv x)
347346
348−predicateRestrictionFilter context (RelationalExprPredicate relExpr) = case runState (evalRelationalExpr relExpr) context of
347+predicateRestrictionFilter context _ (RelationalExprPredicate relExpr) = case runState (evalRelationalExpr relExpr) context of
349348 (Left err, _) -> Left err
350349 (Right rel, _) -> if rel == relationTrue then
351350 Right $ \_ -> True
@@ -354,12 +353,22 @@ predicateRestrictionFilter context (RelationalExprPredicate relExpr) = case runS
354353 else
355354 Left $ PredicateExpressionError "Relational restriction filter must evaluate to 'true' or 'false'"
356355
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
358357 Left _ -> False
359358 Right atomIn ->
360359 case evalAtomExpr tupleIn context atomexpr of
361360 Left _ -> False
362361 Right atomCmp -> atomCmp == atomIn
362+
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
368+ else
369+ Right (\tupleIn -> case evalAtomExpr tupleIn context atomExpr of
370+ Left _ -> False
371+ Right boolAtomValue -> boolAtomValue == BoolAtom True)
363372
364373tupleExprCheckNewAttrName :: AttributeName -> Relation -> Either RelationalError Relation
365374tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName rel then
@@ -445,6 +454,30 @@ basicAtomFunctions = HS.fromList [
445454 atomFunc = (\((RelationAtom relIn):_) -> relationMax relIn)},
446455 AtomFunction { atomFuncName = "min",
447456 atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
448− atomFunc = (\((RelationAtom relIn):_) -> relationMin relIn)}
449−
457+ atomFunc = (\((RelationAtom relIn):_) -> relationMin relIn)},
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}
450473 ]
474+
475+intAtomFuncLessThan :: Bool -> [Atom] -> Atom
476+intAtomFuncLessThan equality (iatom1:iatom2:_) = (\(IntAtom i1) (IntAtom i2) -> BoolAtom $ i1 `op` i2) iatom1 iatom2
477+ where
478+ op = if equality then (<=) else (<)
479+intAtomFuncLessThan _ _= BoolAtom False
480+
481+boolAtomNot :: [Atom] -> Atom
482+boolAtomNot (BoolAtom bool:_) = BoolAtom $ not bool
483+boolAtomNot _ = BoolAtom False