1module ProjectM36.Key where
3import ProjectM36.Relation
4import qualified Data.Set as S
8keys can be implemented using inclusion dependencies as well: the count of the projection of the keys' attributes must be equal to the count of the tuples- p. 120 Database in Depth
11:showexpr ((relation{tuple{}}:{a:=S}):{b:=count(@a)}){b}
17((relation{tuple{}}:{a:=S{S#}}):{b:=count(@a)}){b}
25-- | Create a uniqueness constraint for the attribute names and relational expression. Note that constraint can span multiple relation variables.
26inclusionDependencyForKey :: AttributeNames -> RelationalExpr -> InclusionDependency
27inclusionDependencyForKey attrNames relExpr = --InclusionDependency name (exprCount relExpr) (exprCount (projectedOnKeys relExpr))
28 InclusionDependency equalityExpr (ExistingRelation relationFalse)
30 projectedOnKeys = Project attrNames
31 exprAsSubRelation expr = Extend (AttributeExtendTupleExpr "a" (RelationAtomExpr expr)) (ExistingRelation relationTrue)
32 exprCount expr = projectionForCount (Extend (AttributeExtendTupleExpr "b" (FunctionAtomExpr "count" [AttributeAtomExpr "a"] () )) (exprAsSubRelation expr))
33 projectionForCount = Project (AttributeNames $ S.fromList ["b"])
34 equalityExpr = NotEquals (exprCount relExpr) (exprCount (projectedOnKeys relExpr))
36-- | Create a 'DatabaseContextExpr' which can be used to add a uniqueness constraint to attributes on one relation variable.
37databaseContextExprForUniqueKey :: RelVarName -> [AttributeName] -> DatabaseContextExpr
38databaseContextExprForUniqueKey rvName attrNames = AddInclusionDependency (rvName <> "_key") $ inclusionDependencyForKey (AttributeNames (S.fromList attrNames)) (RelationVariable rvName ())
40-- | Create a foreign key constraint from the first relation variable and attributes to the second.
41databaseContextExprForForeignKey :: IncDepName -> (RelVarName, [AttributeName]) -> (RelVarName, [AttributeName]) -> DatabaseContextExpr
42databaseContextExprForForeignKey fkName infoA infoB =
43 AddInclusionDependency fkName (inclusionDependencyForForeignKey infoA infoB)
45inclusionDependencyForForeignKey :: (RelVarName, [AttributeName]) -> (RelVarName, [AttributeName]) -> InclusionDependency
46inclusionDependencyForForeignKey (rvA, attrsA) (rvB, attrsB) =
48 renameIfNecessary attrsB attrsA (Project (attrsL attrsA)
49 (RelationVariable rvA ()))) (
50 Project (attrsL attrsB) (RelationVariable rvB ()))
52 attrsL = AttributeNames . S.fromList
53 renameIfNecessary attrsExpected attrsExisting expr = foldr folder expr (zip attrsExpected attrsExisting)
54 folder (attrExpected, attrExisting) expr = if attrExpected == attrExisting then
57 Rename attrExisting attrExpected expr
59-- if the constraint is a foreign key constraint, then return the relations and attributes involved - this only detects foreign keys created with `databaseContextExprForForeignKey`
60isForeignKeyFor :: InclusionDependency -> (RelVarName, [AttributeName]) -> (RelVarName, [AttributeName]) -> Bool
61isForeignKeyFor incDep infoA infoB = incDep == checkIncDep
63 checkIncDep = inclusionDependencyForForeignKey infoA infoB
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list