+ RDB.ForeignKeyKey
authorEric Prud'hommeaux <eric@w3.org>
Fri, 28 Jan 2011 10:18:43 -0500
changeset 308 b7c8a3157e6c
parent 307 6adb6a0a5243
child 309 f839901e8183
+ RDB.ForeignKeyKey
directmapping/src/main/scala/DirectMapping.scala
rdb/src/main/scala/RDB.scala
sql/src/main/scala/SQL.scala
--- 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] = (