--- a/directmapping/src/main/scala/DirectMapping.scala Thu Jan 27 15:48:57 2011 -0500
+++ b/directmapping/src/main/scala/DirectMapping.scala Fri Jan 28 10:18:43 2011 -0500
@@ -36,9 +36,9 @@
def ultimateReferent (rn:RelName, k:CandidateKey, vs:List[LexicalValue], db:Database) : Node = {
// Issue: What if fk is a rearrangement of the pk, per issue fk-pk-order?
db(rn).pk match {
- case Some(pk) if db(rn).fks contains (pk.attrs) => {
+ case Some(pk) if db(rn).fks contains(pk.attrs) => {
/** Table's primary key is a foreign key. */
- val target = db(rn).fks(pk.attrs)
+ val target = db(rn).fks(ForeignKeyKey(pk.attrs))
ultimateReferent(target.rel, target.key, vs, db)
}
case _ =>
@@ -60,16 +60,16 @@
* <http://www.w3.org/2001/sw/rdb2rdf/directGraph/>
*/
- def references (t:Tuple, r:Relation):Set[List[AttrName]] = {
- val allFKs:Set[List[AttrName]] = r.fks.keySet
+ def references (t:Tuple, r:Relation):Set[ForeignKeyKey] = {
+ val allFKs:Set[ForeignKeyKey] = r.fks.keySet
val nulllist:Set[AttrName] = t.nullAttributes(r.header)
- val nullFKs:Set[List[AttrName]] = allFKs filter { fk => (nulllist & fk.toSet) nonEmpty }
+ val nullFKs:Set[ForeignKeyKey] = allFKs filter { fk => (nulllist & fk.toSet) nonEmpty }
/** Check to see if r's primary key is a hierarchical key.
* http://www.w3.org/2001/sw/rdb2rdf/directGraph/#rule3 */
r.pk match {
case Some(pk) if r.fks contains (pk.attrs) =>
- r.fks.keySet -- nullFKs - r.fks(pk.attrs).key.attrs
+ r.fks.keySet -- nullFKs - ForeignKeyKey(r.fks.refdAttrs(ForeignKeyKey(pk.attrs)))
case _ =>
r.fks.keySet -- nullFKs
}
@@ -77,14 +77,14 @@
def scalars (t:Tuple, r:Relation):Set[AttrName] = {
val allAttrs:Set[AttrName] = r.header.keySet
- val allFKs:Set[List[AttrName]] = r.fks.keySet
- val unaryFKs:Set[AttrName] = allFKs filter { _.length == 1 } flatten
+ val allFKs:Set[ForeignKeyKey] = r.fks.keySet
+ val unaryFKs:Set[AttrName] = allFKs map { _.attrs } filter { _.length == 1 } flatten
/** Check to see if r's primary key is a hierarchical key.
* http://www.w3.org/2001/sw/rdb2rdf/directGraph/#rule3 */
r.pk match {
case Some(pk) if r.fks contains (pk.attrs) =>
- allAttrs -- unaryFKs ++ r.fks(pk.attrs).key.attrs
+ allAttrs -- unaryFKs ++ r.fks.refdAttrs(ForeignKeyKey(pk.attrs))
case _ =>
allAttrs -- unaryFKs
}
@@ -167,9 +167,9 @@
}
}
- def directN (s:Node, as:List[AttrName], r:Relation, t:Tuple, nodes:NodeMap) : Triple = {
- val p = predicatemap (r.name, as)
- val ls:List[LexicalValue] = t.lexvaluesNoNulls(as)
+ def directN (s:Node, as:ForeignKeyKey, r:Relation, t:Tuple, nodes:NodeMap) : Triple = {
+ val p = predicatemap (r.name, as.attrs)
+ val ls:List[LexicalValue] = t.lexvaluesNoNulls(as.attrs)
val target = r.fks(as)
if (!nodes.contains(target.rel))
error("No referent relation \"" + target.rel + "\" to match " + r.name + t)
--- a/rdb/src/main/scala/RDB.scala Thu Jan 27 15:48:57 2011 -0500
+++ b/rdb/src/main/scala/RDB.scala Fri Jan 28 10:18:43 2011 -0500
@@ -29,21 +29,28 @@
def apply (s:(String, Datatype)*):Header =
Header(s map { case (name, datatype) => (AttrName(name), datatype) } toMap)
}
- case class CandidateKey (attrs:List[AttrName])
+
+ type AttrList = List[AttrName]
+ case class ForeignKeyKey (attrs:AttrList) {
+ def toSet = attrs.toSet
+ }
+
+ case class CandidateKey (attrs:AttrList)
object CandidateKey {
def apply (l:String*):CandidateKey =
CandidateKey(l.toList map { AttrName(_) })
}
implicit def cc2list (cc:CandidateKey) = cc.attrs
- case class ForeignKeys (m:Map[List[AttrName], Target]) {
- def apply (l:List[AttrName]) = m(l)
+ case class ForeignKeys (m:Map[ForeignKeyKey, Target]) {
+ def apply (l:ForeignKeyKey) = m(l)
def keySet = m.keySet.toSet
- def contains (l:List[AttrName]) = m contains l
+ def contains (l:AttrList) = m contains ForeignKeyKey(l) // self-promoting cheat
+ def refdAttrs (kk:ForeignKeyKey) = m(kk).key.attrs
}
object ForeignKeys {
def apply (s:(List[String], Target)*):ForeignKeys =
- ForeignKeys(s map { case (keys, target) => (keys map { AttrName(_) }, target)} toMap)
+ ForeignKeys(s map { case (keys, target) => (ForeignKeyKey(keys map { AttrName(_) }), target)} toMap)
}
case class Target (rel:RelName, key:CandidateKey)
--- a/sql/src/main/scala/SQL.scala Thu Jan 27 15:48:57 2011 -0500
+++ b/sql/src/main/scala/SQL.scala Fri Jan 28 10:18:43 2011 -0500
@@ -167,7 +167,7 @@
sealed abstract class KeyDeclaration extends FieldDescOrKeyDeclaration
case class PrimaryKeyDeclaration(key:RDB.CandidateKey) extends KeyDeclaration
case class CandidateKeyDeclaration(key:RDB.CandidateKey) extends KeyDeclaration
-case class ForeignKeyDeclaration(fk:List[RDB.AttrName], rel:RDB.RelName, pk:RDB.CandidateKey) extends KeyDeclaration
+case class ForeignKeyDeclaration(fk:RDB.ForeignKeyKey, rel:RDB.RelName, pk:RDB.CandidateKey) extends KeyDeclaration
case class View(rel:RDB.RelName, defn:SelectORUnion) { // sibling of RDB.Relation
override def toString = "CREATE VIEW " + rel + " AS\n" + defn
}
@@ -212,7 +212,7 @@
val pk0:Option[RDB.CandidateKey] = None
val attrs0 = Map[RDB.AttrName, RDB.Datatype]()
val candidates0 = List[RDB.CandidateKey]()
- val fks0 = Map[List[RDB.AttrName], RDB.Target]()
+ val fks0 = Map[RDB.ForeignKeyKey, RDB.Target]()
/* <pk>: (most recently parsed) PRIMARY KEY
* <attrs>: map of attribute to type (e.g. INTEGER)
* <fks>: map holding FOREIGN KEY relation REFERENCES attr
@@ -261,7 +261,7 @@
| "UNIQUE" ~ "(" ~ rep1sep(attribute, ",") ~ ")" ^^
{ case "UNIQUE"~"("~attributes~")" => CandidateKeyDeclaration(RDB.CandidateKey(attributes)) }
| "FOREIGN" ~ "KEY" ~ "(" ~ rep1sep(attribute, ",") ~ ")" ~ "REFERENCES" ~ relation ~ "(" ~ rep1sep(attribute, ",") ~ ")" ^^
- { case "FOREIGN"~"KEY"~"("~fk~")"~"REFERENCES"~relation~"("~pk~")" => ForeignKeyDeclaration(fk, relation, RDB.CandidateKey(pk)) }
+ { case "FOREIGN"~"KEY"~"("~fk~")"~"REFERENCES"~relation~"("~pk~")" => ForeignKeyDeclaration(RDB.ForeignKeyKey(fk), relation, RDB.CandidateKey(pk)) }
)
def typpe:Parser[RDB.Datatype] = (