~ migrated rest of tests to use SQL/DDL
authorEric Prud'hommeaux <eric@w3.org>
Wed, 03 Nov 2010 09:59:49 -0400
changeset 256 86d60884a3e7
parent 255 9df103e37c4d
child 257 781efa593fc6
~ migrated rest of tests to use SQL/DDL
- 2 Employees test
directmapping/src/test/scala/DirectMappingTest.scala
sql/src/test/scala/SQLTest.scala
--- a/directmapping/src/test/scala/DirectMappingTest.scala	Tue Nov 02 18:19:39 2010 -0400
+++ b/directmapping/src/test/scala/DirectMappingTest.scala	Wed Nov 03 09:59:49 2010 -0400
@@ -168,40 +168,19 @@
 
   test("1 People 1 Addresses 1 Offices") {
 
-    val addrs = Relation("Addresses",
-			 Header("ID" -> Datatype.INTEGER,
-				"city" -> Datatype.STRING,
-				"state" -> Datatype.STRING),
-			 List(Tuple("ID" -> LexicalValue("18"),
-				    "city" -> LexicalValue("Cambridge"),
-				    "state" -> LexicalValue("MA"))),
-			 List(CandidateKey("ID")),
-			 Some(CandidateKey("ID")),
-			 ForeignKeys())
-
-    val people = Relation("People",
-			  Header("ID" -> Datatype.INTEGER,
-				 "fname" -> Datatype.STRING,
-				 "addr" -> Datatype.INTEGER),
-			  List(Tuple("ID" -> LexicalValue("7"),
-				     "fname" -> LexicalValue("Bob"),
-				     "addr" -> LexicalValue("18"))),
-			  List(CandidateKey("ID")),
-			  Some(CandidateKey("ID")),
-			  ForeignKeys(List("addr") -> Target("Addresses", CandidateKey("ID"))))
-
-    val offices = Relation("Offices",
-			   Header("ID" -> Datatype.INTEGER,
-				  "building" -> Datatype.INTEGER,
-				  "ofcNumber" -> Datatype.STRING),
-			   List(Tuple("ID" -> LexicalValue("18"),
-				      "building" -> LexicalValue("32"),
-				      "ofcNumber" -> LexicalValue("G528"))),
-			   List(CandidateKey("ID")),
-			   Some(CandidateKey("ID")),
-			   ForeignKeys(List("ID") -> Target("Addresses", CandidateKey("ID"))))
-
-    val db = Database(List(addrs, people, offices))
+    val p = SqlParser()
+    val s = """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
+                     FOREIGN KEY (addr) REFERENCES Addresses(ID));
+INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
+CREATE TABLE Offices (ID INT PRIMARY KEY,
+                      building INT, ofcNumber STRING,
+                      FOREIGN KEY (ID) REFERENCES Addresses(ID));
+INSERT INTO Offices (ID, building, ofcNumber) VALUES (18, 32, "G528");
+"""
+    val db = p.parseAll(p.ddl, s).get
     val g = directDB(StemIRI("http://foo.example/DB"), db)
 
     val expected:Graph =
@@ -224,49 +203,24 @@
 
   test("1 People 1 Addresses 1 Offices 1 ExectutiveOffices") {
 
-    val addrs = Relation("Addresses",
-			 Header("ID" -> Datatype.INTEGER,
-				"city" -> Datatype.STRING,
-				"state" -> Datatype.STRING),
-			 List(Tuple("ID" -> LexicalValue("18"),
-				    "city" -> LexicalValue("Cambridge"),
-				    "state" -> LexicalValue("MA"))),
-			 List(CandidateKey("ID")),
-			 Some(CandidateKey("ID")),
-			 ForeignKeys())
+    val p = SqlParser()
+    val s = """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
+                     FOREIGN KEY (addr) REFERENCES Addresses(ID));
+INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
+CREATE TABLE Offices (ID INT PRIMARY KEY,
+                      building INT, ofcNumber STRING,
+                      FOREIGN KEY (ID) REFERENCES Addresses(ID));
+INSERT INTO Offices (ID, building, ofcNumber) VALUES (18, 32, "G528");
+CREATE TABLE ExecutiveOffices (ID INT PRIMARY KEY,
+                               desk STRING,
+                               FOREIGN KEY (ID) REFERENCES Offices(ID));
+INSERT INTO ExecutiveOffices (ID, desk) VALUES (18, "oak");
+"""
 
-    val people = Relation("People",
-			  Header("ID" -> Datatype.INTEGER,
-				 "fname" -> Datatype.STRING,
-				 "addr" -> Datatype.INTEGER),
-			  List(Tuple("ID" -> LexicalValue("7"),
-				     "fname" -> LexicalValue("Bob"),
-				     "addr" -> LexicalValue("18"))),
-			  List(CandidateKey("ID")),
-			  Some(CandidateKey("ID")),
-			  ForeignKeys(List("addr") -> Target("Addresses", CandidateKey("ID"))))
-
-    val offices = Relation("Offices",
-			   Header("ID" -> Datatype.INTEGER,
-				  "building" -> Datatype.INTEGER,
-				  "ofcNumber" -> Datatype.STRING),
-			   List(Tuple("ID" -> LexicalValue("18"),
-				      "building" -> LexicalValue("32"),
-				      "ofcNumber" -> LexicalValue("G528"))),
-			     List(CandidateKey("ID")),
-			     Some(CandidateKey("ID")),
-			     ForeignKeys(List("ID") -> Target("Addresses", CandidateKey("ID"))))
-
-    val execoffices = Relation("ExecutiveOffices",
-			       Header("ID" -> Datatype.INTEGER,
-				      "desk" -> Datatype.STRING),
-			       List(Tuple("ID" -> LexicalValue("18"),
-					  "desk" -> LexicalValue("oak"))),
-			       List(CandidateKey("ID")),
-			       Some(CandidateKey("ID")),
-			       ForeignKeys(List("ID") -> Target("Offices", CandidateKey("ID"))))
-
-    val db = Database(List(addrs, people, offices, execoffices))
+    val db = p.parseAll(p.ddl, s).get
     val g = directDB(StemIRI("http://foo.example/DB"), db)
 
     val expected:Graph =
@@ -314,35 +268,5 @@
     assert(goal === test)
   }
 
-
-  test("2 Employees") {
-    val employees = Relation("Employees",
-			     Header("ID" -> Datatype.INTEGER,
-				    "fname" -> Datatype.STRING,
-				    "boss" -> Datatype.INTEGER),
-			     List(Tuple("ID" -> LexicalValue("1"),
-					"fname" -> LexicalValue("Alice"),
-					"boss" -> ␀()),
-				  Tuple("ID" -> LexicalValue("2"),
-					"fname" -> LexicalValue("Bob"),
-					"boss" -> LexicalValue("1"))
-				),
-			     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)
-
-    val expected:Graph =
-      Set(
-	Triple(IRI("http://foo.example/DB/Employees/ID.1#_"),IRI("http://foo.example/DB/Employees#ID"),TypedLiteral("1",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/Employees/ID.1#_"),IRI("http://foo.example/DB/Employees#fname"),TypedLiteral("Alice",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/Employees/ID.2#_"),IRI("http://foo.example/DB/Employees#ID"),TypedLiteral("2",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/Employees/ID.2#_"),IRI("http://foo.example/DB/Employees#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/Employees/ID.2#_"),IRI("http://foo.example/DB/Employees#boss"),IRI("http://foo.example/DB/Employees/ID.1#_"))
-      )
-    assert (expected === g)
-  }
-
 }
 
--- a/sql/src/test/scala/SQLTest.scala	Tue Nov 02 18:19:39 2010 -0400
+++ b/sql/src/test/scala/SQLTest.scala	Wed Nov 03 09:59:49 2010 -0400
@@ -13,132 +13,6 @@
     rs.map(r => (r.name -> r)).toMap
   // implicit def string2attrName (n:String) = RDB.AttrName(n)
 
-  test("parse 2 People 1 Addresses 1 Department 2 Projects 1 Task") {
-    val p = SqlParser()
-    val s = """
-CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
-INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
-CREATE TABLE Department (ID INT PRIMARY KEY, name STRING, city STRING, manager INT,
-                         FOREIGN KEY (manager) REFERENCES People(ID),
-                         UNIQUE (name, city));
-INSERT INTO Department (ID, name, city, manager) VALUES (23, "accounting", "Cambridge", 8);
-CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
-                     FOREIGN KEY (addr) REFERENCES Addresses(ID),
-                     deptName STRING, deptCity STRING,
-                     FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
-INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (7, "Bob", 18, "accounting", "Cambridge");
-INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (8, "Sue", NULL, NULL, NULL);
-CREATE TABLE Projects (lead INT,
-                       FOREIGN KEY (lead) REFERENCES People(ID),
-                       name STRING, UNIQUE (lead, name), 
-                       deptName STRING, deptCity STRING,
-                       UNIQUE (name, deptName, deptCity),
-                       FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
-INSERT INTO Projects (lead, name, deptName, deptCity) VALUES (8, "pencil survey", "accounting", "Cambridge");
-INSERT INTO Projects (lead, name, deptName, deptCity) VALUES (8, "eraser survey", "accounting", "Cambridge");
-CREATE TABLE TaskAssignments (worker INT,
-                              FOREIGN KEY (worker) REFERENCES People(ID),
-                              project STRING, PRIMARY KEY (worker, project), 
-                              deptName STRING, deptCity STRING,
-                              FOREIGN KEY (worker) REFERENCES People(ID),
-                              FOREIGN KEY (project, deptName, deptCity) REFERENCES Projects(name, deptName, deptCity),
-                              FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
-INSERT INTO TaskAssignments (worker, project, deptName, deptCity) VALUES (7, "pencil survey", "accounting", "Cambridge");
-"""
-
-    val addrs = RDB.Relation(
-      "Addresses",
-      RDB.Header("ID" -> RDB.Datatype.INTEGER,
-		 "city" -> RDB.Datatype.STRING,
-		 "state" -> RDB.Datatype.STRING),
-      List(RDB.Tuple("ID" -> RDB.LexicalValue("18"),
-		     "city" -> RDB.LexicalValue("Cambridge"),
-		     "state" -> RDB.LexicalValue("MA"))),
-      List(RDB.CandidateKey("ID")),
-      Some(RDB.CandidateKey("ID")),
-      RDB.ForeignKeys())
-
-    val people = RDB.Relation(
-      "People",
-      RDB.Header("ID" -> RDB.Datatype.INTEGER,
-		 "fname" -> RDB.Datatype.STRING,
-		 "addr" -> RDB.Datatype.INTEGER,
-		 "deptName" -> RDB.Datatype.STRING,
-		 "deptCity" -> RDB.Datatype.STRING),
-      List(RDB.Tuple("ID" -> RDB.LexicalValue("7"),
-		     "fname" -> RDB.LexicalValue("Bob"),
-		     "addr" -> RDB.LexicalValue("18"),
-		     "deptName" -> RDB.LexicalValue("accounting"),
-		     "deptCity" -> RDB.LexicalValue("Cambridge")),
-	   RDB.Tuple("ID" -> RDB.LexicalValue("8"),
-		     "fname" -> RDB.LexicalValue("Sue"),
-		     "addr" -> RDB.␀(),
-		     "deptName" -> RDB.␀(),
-		     "deptCity" -> RDB.␀())),
-      List(RDB.CandidateKey("ID")),
-      Some(RDB.CandidateKey("ID")),
-      RDB.ForeignKeys(List("addr") -> RDB.Target("Addresses", RDB.CandidateKey("ID")),
-		      List("deptName", "deptCity") -> RDB.Target("Department", RDB.CandidateKey("name", "city"))))
-
-    val department = RDB.Relation(
-      "Department",
-      RDB.Header("ID" -> RDB.Datatype.INTEGER,
-		 "name" -> RDB.Datatype.STRING,
-		 "city" -> RDB.Datatype.STRING,
-		 "manager" -> RDB.Datatype.INTEGER),
-      List(RDB.Tuple("ID" -> RDB.LexicalValue("23"),
-		     "name" -> RDB.LexicalValue("accounting"),
-		     "city" -> RDB.LexicalValue("Cambridge"),
-		     "manager" -> RDB.LexicalValue("8"))),
-      List(RDB.CandidateKey("ID"),
-	   RDB.CandidateKey("name", "city")),
-      Some(RDB.CandidateKey("ID")),
-      RDB.ForeignKeys(List("manager") -> RDB.Target("People", RDB.CandidateKey("ID"))))
-
-    val projects = RDB.Relation(
-      "Projects",
-      RDB.Header("lead" -> RDB.Datatype.INTEGER,
-		 "name" -> RDB.Datatype.STRING,
-		 "deptName" -> RDB.Datatype.STRING,
-		 "deptCity" -> RDB.Datatype.STRING),
-      List(RDB.Tuple("lead" -> RDB.LexicalValue("8"),
-		     "name" -> RDB.LexicalValue("pencil survey"),
-		     "deptName" -> RDB.LexicalValue("accounting"),
-		     "deptCity" -> RDB.LexicalValue("Cambridge")),
-	   RDB.Tuple("lead" -> RDB.LexicalValue("8"),
-		     "name" -> RDB.LexicalValue("eraser survey"),
-		     "deptName" -> RDB.LexicalValue("accounting"),
-		     "deptCity" -> RDB.LexicalValue("Cambridge"))),
-      List(RDB.CandidateKey("lead", "name"),
-	   RDB.CandidateKey("name", "deptName", "deptCity")),
-      None,
-      /* List(List("name"), List("lead", "name"), List("name", "deptName", "deptCity")),
-			    List("name"), // !!! */
-      RDB.ForeignKeys(List("lead") -> RDB.Target("People", RDB.CandidateKey("ID")),
-		      List("deptName", "deptCity") -> RDB.Target("Department", RDB.CandidateKey("name", "city"))))
-
-    val tasks = RDB.Relation(
-      "TaskAssignments",
-      RDB.Header("worker" -> RDB.Datatype.INTEGER,
-		 "project" -> RDB.Datatype.STRING,
-		 "deptName" -> RDB.Datatype.STRING,
-		 "deptCity" -> RDB.Datatype.STRING),
-      List(RDB.Tuple("worker" -> RDB.LexicalValue("7"),
-		     "project" -> RDB.LexicalValue("pencil survey"),
-		     "deptName" -> RDB.LexicalValue("accounting"),
-		     "deptCity" -> RDB.LexicalValue("Cambridge"))),
-      List(RDB.CandidateKey("worker", "project")),
-      Some(RDB.CandidateKey("worker", "project")),
-      RDB.ForeignKeys(List("worker") -> RDB.Target("People", RDB.CandidateKey("ID")),
-		      List("project", "deptName", "deptCity") -> RDB.Target("Projects", RDB.CandidateKey("name", "deptName", "deptCity")),
-		      List("deptName", "deptCity") -> RDB.Target("Department", RDB.CandidateKey("name", "city"))))
-    val db = RDB.Database(List(addrs, people, department, projects, tasks))
-
-    val expected = RDB.Database(List(addrs, people, department, projects, tasks))
-    assert(expected === (p.parseAll(p.ddl, s).get))
-  }
-
-
   test("parse ANDexpression") {
     // AliasedResource(Relation(Name("Employee")),RelVar(Name("R_emp")))
     val a = SqlParser()
@@ -845,6 +719,255 @@
   }
 
 
+  test("parse 2 People 1 Addresses 1 Department 2 Projects 1 Task") {
+    val p = SqlParser()
+    val s = """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE Department (ID INT PRIMARY KEY, name STRING, city STRING, manager INT,
+                         FOREIGN KEY (manager) REFERENCES People(ID),
+                         UNIQUE (name, city));
+INSERT INTO Department (ID, name, city, manager) VALUES (23, "accounting", "Cambridge", 8);
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
+                     FOREIGN KEY (addr) REFERENCES Addresses(ID),
+                     deptName STRING, deptCity STRING,
+                     FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
+INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (7, "Bob", 18, "accounting", "Cambridge");
+INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (8, "Sue", NULL, NULL, NULL);
+CREATE TABLE Projects (lead INT,
+                       FOREIGN KEY (lead) REFERENCES People(ID),
+                       name STRING, UNIQUE (lead, name), 
+                       deptName STRING, deptCity STRING,
+                       UNIQUE (name, deptName, deptCity),
+                       FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
+INSERT INTO Projects (lead, name, deptName, deptCity) VALUES (8, "pencil survey", "accounting", "Cambridge");
+INSERT INTO Projects (lead, name, deptName, deptCity) VALUES (8, "eraser survey", "accounting", "Cambridge");
+CREATE TABLE TaskAssignments (worker INT,
+                              FOREIGN KEY (worker) REFERENCES People(ID),
+                              project STRING, PRIMARY KEY (worker, project), 
+                              deptName STRING, deptCity STRING,
+                              FOREIGN KEY (worker) REFERENCES People(ID),
+                              FOREIGN KEY (project, deptName, deptCity) REFERENCES Projects(name, deptName, deptCity),
+                              FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
+INSERT INTO TaskAssignments (worker, project, deptName, deptCity) VALUES (7, "pencil survey", "accounting", "Cambridge");
+"""
+
+    val addrs = RDB.Relation(
+      "Addresses",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "city" -> RDB.Datatype.STRING,
+		 "state" -> RDB.Datatype.STRING),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("18"),
+		     "city" -> RDB.LexicalValue("Cambridge"),
+		     "state" -> RDB.LexicalValue("MA"))),
+      List(RDB.CandidateKey("ID")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys())
+
+    val people = RDB.Relation(
+      "People",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "fname" -> RDB.Datatype.STRING,
+		 "addr" -> RDB.Datatype.INTEGER,
+		 "deptName" -> RDB.Datatype.STRING,
+		 "deptCity" -> RDB.Datatype.STRING),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("7"),
+		     "fname" -> RDB.LexicalValue("Bob"),
+		     "addr" -> RDB.LexicalValue("18"),
+		     "deptName" -> RDB.LexicalValue("accounting"),
+		     "deptCity" -> RDB.LexicalValue("Cambridge")),
+	   RDB.Tuple("ID" -> RDB.LexicalValue("8"),
+		     "fname" -> RDB.LexicalValue("Sue"),
+		     "addr" -> RDB.␀(),
+		     "deptName" -> RDB.␀(),
+		     "deptCity" -> RDB.␀())),
+      List(RDB.CandidateKey("ID")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys(List("addr") -> RDB.Target("Addresses", RDB.CandidateKey("ID")),
+		      List("deptName", "deptCity") -> RDB.Target("Department", RDB.CandidateKey("name", "city"))))
+
+    val department = RDB.Relation(
+      "Department",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "name" -> RDB.Datatype.STRING,
+		 "city" -> RDB.Datatype.STRING,
+		 "manager" -> RDB.Datatype.INTEGER),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("23"),
+		     "name" -> RDB.LexicalValue("accounting"),
+		     "city" -> RDB.LexicalValue("Cambridge"),
+		     "manager" -> RDB.LexicalValue("8"))),
+      List(RDB.CandidateKey("ID"),
+	   RDB.CandidateKey("name", "city")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys(List("manager") -> RDB.Target("People", RDB.CandidateKey("ID"))))
+
+    val projects = RDB.Relation(
+      "Projects",
+      RDB.Header("lead" -> RDB.Datatype.INTEGER,
+		 "name" -> RDB.Datatype.STRING,
+		 "deptName" -> RDB.Datatype.STRING,
+		 "deptCity" -> RDB.Datatype.STRING),
+      List(RDB.Tuple("lead" -> RDB.LexicalValue("8"),
+		     "name" -> RDB.LexicalValue("pencil survey"),
+		     "deptName" -> RDB.LexicalValue("accounting"),
+		     "deptCity" -> RDB.LexicalValue("Cambridge")),
+	   RDB.Tuple("lead" -> RDB.LexicalValue("8"),
+		     "name" -> RDB.LexicalValue("eraser survey"),
+		     "deptName" -> RDB.LexicalValue("accounting"),
+		     "deptCity" -> RDB.LexicalValue("Cambridge"))),
+      List(RDB.CandidateKey("lead", "name"),
+	   RDB.CandidateKey("name", "deptName", "deptCity")),
+      None,
+      /* List(List("name"), List("lead", "name"), List("name", "deptName", "deptCity")),
+			    List("name"), // !!! */
+      RDB.ForeignKeys(List("lead") -> RDB.Target("People", RDB.CandidateKey("ID")),
+		      List("deptName", "deptCity") -> RDB.Target("Department", RDB.CandidateKey("name", "city"))))
+
+    val tasks = RDB.Relation(
+      "TaskAssignments",
+      RDB.Header("worker" -> RDB.Datatype.INTEGER,
+		 "project" -> RDB.Datatype.STRING,
+		 "deptName" -> RDB.Datatype.STRING,
+		 "deptCity" -> RDB.Datatype.STRING),
+      List(RDB.Tuple("worker" -> RDB.LexicalValue("7"),
+		     "project" -> RDB.LexicalValue("pencil survey"),
+		     "deptName" -> RDB.LexicalValue("accounting"),
+		     "deptCity" -> RDB.LexicalValue("Cambridge"))),
+      List(RDB.CandidateKey("worker", "project")),
+      Some(RDB.CandidateKey("worker", "project")),
+      RDB.ForeignKeys(List("worker") -> RDB.Target("People", RDB.CandidateKey("ID")),
+		      List("project", "deptName", "deptCity") -> RDB.Target("Projects", RDB.CandidateKey("name", "deptName", "deptCity")),
+		      List("deptName", "deptCity") -> RDB.Target("Department", RDB.CandidateKey("name", "city"))))
+    val db = RDB.Database(List(addrs, people, department, projects, tasks))
+
+    val expected = RDB.Database(List(addrs, people, department, projects, tasks))
+    assert(expected === (p.parseAll(p.ddl, s).get))
+  }
+
+
+  test("parse 1 People 1 Addresses 1 Offices") {
+    val p = SqlParser()
+    val s = """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
+                     FOREIGN KEY (addr) REFERENCES Addresses(ID));
+INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
+CREATE TABLE Offices (ID INT PRIMARY KEY,
+                      building INT, ofcNumber STRING,
+                      FOREIGN KEY (ID) REFERENCES Addresses(ID));
+INSERT INTO Offices (ID, building, ofcNumber) VALUES (18, 32, "G528");
+"""
+
+    val addrs = RDB.Relation(
+      "Addresses",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "city" -> RDB.Datatype.STRING,
+		 "state" -> RDB.Datatype.STRING),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("18"),
+		     "city" -> RDB.LexicalValue("Cambridge"),
+		     "state" -> RDB.LexicalValue("MA"))),
+      List(RDB.CandidateKey("ID")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys())
+
+    val people = RDB.Relation(
+      "People",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "fname" -> RDB.Datatype.STRING,
+		 "addr" -> RDB.Datatype.INTEGER),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("7"),
+		     "fname" -> RDB.LexicalValue("Bob"),
+		     "addr" -> RDB.LexicalValue("18"))),
+      List(RDB.CandidateKey("ID")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys(List("addr") -> RDB.Target("Addresses", RDB.CandidateKey("ID"))))
+
+    val offices = RDB.Relation(
+      "Offices",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "building" -> RDB.Datatype.INTEGER,
+		 "ofcNumber" -> RDB.Datatype.STRING),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("18"),
+		     "building" -> RDB.LexicalValue("32"),
+		     "ofcNumber" -> RDB.LexicalValue("G528"))),
+      List(RDB.CandidateKey("ID")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys(List("ID") -> RDB.Target("Addresses", RDB.CandidateKey("ID"))))
+
+    val expected = RDB.Database(List(addrs, people, offices))
+    assert(expected === (p.parseAll(p.ddl, s).get))
+  }
+
+
+  test("parse 1 People 1 Addresses 1 Offices 1 ExectutiveOffices") {
+    val p = SqlParser()
+    val s = """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
+                     FOREIGN KEY (addr) REFERENCES Addresses(ID));
+INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
+CREATE TABLE Offices (ID INT PRIMARY KEY,
+                      building INT, ofcNumber STRING,
+                      FOREIGN KEY (ID) REFERENCES Addresses(ID));
+INSERT INTO Offices (ID, building, ofcNumber) VALUES (18, 32, "G528");
+CREATE TABLE ExecutiveOffices (ID INT PRIMARY KEY,
+                               desk STRING,
+                               FOREIGN KEY (ID) REFERENCES Offices(ID));
+INSERT INTO ExecutiveOffices (ID, desk) VALUES (18, "oak");
+"""
+
+    val addrs = RDB.Relation(
+      "Addresses",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "city" -> RDB.Datatype.STRING,
+		 "state" -> RDB.Datatype.STRING),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("18"),
+		     "city" -> RDB.LexicalValue("Cambridge"),
+		     "state" -> RDB.LexicalValue("MA"))),
+      List(RDB.CandidateKey("ID")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys())
+
+    val people = RDB.Relation(
+      "People",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "fname" -> RDB.Datatype.STRING,
+		 "addr" -> RDB.Datatype.INTEGER),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("7"),
+		     "fname" -> RDB.LexicalValue("Bob"),
+		     "addr" -> RDB.LexicalValue("18"))),
+      List(RDB.CandidateKey("ID")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys(List("addr") -> RDB.Target("Addresses", RDB.CandidateKey("ID"))))
+
+    val offices = RDB.Relation(
+      "Offices",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "building" -> RDB.Datatype.INTEGER,
+		 "ofcNumber" -> RDB.Datatype.STRING),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("18"),
+		     "building" -> RDB.LexicalValue("32"),
+		     "ofcNumber" -> RDB.LexicalValue("G528"))),
+      List(RDB.CandidateKey("ID")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys(List("ID") -> RDB.Target("Addresses", RDB.CandidateKey("ID"))))
+
+    val execoffices = RDB.Relation(
+      "ExecutiveOffices",
+      RDB.Header("ID" -> RDB.Datatype.INTEGER,
+		 "desk" -> RDB.Datatype.STRING),
+      List(RDB.Tuple("ID" -> RDB.LexicalValue("18"),
+		     "desk" -> RDB.LexicalValue("oak"))),
+      List(RDB.CandidateKey("ID")),
+      Some(RDB.CandidateKey("ID")),
+      RDB.ForeignKeys(List("ID") -> RDB.Target("Offices", RDB.CandidateKey("ID"))))
+    val expected = RDB.Database(List(addrs, people, offices, execoffices))
+    assert(expected === (p.parseAll(p.ddl, s).get))
+  }
+
+
   /**
    * junk that should be elsewhere
    */