@@ -4,12 +4,12 @@ module Relation where
4import qualified Data.Map as M
4import qualified Data.Map as M
5import qualified Data.Set as S
5import qualified Data.Set as S
6import qualified Data.HashSet as HS
6import qualified Data.HashSet as HS
7−import qualified Control.Monad.Error as Err
9import RelationType
8import RelationType
10import RelationTuple
9import RelationTuple
11import RelationAttribute
10import RelationAttribute
12import RelationTupleSet
11import RelationTupleSet
12+import RelationalError
14testTuple1 = mkRelationTuple (S.fromList ["hair"]) (M.fromList [("hair", StringAtom "brown")])
14testTuple1 = mkRelationTuple (S.fromList ["hair"]) (M.fromList [("hair", StringAtom "brown")])
@@ -39,18 +39,16 @@ atomValueType (StringAtom _) = StringAtomType
39atomValueType (IntAtom _) = IntAtomType
39atomValueType (IntAtom _) = IntAtomType
40atomValueType (RelationAtom rel) = RelationAtomType (attributes rel)
40atomValueType (RelationAtom rel) = RelationAtomType (attributes rel)
42−instance Err.Error RelationalError where
44mkRelation :: Attributes -> RelationTupleSet -> Either RelationalError Relation
42mkRelation :: Attributes -> RelationTupleSet -> Either RelationalError Relation
45mkRelation attrs tupleSet =
43mkRelation attrs tupleSet =
46 --check that all tuples have the same keys
44 --check that all tuples have the same keys
47 --check that all tuples have keys (1-N) where N is the attribute count
45 --check that all tuples have keys (1-N) where N is the attribute count
48 if differentTupleCounts
46 if differentTupleCounts
49− then Left $ RelationalError 1 "Tuple attribute count mismatch"
47+ then Left $ TupleAttributeCountMismatchError 0
50 else if not (fst (verifyRelationTupleSet tupleSet))
48 else if not (fst (verifyRelationTupleSet tupleSet))
51− then Left $ RelationalError 1 "Tuple values not of the same type for same keys"
49+ then Left $ TupleAttributeTypeMismatchError 0
52 else if attrCountMismatch
50 else if attrCountMismatch
53− then Left $ RelationalError 1 "Attribute count mismatch"
51+ then Left $ AttributeCountMismatchError 0
55 Right $ Relation attrs tupleSet
53 Right $ Relation attrs tupleSet
@@ -70,7 +68,7 @@ madeFalse = mkRelation M.empty emptyTupleSet
70union :: Relation -> Relation -> Either RelationalError Relation
68union :: Relation -> Relation -> Either RelationalError Relation
71union (Relation attrs1 tupSet1) (Relation attrs2 tupSet2) =
69union (Relation attrs1 tupSet1) (Relation attrs2 tupSet2) =
72 if not (attrs1 == attrs2)
70 if not (attrs1 == attrs2)
73− then Left $ RelationalError 1 ("Attribute mismatch " ++ show attrs1 ++ show attrs2)
71+ then Left $ AttributeNameMismatchError (show attrs1 ++ show attrs2)
75 Right $ Relation attrs1 newtuples
73 Right $ Relation attrs1 newtuples
@@ -79,7 +77,7 @@ union (Relation attrs1 tupSet1) (Relation attrs2 tupSet2) =
79project :: S.Set AttributeName -> Relation -> Either RelationalError Relation
77project :: S.Set AttributeName -> Relation -> Either RelationalError Relation
80project projectionAttrNames rel@(Relation oldattrs rtuples) =
78project projectionAttrNames rel@(Relation oldattrs rtuples) =
81 if not $ attributeNamesContained projectionAttrNames (attributeNames rel)
79 if not $ attributeNamesContained projectionAttrNames (attributeNames rel)
82− then Left $ RelationalError 1 "Attributes mismatch"
80+ then Left $ AttributeNameMismatchError ""
84 relFold folder (Right $ Relation newAttrs HS.empty) rel
82 relFold folder (Right $ Relation newAttrs HS.empty) rel
@@ -98,9 +96,9 @@ tupleProject projectAttrs tupleIn@(RelationTuple tupleInMap) = RelationTuple $ M
98rename :: AttributeName -> AttributeName -> Relation -> Either RelationalError Relation
96rename :: AttributeName -> AttributeName -> Relation -> Either RelationalError Relation
99rename oldAttrName newAttrName rel@(Relation oldAttrs oldTupSet) =
97rename oldAttrName newAttrName rel@(Relation oldAttrs oldTupSet) =
100 if not attributeValid
98 if not attributeValid
101− then Left $ RelationalError 1 "No such attribute"
99+ then Left $ AttributeNameMismatchError ""
102 else if newAttributeInUse
100 else if newAttributeInUse
103− then Left $ RelationalError 1 ("Attribute \"" ++ newAttrName ++ "\" already in use.")
101+ then Left $ AttributeNameInUseError newAttrName
105 mkRelation newAttrs newTupSet
103 mkRelation newAttrs newTupSet
@@ -194,7 +192,7 @@ tupleUngroup relvalAttrName newAttrs tuple@(RelationTuple tupMap) = case (tupMap
195 unsafeRelValFromAtom :: Atom -> Relation
193 unsafeRelValFromAtom :: Atom -> Relation
196 unsafeRelValFromAtom (RelationAtom rel) = rel
194 unsafeRelValFromAtom (RelationAtom rel) = rel
197− _ -> Left $ RelationalError 1 "Attribute is not relation-valued."
195+ _ -> Left $ AttributeIsNotRelationValuedError relvalAttrName
199--this is a hack needed because the relation attributes are untyped so we must dig into the relval to get the attribute names
197--this is a hack needed because the relation attributes are untyped so we must dig into the relval to get the attribute names
200attributesForRelval :: AttributeName -> Relation -> Attributes
198attributesForRelval :: AttributeName -> Relation -> Attributes