~ re-integrated branch: bnode-generator-for-no-primary-key
authorEric Prud'hommeaux <bertails@w3.org>
Wed, 06 Jan 2010 17:24:50 -0500
changeset 116 f4fa891ab93c
parent 115 5bc0f8043c31
child 117 11e5b3672a69
~ re-integrated branch: bnode-generator-for-no-primary-key
src/main/scala/RDB2RDFMain.scala
src/test/scala/RDB2RDFTest.scala
--- a/src/main/scala/RDB2RDFMain.scala	Tue Jan 05 13:39:13 2010 -0500
+++ b/src/main/scala/RDB2RDFMain.scala	Wed Jan 06 17:24:50 2010 -0500
@@ -86,11 +86,12 @@
    * type String -> RDFStringConstructor // adds ^^xsd:string
    * type primary key -> RDFNodeConstructor // prefixes with stemURL + relation + attribute  and adds #record
    * */
-  def varConstraint(state:R2RState, constrainMe:sql.RelAliasAttribute, v:sparql.Var, db:sql.DatabaseDesc, rel:sql.Relation):R2RState = {
+  def varConstraint(state:R2RState, alias:sql.RelAlias, optAttr:Option[sql.Attribute], v:sparql.Var, db:sql.DatabaseDesc, rel:sql.Relation):R2RState = {
     /* e.g.                                 Employee      _emp.id            
     **                                      Employee      _emp.lastName      
     **                                      Employee      _emp.manager       
     */
+    val constrainMe = if (optAttr.isDefined) sql.RelAliasAttribute(alias, optAttr.get) else sql.RelAliasAttribute(alias, sql.Attribute(sql.Name("_no_such_attribute")))
     val reldesc = db.relationdescs(rel)
     if (state.varmap.contains(v) && varToAttribute(state.varmap, v) != constrainMe) {
       /* The variable has already been bound to another attribute. */
@@ -142,7 +143,7 @@
     }
   }
 
-  def bindOnPredicate(db:sql.DatabaseDesc, stateP:R2RState, triple:sparql.TriplePattern, pk:PrimaryKey, enforceForeignKeys:Boolean):R2RState = {
+  def bindOnPredicate(db:sql.DatabaseDesc, stateP:R2RState, triple:sparql.TriplePattern, enforceForeignKeys:Boolean):R2RState = {
     val sparql.TriplePattern(s, p, o) = triple
     p match {
       case sparql.PVar(v) => error("variable predicates require tedious enumeration; too tedious for me.")
@@ -153,11 +154,10 @@
 	val relalias = relAliasFromS(s)
 
 	/* Attributes that come from the subject: */
-	val subjattr = sql.RelAliasAttribute(relalias, pk.attr)
 	val objattr = sql.RelAliasAttribute(relalias, attr)
 	val state_postSubj = s match {
-	  case sparql.SUri(u) => uriConstraint(stateP, subjattr, u, true)
-	  case sparql.SVar(v) => varConstraint(stateP, subjattr, v, db, rel)
+	  case sparql.SUri(u) => uriConstraint(stateP, sql.RelAliasAttribute(relalias, db.relationdescs(rel).primarykey.get), u, true)
+	  case sparql.SVar(v) => varConstraint(stateP, relalias, db.relationdescs(rel).primarykey, v, db, rel)
 	}
 	val state_subjJoin = R2RState(state_postSubj.joins + sql.InnerJoin(sql.AliasedResource(rel,relalias)), state_postSubj.varmap, state_postSubj.exprs)
 
@@ -186,7 +186,7 @@
 	o match {
 	  case sparql.OLit(l) => literalConstraint(state_fkeys, targetattr, l, dt)
 	  case sparql.OUri(u) => uriConstraint    (state_fkeys, targetattr, u, enforceForeignKeys)
-	  case sparql.OVar(v) => varConstraint    (state_fkeys, targetattr, v, db, targetrel)
+	  case sparql.OVar(v) => varConstraint    (state_fkeys, targetattr.relalias, Some(targetattr.attribute), v, db, targetrel)
 	}
       }
     }
@@ -232,7 +232,7 @@
       case StringMapper(relalias, disjoints) => relalias
       case DateMapper(relalias, disjoints) => relalias
       case RDFNoder(relation, relalias, disjoints) => relalias
-      case RDFBNoder(relation, relalias, disjoints) => relalias
+      case RDFBNoder(relation, relalias, disjoints) =>  relalias // error("BNode should not need relalias " + relalias)
     }
   }
 
@@ -242,7 +242,7 @@
       case StringMapper(relalias, disjoints) => disjoints
       case DateMapper(relalias, disjoints) => disjoints
       case RDFNoder(relation, relalias, disjoints) => disjoints
-      case RDFBNoder(relation, relalias, disjoints) => disjoints
+      case RDFBNoder(relation, relalias, disjoints) =>  disjoints // error("BNode should not need join constraints " + relalias)
     }
   }
 
@@ -299,10 +299,10 @@
     }
   }
 
-  def mapGraphPattern(db:sql.DatabaseDesc, state:R2RState, gp:sparql.GraphPattern, pk:PrimaryKey, enforceForeignKeys:Boolean):R2RState = {
+  def mapGraphPattern(db:sql.DatabaseDesc, state:R2RState, gp:sparql.GraphPattern, enforceForeignKeys:Boolean):R2RState = {
     gp match {
       case sparql.TableFilter(gp2:sparql.GraphPattern, expr:sparql.Expression) => {
-	val state2 = mapGraphPattern(db, state, gp2, pk, enforceForeignKeys)
+	val state2 = mapGraphPattern(db, state, gp2, enforceForeignKeys)
 
 	/* Add constraints for all the FILTERS */
 	val filterExprs:Set[sql.RelationalExpression] =
@@ -312,12 +312,16 @@
       }
       case sparql.TriplesBlock(triplepatterns) => {
 	/* Examine each triple, updating the compilation state. */
-	val state2 = triplepatterns.foldLeft(state)((incState,s) => bindOnPredicate(db, incState, s, pk, enforceForeignKeys))
-	val nullExprs = findVars(gp) map (vvar => sql.RelationalExpressionNotNull(sql.PrimaryExpressionAttr(varToAttribute(state2.varmap, vvar))))
+	val state2 = triplepatterns.foldLeft(state)((incState,s) => bindOnPredicate(db, incState, s, enforceForeignKeys))
+	val nullExprs = findVars(gp).foldLeft(Set[sql.Expression]())((s, vvar) => {
+	  state2.varmap(vvar) match {
+	    case RDFBNoder(relation, relalias, disjoints) => s
+	    case _ => s ++ Set(sql.RelationalExpressionNotNull(sql.PrimaryExpressionAttr(varToAttribute(state2.varmap, vvar))))
+	  }})
 	R2RState(state2.joins, state2.varmap, state2.exprs ++ nullExprs)
       }
       case sparql.TableConjunction(list) => {
-	list.foldLeft(state)((incState,s) => mapGraphPattern(db, incState, s, pk, enforceForeignKeys))
+	list.foldLeft(state)((incState,s) => mapGraphPattern(db, incState, s, enforceForeignKeys))
       }
       case sparql.TableDisjunction(list) => {
 	val unionAlias = sql.RelAlias(sql.Name("R_union" + state.joins.size))
@@ -330,7 +334,7 @@
 	val unionVars = list.foldLeft(Set[sparql.Var]())((mySet,disjoint) => mySet ++ findVars(disjoint)).toList
 	val (state2, disjoints, count) = list.foldLeft((state, initDisjoints, 0))((incPair,disjoint) => {
 	  val (outerState, outerDisjoints, no) = incPair
-	  val disjointState = mapGraphPattern(db, emptyState, disjoint, pk, enforceForeignKeys)
+	  val disjointState = mapGraphPattern(db, emptyState, disjoint, enforceForeignKeys)
 	  val disjointVars = findVars(disjoint)
 	  val disjointNo = sql.NamedAttribute(sql.PrimaryExpressionTyped(sql.Datatype.INTEGER,sql.Name("" + no)), sql.AttrAlias(sql.Name("_DISJOINT_")))
 
@@ -405,7 +409,7 @@
       	  Map[sparql.Var, SQL2RDFValueMapper](), 
       	  Set[sql.Expression]()
       	)
-      	val optionalState = mapGraphPattern(db, emptyState, gp, pk, enforceForeignKeys)
+      	val optionalState = mapGraphPattern(db, emptyState, gp, enforceForeignKeys)
       	val optionalVars = findVars(gp)
 	val disjointNo = sql.NamedAttribute(sql.PrimaryExpressionTyped(sql.Datatype.INTEGER,sql.Name("" + state.joins.size)), sql.AttrAlias(sql.Name("_DISJOINT_")))
 
@@ -478,7 +482,7 @@
     }
   }
 
-  def apply (db:sql.DatabaseDesc, sparquery:sparql.Select, stem:StemURI, pk:PrimaryKey, enforceForeignKeys:Boolean, concat:Boolean) : sql.Select = {
+  def apply (db:sql.DatabaseDesc, sparquery:sparql.Select, stem:StemURI, enforceForeignKeys:Boolean, concat:Boolean) : sql.Select = {
     val sparql.Select(attrs, triples) = sparquery
 
     /* Create an object to hold our compilation state. */
@@ -488,7 +492,7 @@
       Set[sql.Expression]()
     )
 
-    val r2rState = mapGraphPattern(db, initState, sparquery.gp, pk, enforceForeignKeys)
+    val r2rState = mapGraphPattern(db, initState, sparquery.gp, enforceForeignKeys)
 
     /* Select the attributes corresponding to the variables
      * in the SPARQL SELECT.  */
--- a/src/test/scala/RDB2RDFTest.scala	Tue Jan 05 13:39:13 2010 -0500
+++ b/src/test/scala/RDB2RDFTest.scala	Wed Jan 06 17:24:50 2010 -0500
@@ -29,7 +29,7 @@
 			 Attribute("manager") -> Value(Datatype.INTEGER),
 			 Attribute("address") -> Value(Datatype.INTEGER))),
 	Relation("Manage") -> 
-	RelationDesc(None,
+	RelationDesc(Option(Attribute("id")),
 		     Map(Attribute("manager") -> ForeignKey(Relation("Employee"), Attribute("id")), 
 			 Attribute("manages") -> ForeignKey(Relation("Employee"),  Attribute("id"))))
       ))
@@ -50,7 +50,7 @@
             INNER JOIN Employee AS R_id18
  WHERE R_id18.id=R_emp.manager AND R_id18.id=18 AND R_emp.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, false) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, false) === sqlSelect)
   }
 
   test("SELECT <x> { ?sf <p> <x>} (in-SQL Nodizer)") {
@@ -69,7 +69,7 @@
             INNER JOIN Employee AS R_id18
  WHERE R_id18.id=R_emp.manager AND R_id18.id=18 AND R_emp.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, true) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, true) === sqlSelect)
     true
   }
 
@@ -88,7 +88,7 @@
        FROM Employee AS R_emp
  WHERE R_emp.id IS NOT NULL AND R_emp.lastName IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, true) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, true) === sqlSelect)
     true
   }
 
@@ -107,7 +107,7 @@
             INNER JOIN Employee AS R_manager
  WHERE R_manager.id=R_id18.manager AND R_id18.id=18 AND R_manager.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, false) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, false) === sqlSelect)
     true
   }
 
@@ -129,7 +129,7 @@
             INNER JOIN Employee AS R_18
  WHERE R_18.id=R_emp.manager AND R_18.id=18 AND R_emp.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, false) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, false) === sqlSelect)
     true
   }
 
@@ -149,7 +149,7 @@
             INNER JOIN Employee AS R_emp2
  WHERE R_emp1.lastName=R_emp2.lastName AND R_emp1.id IS NOT NULL AND R_emp1.lastName IS NOT NULL AND R_emp2.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, false) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, false) === sqlSelect)
     true
   }
 
@@ -172,7 +172,7 @@
  AND R_emp.id IS NOT NULL
  AND R_manager.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, false) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, false) === sqlSelect)
   }
 
   test("transform tup1 no-enforce") {
@@ -191,7 +191,7 @@
  WHERE R_emp.manager=18 AND R_emp.lastName IS NOT NULL
  AND R_emp.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false, false) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), false, false) === sqlSelect)
   }
 
   test("transform tup1 enforce") {
@@ -211,7 +211,7 @@
  WHERE R_id18.id=R_emp.manager AND R_id18.id=18 AND R_emp.lastName IS NOT NULL
  AND R_emp.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, false) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, false) === sqlSelect)
   }
 
 
@@ -235,7 +235,7 @@
  AND R_emp.id IS NOT NULL
  AND R_manager.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, false) === sqlSelect)
+    assert(RDB2RDF(db, sparqlSelect, StemURI("http://hr.example/DB/"), true, false) === sqlSelect)
   }
 
   test("transform filter1") {
@@ -274,7 +274,7 @@
  AND R_manager.birthday IS NOT NULL
  AND R_grandManager.birthday IS NOT NULL
 """).get
-    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), true, false) === sqlSelect)
+    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), true, false) === sqlSelect)
   }
 
   test("transform disj1") {
@@ -315,7 +315,7 @@
        (R_union1._DISJOINT_!=0 OR R_who.id=R_union1.A_who) AND
        (R_union1._DISJOINT_!=1 OR R_who.id=R_union1.A_who)
 """).get
-    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false, false) === sqlSelect)
+    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), false, false) === sqlSelect)
   }
 
   test("transform assymDisj1") {
@@ -361,7 +361,7 @@
        R_union0.A_who IS NOT NULL AND
        R_union0.A_bday IS NOT NULL
 """).get
-    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false, false) === sqlSelect)
+    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), false, false) === sqlSelect)
   }
 
   test("transform assymDisj1 reversed") {
@@ -409,7 +409,7 @@
        R_who.id IS NOT NULL AND
        R_who.birthday IS NOT NULL
 """).get
-    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false, false) === sqlSelect)
+    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), false, false) === sqlSelect)
   }
 
   test("transform assymDisj1 interspersed") {
@@ -457,7 +457,7 @@
        R_who.id IS NOT NULL AND
        R_union1.A_bday IS NOT NULL
 """).get
-    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false, false) === sqlSelect)
+    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), false, false) === sqlSelect)
   }
 
   test("transform optJoin1") {
@@ -501,7 +501,7 @@
  WHERE R_emp.lastName IS NOT NULL
    AND R_emp.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false, false) === sqlSelect)
+    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), false, false) === sqlSelect)
   }
 
   test("transform nestOpt") {
@@ -542,7 +542,7 @@
              ) AS R_opt1 ON R_emp.id=R_opt1.A_emp
  WHERE R_emp.lastName IS NOT NULL AND R_emp.id IS NOT NULL
 """).get
-    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false, false) === sqlSelect)
+    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), false, false) === sqlSelect)
   }
 
   test("transform equivOpt1") {
@@ -597,7 +597,7 @@
    AND R_emp1.lastName IS NOT NULL
    AND R_opt1.A_birthday IS NOT NULL
 """).get
-    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false, false) === sqlSelect)
+    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), false, false) === sqlSelect)
   }