~ made CandidateKey a case class
authorEric Prud'hommeaux <eric@w3.org>
Tue, 12 Oct 2010 14:01:46 -0400
changeset 36 15ef23dfd492
parent 35 527a7792e4b6
child 37 3e1521c837cb
~ made CandidateKey a case class
src/main/scala/Main.scala
src/test/scala/Test.scala
--- a/src/main/scala/Main.scala	Tue Oct 12 02:30:29 2010 -0400
+++ b/src/main/scala/Main.scala	Tue Oct 12 14:01:46 2010 -0400
@@ -20,7 +20,12 @@
     def apply (s:(String, SQLDatatype)*):Header =
       Header(s.map{p => (AttrName(p._1), p._2)}.toMap)
   }
-  type CandidateKey = List[AttrName]
+  case class CandidateKey (attrs:List[AttrName])
+  object CandidateKey {
+    def apply (l:(String)*):CandidateKey =
+      CandidateKey(l.map{s => AttrName(s)}.toList)
+  }
+  implicit def cc2list (cc:CandidateKey) = cc.attrs
 
   case class ForeignKeys (m:Map[List[AttrName], Target]) {
     def apply (l:List[AttrName]) = m(l)
@@ -32,7 +37,7 @@
       ForeignKeys(s.map{p => (p._1.map{s => AttrName(s)}, p._2)}.toMap)
   }
 
-  case class Target (rel:RelName, attrs:CandidateKey)
+  case class Target (rel:RelName, key:CandidateKey)
 
   sealed abstract class SQLDatatype
   case class SQLInt () extends SQLDatatype
@@ -158,7 +163,7 @@
       if (db(rn).pk.isDefined && db(rn).fks.contains(db(rn).pk.get)) {
 	/** Table's primary key is a foreign key. */
 	val target = db(rn).fks(db(rn).pk.get)
-	ultimateReferent(target.rel, target.attrs, vs, db)
+	ultimateReferent(target.rel, target.key, vs, db)
       } else
 	m(rn)(k)(vs)
     }
@@ -187,7 +192,7 @@
     /** Check to see if r's primary key is a hierarchical key.
      * http://www.w3.org/2001/sw/rdb2rdf/directGraph/#rule3 */
     if (r.pk.isDefined && r.fks.contains(r.pk.get))
-      r.fks.keySet -- nullFKs - r.fks(r.pk.get).attrs
+      r.fks.keySet -- nullFKs - r.fks(r.pk.get).key
     else
       r.fks.keySet -- nullFKs
   }
@@ -203,7 +208,7 @@
     /** Check to see if r's primary key is a hierarchical key.
      * http://www.w3.org/2001/sw/rdb2rdf/directGraph/#rule3 */
     if (r.pk.isDefined && r.fks.contains(r.pk.get))
-      allAttrs -- unaryFKs -- nulllist ++ r.fks(r.pk.get).attrs
+      allAttrs -- unaryFKs -- nulllist ++ r.fks(r.pk.get).key
     else
       allAttrs -- unaryFKs -- nulllist
   }
@@ -277,7 +282,7 @@
     val p = predicatemap (u, r.name, as)
     val ls:List[LexicalValue] = t.lexvaluesNoNulls(as)
     val target = r.fks(as)
-    val o:Object = nodes(target.rel)(target.attrs)(ls)
+    val o:Object = nodes(target.rel)(target.key)(ls)
     Triple(s, p, o)
   }
 
--- a/src/test/scala/Test.scala	Tue Oct 12 02:30:29 2010 -0400
+++ b/src/test/scala/Test.scala	Tue Oct 12 14:01:46 2010 -0400
@@ -13,6 +13,8 @@
   implicit def string2relName (n:String) = RelName(n)
   implicit def string2attrName (n:String) = AttrName(n)
 
+
+
   test("2 People 1 Addresses") {
 
     val addrs = Relation("Addresses",
@@ -22,8 +24,8 @@
 			 Set(Tuple("ID" -> LexicalValue("18"),
 				   "city" -> LexicalValue("Cambridge"),
 				   "state" -> LexicalValue("MA"))),
-			 List(List("ID")),
-			 Some(List("ID")),
+			 List(CandidateKey("ID")),
+			 Some(CandidateKey("ID")),
 			 ForeignKeys())
 
     val people = Relation("People",
@@ -36,9 +38,9 @@
 			      Tuple("ID" -> LexicalValue("8"),
 				    "fname" -> LexicalValue("Sue"),
 				    "addr" -> ␀())),
-			  List(List("ID")),
-			  Some(List("ID")),
-			  ForeignKeys(List("addr") -> Target("Addresses", List("ID"))))
+			  List(CandidateKey("ID")),
+			  Some(CandidateKey("ID")),
+			  ForeignKeys(List("addr") -> Target("Addresses", CandidateKey("ID"))))
 
     val db = Database(List(addrs, people))
     val g = directDB(StemIRI("http://foo.example/DB"), db)
@@ -68,8 +70,8 @@
 			 Set(Tuple("ID" -> LexicalValue("18"),
 				   "city" -> LexicalValue("Cambridge"),
 				   "state" -> LexicalValue("MA"))),
-			 List(List("ID")),
-			 Some(List("ID")),
+			 List(CandidateKey("ID")),
+			 Some(CandidateKey("ID")),
 			 ForeignKeys())
 
     val people = Relation("People",
@@ -88,10 +90,10 @@
 				    "addr" -> ␀(),
 				    "deptName" -> ␀(),
 				    "deptCity" -> ␀())),
-			  List(List("ID")),
-			  Some(List("ID")),
-			  ForeignKeys(List("addr") -> Target("Addresses", List("ID")),
-				      List("deptName", "deptCity") -> Target("Department", List("name", "city"))))
+			  List(CandidateKey("ID")),
+			  Some(CandidateKey("ID")),
+			  ForeignKeys(List("addr") -> Target("Addresses", CandidateKey("ID")),
+				      List("deptName", "deptCity") -> Target("Department", CandidateKey("name", "city"))))
 
     val department = Relation("Department",
 			      Header("ID" -> SQLInt(),
@@ -102,9 +104,10 @@
 					"name" -> LexicalValue("accounting"),
 					"city" -> LexicalValue("Cambridge"),
 					"manager" -> LexicalValue("8"))),
-			      List(List("ID"), List("name", "city")),
-			      Some(List("ID")),
-			      ForeignKeys(List("manager") -> Target("People", List("ID"))))
+			      List(CandidateKey("ID"),
+				   CandidateKey("name", "city")),
+			      Some(CandidateKey("ID")),
+			      ForeignKeys(List("manager") -> Target("People", CandidateKey("ID"))))
 
     val db = Database(List(addrs, people, department))
     val g = directDB(StemIRI("http://foo.example/DB"), db)
@@ -143,8 +146,8 @@
 			 Set(Tuple("ID" -> LexicalValue("18"),
 				   "city" -> LexicalValue("Cambridge"),
 				   "state" -> LexicalValue("MA"))),
-			 List(List("ID")),
-			 Some(List("ID")),
+			 List(CandidateKey("ID")),
+			 Some(CandidateKey("ID")),
 			 ForeignKeys())
 
     val people = Relation("People",
@@ -163,10 +166,10 @@
 				    "addr" -> ␀(),
 				    "deptName" -> ␀(),
 				    "deptCity" -> ␀())), // no data
-			  List(List("ID")),
-			  Some(List("ID")),
-			  ForeignKeys(List("addr") -> Target("Addresses", List("ID")),
-				      List("deptName", "deptCity") -> Target("Department", List("name", "city"))))
+			  List(CandidateKey("ID")),
+			  Some(CandidateKey("ID")),
+			  ForeignKeys(List("addr") -> Target("Addresses", CandidateKey("ID")),
+				      List("deptName", "deptCity") -> Target("Department", CandidateKey("name", "city"))))
 
     val department = Relation("Department",
 			      Header("ID" -> SQLInt(),
@@ -177,9 +180,10 @@
 					"name" -> LexicalValue("accounting"),
 					"city" -> LexicalValue("Cambridge"),
 					"manager" -> LexicalValue("8"))),
-			      List(List("ID"), List("name", "city")),
-			      Some(List("ID")),
-			      ForeignKeys(List("manager") -> Target("People", List("ID"))))
+			      List(CandidateKey("ID"),
+				   CandidateKey("name", "city")),
+			      Some(CandidateKey("ID")),
+			      ForeignKeys(List("manager") -> Target("People", CandidateKey("ID"))))
 
     val projects = Relation("Projects",
 			    Header("lead" -> SQLInt(),
@@ -194,12 +198,13 @@
 				      "name" -> LexicalValue("eraser survey"),
 				      "deptName" -> LexicalValue("accounting"),
 				      "deptCity" -> LexicalValue("Cambridge"))),
-			    List(List("lead", "name"), List("name", "deptName", "deptCity")),
+			    List(CandidateKey("lead", "name"),
+				 CandidateKey("name", "deptName", "deptCity")),
 			    None,
 			    /* List(List("name"), List("lead", "name"), List("name", "deptName", "deptCity")),
 			    List("name"), // !!! */
-			    ForeignKeys(List("lead") -> Target("People", List("ID")),
-					List("deptName", "deptCity") -> Target("Department", List("name", "city"))))
+			    ForeignKeys(List("lead") -> Target("People", CandidateKey("ID")),
+					List("deptName", "deptCity") -> Target("Department", CandidateKey("name", "city"))))
 
     val tasks = Relation("TaskAssignments",
 			 Header("worker" -> SQLInt(),
@@ -210,11 +215,11 @@
 				   "project" -> LexicalValue("pencil survey"),
 				   "deptName" -> LexicalValue("accounting"),
 				   "deptCity" -> LexicalValue("Cambridge"))),
-			 List(List("worker", "project")),
-			 Some(List("worker", "project")),
-			 ForeignKeys(List("worker") -> Target("People", List("ID")),
-				     List("project", "deptName", "deptCity") -> Target("Projects", List("name", "deptName", "deptCity")),
-				     List("deptName", "deptCity") -> Target("Department", List("name", "city"))))
+			 List(CandidateKey("worker", "project")),
+			 Some(CandidateKey("worker", "project")),
+			 ForeignKeys(List("worker") -> Target("People", CandidateKey("ID")),
+				     List("project", "deptName", "deptCity") -> Target("Projects", CandidateKey("name", "deptName", "deptCity")),
+				     List("deptName", "deptCity") -> Target("Department", CandidateKey("name", "city"))))
 
     val db = Database(List(addrs, people, department, projects, tasks))
     val g = directDB(StemIRI("http://foo.example/DB"), db)
@@ -272,8 +277,8 @@
 			 Set(Tuple("ID" -> LexicalValue("18"),
 				   "city" -> LexicalValue("Cambridge"),
 				   "state" -> LexicalValue("MA"))),
-			 List(List("ID")),
-			 Some(List("ID")),
+			 List(CandidateKey("ID")),
+			 Some(CandidateKey("ID")),
 			 ForeignKeys())
 
     val people = Relation("People",
@@ -283,9 +288,9 @@
 			  Set(Tuple("ID" -> LexicalValue("7"),
 				    "fname" -> LexicalValue("Bob"),
 				    "addr" -> LexicalValue("18"))),
-			  List(List("ID")),
-			  Some(List("ID")),
-			  ForeignKeys(List("addr") -> Target("Addresses", List("ID"))))
+			  List(CandidateKey("ID")),
+			  Some(CandidateKey("ID")),
+			  ForeignKeys(List("addr") -> Target("Addresses", CandidateKey("ID"))))
 
     val offices = Relation("Offices",
 			   Header("ID" -> SQLInt(),
@@ -294,9 +299,9 @@
 			   Set(Tuple("ID" -> LexicalValue("18"),
 				     "building" -> LexicalValue("32"),
 				     "ofcNumber" -> LexicalValue("G528"))),
-			   List(List("ID")),
-			   Some(List("ID")),
-			   ForeignKeys(List("ID") -> Target("Addresses", List("ID"))))
+			   List(CandidateKey("ID")),
+			   Some(CandidateKey("ID")),
+			   ForeignKeys(List("ID") -> Target("Addresses", CandidateKey("ID"))))
 
     val db = Database(List(addrs, people, offices))
     val g = directDB(StemIRI("http://foo.example/DB"), db)
@@ -328,8 +333,8 @@
 			 Set(Tuple("ID" -> LexicalValue("18"),
 				   "city" -> LexicalValue("Cambridge"),
 				   "state" -> LexicalValue("MA"))),
-			 List(List("ID")),
-			 Some(List("ID")),
+			 List(CandidateKey("ID")),
+			 Some(CandidateKey("ID")),
 			 ForeignKeys())
 
     val people = Relation("People",
@@ -339,9 +344,9 @@
 			  Set(Tuple("ID" -> LexicalValue("7"),
 				    "fname" -> LexicalValue("Bob"),
 				    "addr" -> LexicalValue("18"))),
-			  List(List("ID")),
-			  Some(List("ID")),
-			  ForeignKeys(List("addr") -> Target("Addresses", List("ID"))))
+			  List(CandidateKey("ID")),
+			  Some(CandidateKey("ID")),
+			  ForeignKeys(List("addr") -> Target("Addresses", CandidateKey("ID"))))
 
     val offices = Relation("Offices",
 			   Header("ID" -> SQLInt(),
@@ -350,18 +355,18 @@
 			   Set(Tuple("ID" -> LexicalValue("18"),
 				     "building" -> LexicalValue("32"),
 				     "ofcNumber" -> LexicalValue("G528"))),
-			     List(List("ID")),
-			     Some(List("ID")),
-			     ForeignKeys(List("ID") -> Target("Addresses", List("ID"))))
+			     List(CandidateKey("ID")),
+			     Some(CandidateKey("ID")),
+			     ForeignKeys(List("ID") -> Target("Addresses", CandidateKey("ID"))))
 
     val execoffices = Relation("ExecutiveOffices",
 			       Header("ID" -> SQLInt(),
 				      "desk" -> SQLString()),
 			       Set(Tuple("ID" -> LexicalValue("18"),
 					 "desk" -> LexicalValue("oak"))),
-			       List(List("ID")),
-			       Some(List("ID")),
-			       ForeignKeys(List("ID") -> Target("Offices", List("ID"))))
+			       List(CandidateKey("ID")),
+			       Some(CandidateKey("ID")),
+			       ForeignKeys(List("ID") -> Target("Offices", CandidateKey("ID"))))
 
     val db = Database(List(addrs, people, offices, execoffices))
     val g = directDB(StemIRI("http://foo.example/DB"), db)
@@ -389,8 +394,8 @@
 
   test("NodeMap") {
 
-    val ck1:CandidateKey = List("name", "ssn")
-    val ck2:CandidateKey = List("ID")
+    val ck1:CandidateKey = CandidateKey("name", "ssn")
+    val ck2:CandidateKey = CandidateKey("ID")
     val v11:List[CellValue] = List(LexicalValue("bob"), LexicalValue("123"))
     val v21:List[CellValue] = List(LexicalValue("alice"), LexicalValue("8"))
     val v12:List[CellValue] = List(LexicalValue("18"))
@@ -424,9 +429,9 @@
 				       "fname" -> LexicalValue("Bob"),
 				       "boss" -> LexicalValue("1"))
 			       ),
-			     List(List("ID")),
-			     Some(List("ID")),
-			     ForeignKeys(List("boss") -> Target("Employees", List("ID"))))
+			     List(CandidateKey("ID")),
+			     Some(CandidateKey("ID")),
+			     ForeignKeys(List("boss") -> Target("Employees", CandidateKey("ID"))))
     val db = Database(List(employees))
     val g = directDB(StemIRI("http://foo.example/DB"), db)