~ migrating RelationDesc towards RDB.Relation
authorEric Prud'hommeaux <eric@w3.org>
Fri, 15 Oct 2010 11:23:10 -0400
changeset 233 ebace24ecbc8
parent 232 bb4269312c48
child 234 84e78c96a219
~ migrating RelationDesc towards RDB.Relation
src/main/scala/SQL.scala
src/main/scala/SparqlToSql.scala
src/test/scala/SQLTest.scala
--- a/src/main/scala/SQL.scala	Fri Oct 15 10:43:09 2010 -0400
+++ b/src/main/scala/SQL.scala	Fri Oct 15 11:23:10 2010 -0400
@@ -265,7 +265,7 @@
     DatabaseDesc(rs.map{r => (r.name -> r)}.toMap)
 }
 // case class Relation (name:RDB.RelName, header:RDB.Header, body:List[RDB.Tuple], candidates:List[RDB.CandidateKey], pk:Option[RDB.CandidateKey], fks:RDB.ForeignKeys)
-case class RelationDesc(name:RDB.RelName, attributes:Map[RDB.AttrName, ValueDescription], body:List[RDB.Tuple], candidates:List[RDB.CandidateKey], primarykey:Option[RDB.AttrName])
+case class RelationDesc(name:RDB.RelName, attributes:Map[RDB.AttrName, ValueDescription], body:List[RDB.Tuple], candidates:List[RDB.CandidateKey], pk:Option[RDB.AttrName])
 sealed abstract class FieldDescOrKeyDeclaration
 case class FieldDesc(attr:RDB.AttrName, value:Value, pkness:Boolean) extends FieldDescOrKeyDeclaration
 sealed abstract class KeyDeclaration extends FieldDescOrKeyDeclaration
@@ -296,25 +296,27 @@
     case "CREATE"~"TABLE"~relation~"("~reldesc~")" => {
       val pk0:Option[RDB.AttrName] = None
       val attrs0 = Map[RDB.AttrName, ValueDescription]()
+      val candidates0 = List[RDB.CandidateKey]()
       val fks0 = Map[RDB.AttrName, ForeignKey]()
       /* <pk>: (most recently parsed) PRIMARY KEY
        * <attrs>: map of attribute to type (e.g. INTEGER)
        * <fks>: map holding FOREIGN KEY relation REFERENCES attr
        */
-      val (pk, attrs, fks) =
-	reldesc.foldLeft((pk0, attrs0, fks0))((p, rd) => {
-	  val (pkopt, attrs, fks) = p
+      val (pk, attrs, candidates, fks) =
+	reldesc.foldLeft((pk0, attrs0, candidates0, fks0))((p, rd) => {
+	  val (pkopt, attrs, candidates, fks) = p
 	  rd match {
 	    case FieldDesc(attr, value, pkness) => {
-	      val pkNew =
-		if (pkness) Some(attr)
-		else pkopt
-	      (pkNew, attrs + (attr -> value), fks)
+	      val (pkNew, candNew) =
+		if (pkness) (Some(attr), candidates ++ List(RDB.CandidateKey(attr.n)))
+		else (pkopt, candidates)
+	      (pkNew, attrs + (attr -> value), candNew, fks)
 	    }
 	    case PrimaryKeyDeclaration(attr) =>
-	      (Some(attr), attrs, fks)
+	      // @@ why doesn't [[ candidates + RDB.CandidateKey(attr.n) ]] work?
+	      (Some(attr), attrs, candidates ++ List(RDB.CandidateKey(attr.n)), fks)
 	    case ForeignKeyDeclaration(fk, rel, pk) =>
-	      (pkopt, attrs, fks + (fk -> ForeignKey(rel, pk)))
+	      (pkopt, attrs, candidates, fks + (fk -> ForeignKey(rel, pk)))
 	  }
 	})
       /* Change data type of foreign key attributes to ForeignKey.
@@ -325,7 +327,7 @@
 	if (fks.contains(attr))	(attr -> fks(attr))
 	else (attr -> value)
       })
-      val rd = RelationDesc(relation, attrs2, List(), List(), pk)
+      val rd = RelationDesc(relation, attrs2, List(), candidates, pk)
       (relation -> rd)
     }
   }
--- a/src/main/scala/SparqlToSql.scala	Fri Oct 15 10:43:09 2010 -0400
+++ b/src/main/scala/SparqlToSql.scala	Fri Oct 15 11:23:10 2010 -0400
@@ -287,7 +287,7 @@
     /**
      * Bind optAttr to an SQL generator like RDFNoder(Employee,FullBinding(R_emp.empid))
      */
-    val binding = reldesc.primarykey match {
+    val binding = reldesc.pk match {
       /** <pre>varConstraint(R_emp, Some(empid), VarAssignable(?emp), Employee) -&gt; RDFNoder(Employee,FullBinding(R_emp.empid))</pre> */
       case Some(sql.RDB.AttrName(constrainMe.attribute.n)) => RDFNoder(rel, boundTo)
       case _ => {
@@ -390,11 +390,11 @@
 	val state_postSubj = s match {
 	  case sparql.TermUri(u) =>
 	    /** additional constraint, e.g. R_empid18.empid=18. */
-	    uriConstraint(stateP, sql.RelVarAttr(relvar, db.relationdescs(rel).primarykey.get), parseObjectURI(u))
+	    uriConstraint(stateP, sql.RelVarAttr(relvar, db.relationdescs(rel).pk.get), parseObjectURI(u))
 	  case sparql.TermVar(v) =>
 	    /** assignable binding for novel vars, new constraint for previously bound vars. */
 	    try {
-	      varConstraint(stateP, relvar, db.relationdescs(rel).primarykey, sparql.VarAssignable(v), db, rel)
+	      varConstraint(stateP, relvar, db.relationdescs(rel).pk, sparql.VarAssignable(v), db, rel)
 	    } catch {
 	      case e:java.util.NoSuchElementException =>
 		/** Tell user that the relation.attribute encoded in the subject was not found in the database description. */
@@ -403,7 +403,7 @@
 	  case sparql.TermBNode(b) =>
 	    /** assignable binding for novel bnodes, new constraint for previously bound bnodes. */
 	    try {
-	      varConstraint(stateP, relvar, db.relationdescs(rel).primarykey, sparql.BNodeAssignable(b), db, rel)
+	      varConstraint(stateP, relvar, db.relationdescs(rel).pk, sparql.BNodeAssignable(b), db, rel)
 	    } catch {
 	      case e:java.util.NoSuchElementException =>
 		throw new Exception("error processing { " + s + " " + p + " " + o + " } :db.relationdescs(" + rel + ") not found in " + db)
--- a/src/test/scala/SQLTest.scala	Fri Oct 15 10:43:09 2010 -0400
+++ b/src/test/scala/SQLTest.scala	Fri Oct 15 11:23:10 2010 -0400
@@ -435,7 +435,7 @@
       RelationDesc("Sex_DE",
 		   Map(RDB.AttrName("ID") -> Value(Datatype.INTEGER)),
 		   List(),
-		   List(),
+		   List(RDB.CandidateKey("ID")),
 		   Option(RDB.AttrName("ID"))))
       assert(expected === (a.parseAll(a.ddl, e).get))
   }
@@ -451,7 +451,7 @@
 		   Map(RDB.AttrName("ID") -> Value(Datatype.INTEGER),
 		       RDB.AttrName("EnterpriseEntryID") -> Value(Datatype.INTEGER)),
 		   List(),
-		   List(),
+		   List(RDB.CandidateKey("ID")),
 		   Option(RDB.AttrName("ID"))))
 
     assert(expected === (a.parseAll(a.ddl, e).get))
@@ -467,7 +467,7 @@
 		   Map(RDB.AttrName("ID") -> Value(Datatype.INTEGER),
 		       RDB.AttrName("EnterpriseEntryID") -> Value(Datatype.INTEGER)),
 		   List(),
-		   List(),
+		   List(RDB.CandidateKey("ID")),
 		   Option(RDB.AttrName("ID"))))
 
     assert(expected === (a.parseAll(a.ddl, e).get))
@@ -476,7 +476,7 @@
   test("foreign key") {
     val a = Sql()
     val e = """
-    CREATE TABLE Person (ID INT PRIMARY KEY, MiddleName STRING, DateOfBirth DATE, SexDE INT, PRIMARY KEY (ID), FOREIGN KEY (SexDE) REFERENCES Sex_DE(ID));
+    CREATE TABLE Person (ID INT PRIMARY KEY, MiddleName STRING, DateOfBirth DATE, SexDE INT, FOREIGN KEY (SexDE) REFERENCES Sex_DE(ID));
     CREATE TABLE Sex_DE (ID INT PRIMARY KEY, EntryName STRING)
     """
     val expected:DatabaseDesc = DatabaseDesc(
@@ -486,13 +486,13 @@
 		       RDB.AttrName("DateOfBirth") -> Value(Datatype.DATE),
 		       RDB.AttrName("SexDE") -> ForeignKey(RDB.RelName("Sex_DE"), RDB.AttrName("ID"))),
 		   List(),
-		   List(),
+		   List(RDB.CandidateKey("ID")),
 		   Option(RDB.AttrName("ID"))),
       RelationDesc("Sex_DE",
 		   Map(RDB.AttrName("ID") -> Value(Datatype.INTEGER),
 		       RDB.AttrName("EntryName") -> Value(Datatype.STRING)),
 		   List(),
-		   List(),
+		   List(RDB.CandidateKey("ID")),
 		   Option(RDB.AttrName("ID")))
     )
     assert(expected === (a.parseAll(a.ddl, e).get))
@@ -501,10 +501,10 @@
   test("create db") {
     val a = Sql()
     val e = """
-CREATE TABLE Person (ID INT PRIMARY KEY, MiddleName STRING, DateOfBirth DATE, SexDE INT, PRIMARY KEY (ID), FOREIGN KEY (SexDE) REFERENCES Sex_DE(ID));
+CREATE TABLE Person (ID INT PRIMARY KEY, MiddleName STRING, DateOfBirth DATE, SexDE INT, FOREIGN KEY (SexDE) REFERENCES Sex_DE(ID));
 CREATE TABLE Sex_DE (ID INT PRIMARY KEY, EntryName STRING);
-CREATE TABLE Item_Medication (ID INT PRIMARY KEY, PRIMARY KEY (ID), PatientID INT, FOREIGN KEY (PatientID) REFERENCES Person(ID), PerformedDTTM DATE, EntryName STRING);
-CREATE TABLE Medication (ID INT PRIMARY KEY, PRIMARY KEY (ID), ItemID INT, FOREIGN KEY (ItemID) REFERENCES Item_Medication(ID), MedDictDE INT, FOREIGN KEY (MedDictDE) REFERENCES Medication_DE(ID));
+CREATE TABLE Item_Medication (ID INT PRIMARY KEY, PatientID INT, FOREIGN KEY (PatientID) REFERENCES Person(ID), PerformedDTTM DATE, EntryName STRING);
+CREATE TABLE Medication (ID INT PRIMARY KEY, ItemID INT, FOREIGN KEY (ItemID) REFERENCES Item_Medication(ID), MedDictDE INT, FOREIGN KEY (MedDictDE) REFERENCES Medication_DE(ID));
 CREATE TABLE Medication_DE (ID INT PRIMARY KEY, NDC INT);
 CREATE TABLE NDCcodes (ID INT PRIMARY KEY, NDC INT, ingredient INT);
 """
@@ -515,13 +515,13 @@
 		     RDB.AttrName("DateOfBirth") -> Value(Datatype.DATE),
 		     RDB.AttrName("SexDE") -> ForeignKey(RDB.RelName("Sex_DE"), RDB.AttrName("ID"))),
 		 List(),
-		 List(), // RDB.CandidateKey("ID")
+		 List(RDB.CandidateKey("ID")),
 		 Option(RDB.AttrName("ID"))),
     RelationDesc("Sex_DE",
 		 Map(RDB.AttrName("ID") -> Value(Datatype.INTEGER),
 		     RDB.AttrName("EntryName") -> Value(Datatype.STRING)),
 		 List(),
-		 List(),
+		 List(RDB.CandidateKey("ID")),
 		 Option(RDB.AttrName("ID"))),
     RelationDesc("Item_Medication",
 		 Map(RDB.AttrName("ID") -> Value(Datatype.INTEGER),
@@ -529,27 +529,27 @@
 		     RDB.AttrName("PerformedDTTM") -> Value(Datatype.DATE),
 		     RDB.AttrName("EntryName") -> Value(Datatype.STRING)),
 		 List(),
-		 List(),
+		 List(RDB.CandidateKey("ID")),
 		 Option(RDB.AttrName("ID"))),
     RelationDesc("Medication",
 		 Map(RDB.AttrName("ID") -> Value(Datatype.INTEGER),
 		     RDB.AttrName("ItemID") -> ForeignKey(RDB.RelName("Item_Medication"),  RDB.AttrName("ID")),
 		     RDB.AttrName("MedDictDE") -> ForeignKey(RDB.RelName("Medication_DE"), RDB.AttrName("ID"))),
 		 List(),
-		 List(),
+		 List(RDB.CandidateKey("ID")),
 		 Option(RDB.AttrName("ID"))),
     RelationDesc("Medication_DE",
 		 Map(RDB.AttrName("ID") -> Value(Datatype.INTEGER),
 		     RDB.AttrName("NDC") -> Value(Datatype.INTEGER)),
 		 List(),
-		 List(),
+		 List(RDB.CandidateKey("ID")),
 		 Option(RDB.AttrName("ID"))),
     RelationDesc("NDCcodes",
 		 Map(RDB.AttrName("ID") -> Value(Datatype.INTEGER),
 		     RDB.AttrName("NDC") -> Value(Datatype.INTEGER),
 		     RDB.AttrName("ingredient") -> Value(Datatype.INTEGER)),
 		 List(),
-		 List(),
+		 List(RDB.CandidateKey("ID")),
 		 Option(RDB.AttrName("ID")))
   )
     assert(expected === (a.parseAll(a.ddl, e).get))