~ separating shared-variable conditional on disjoints
authorEric Prud'hommeaux <bertails@w3.org>
Thu, 31 Dec 2009 18:22:24 -0500
changeset 96 516608676c67
parent 95 79703c0f93a2
child 97 bcaa2b088460
~ separating shared-variable conditional on disjoints
src/main/scala/RDB2RDFMain.scala
src/test/scala/RDB2RDFTest.scala
--- a/src/main/scala/RDB2RDFMain.scala	Thu Dec 31 05:53:28 2009 -0500
+++ b/src/main/scala/RDB2RDFMain.scala	Thu Dec 31 18:22:24 2009 -0500
@@ -276,15 +276,16 @@
 	  Map[Var, SQL2RDFValueMapper](), 
 	  Set[Expression]()
 	)
-	val (state2, disjoints) = list.foldLeft((state, initDisjoints))((incPair,disjoint) => {
-	  val (outerState, outerDisjoints) = incPair
+	val (state2, disjoints, count) = list.foldLeft((state, initDisjoints, 0))((incPair,disjoint) => {
+	  val (outerState, outerDisjoints, no) = incPair
 	  val disjointState = mapGraphPattern(db, emptyState, disjoint, pk, enforeForeignKeys)
 	  val disjointVars = findVars(disjoint)
+	  val disjointNo = NamedAttribute(ConstInt("" + no), AttrAlias(Name("_DISJOINT_")))
 
-	  val attrlist:Set[NamedAttribute] = disjointVars.foldLeft(Set[NamedAttribute]())((attrs, v) => 
+	  val attrlist:Set[NamedAttribute] = disjointVars.foldLeft(Set(disjointNo))((attrs, v) => 
 	    attrs ++ Set(NamedAttribute(varToAttribute(disjointState.varmap, v), AttrAlias(Name("A_" + v.s)))))
 
-	  val sel = Select(
+	  val subselect = Select(
 	    AttributeList(attrlist),
 	    TableList(disjointState.joins),
 	    disjointState.exprs.size match {
@@ -306,16 +307,16 @@
 	    } else {
 	      /* This variable is new to the outer context. */
 	      val mapper:SQL2RDFValueMapper = disjointState.varmap(v) match {
-		case IntMapper(constrainMe)      => IntMapper(unionAliasAttr)
-		case StringMapper(constrainMe)   => StringMapper(unionAliasAttr)
-		case DateMapper(constrainMe)   => DateMapper(unionAliasAttr)
-		case RDFNoder(rel, constrainMe)  => RDFNoder(rel, unionAliasAttr)
-		case RDFBNoder(rel, constrainMe) => RDFBNoder(rel, unionAliasAttr)
+		case IntMapper(_)      => IntMapper(unionAliasAttr)
+		case StringMapper(_)   => StringMapper(unionAliasAttr)
+		case DateMapper(_)   => DateMapper(unionAliasAttr)
+		case RDFNoder(rel, _)  => RDFNoder(rel, unionAliasAttr)
+		case RDFBNoder(rel, _) => RDFBNoder(rel, unionAliasAttr)
 	      }
 	      R2RState(myState.joins, myState.varmap + (v -> mapper), myState.exprs)
 	    }
 	  })
-	  (outerState2, outerDisjoints ++ Set(sel))
+	  (outerState2, outerDisjoints ++ Set(subselect), no+1)
 	})
 	val union = Subselect(Union(disjoints))
 	R2RState(state.joins + AliasedResource(union,unionAlias), state2.varmap, state2.exprs)
--- a/src/test/scala/RDB2RDFTest.scala	Thu Dec 31 05:53:28 2009 -0500
+++ b/src/test/scala/RDB2RDFTest.scala	Thu Dec 31 18:22:24 2009 -0500
@@ -254,14 +254,14 @@
 SELECT R_union1.A_name AS A_name
   FROM Employee AS R_who
        INNER JOIN (
-         SELECT R_manager.lastName AS A_name, R_above.manages AS A_who
+         SELECT 0 AS _DISJOINT_, R_manager.lastName AS A_name, R_above.manages AS A_who
                 , R_above.id AS A_above, R_above.manager AS A_manager
                 FROM Manage AS R_above
                 INNER JOIN Employee AS R_manager
           WHERE R_above.manager=R_manager.id AND R_manager.lastName IS NOT NULL
                 AND R_above.manager IS NOT NULL AND R_above.id IS NOT NULL AND R_above.manages IS NOT NULL
        UNION
-         SELECT R_managed.lastName AS A_name, R_below.manager AS A_who
+         SELECT 1 AS _DISJOINT_, R_managed.lastName AS A_name, R_below.manager AS A_who
                 , R_below.id AS A_below, R_below.manages AS A_managed
                 FROM Manage AS R_below
                 INNER JOIN Employee AS R_managed
@@ -272,4 +272,43 @@
 """).get
     assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false) === sqlSelect)
   }
+
+  test("transform assymDisj1") {
+    val sparqlParser = Sparql()
+    val sparqlSelect = sparqlParser.parseAll(sparqlParser.select, """
+PREFIX empP : <http://hr.example/DB/Employee#>
+PREFIX manP : <http://hr.example/DB/Manage#>
+PREFIX xsd : <http://www.w3.org/2001/XMLSchema#>
+SELECT ?name
+       { { ?above   manP:manages ?who .
+           ?above   manP:manager ?manager .
+           ?manager empP:lastName  ?name }
+         UNION
+         { ?below   manP:manager ?who .
+           ?below   manP:manages ?managed .
+           ?managed empP:lastName  ?name .
+           ?managed empP:birthday  ?bday } 
+         ?who empP:lastName "Smith"^^xsd:string .
+         ?who empP:birthday ?bday }
+""").get
+    val sqlParser = Sql()
+    val sqlSelect = sqlParser.parseAll(sqlParser.select, """
+SELECT R_union0.A_name AS A_name
+  FROM ( SELECT 0 AS _DISJOINT_, R_manager.lastName AS A_lastName, R_above.manages AS A_who, NULL AS A_bday
+                FROM Manage AS R_above
+                INNER JOIN Employee AS R_manager
+          WHERE R_above.manager=R_manager.id AND R_manager.lastName IS NOT NULL
+       UNION
+         SELECT 1 AS _DISJOINT_, R_managed.lastName AS A_lastName, R_below.manager AS A_who, R_managed.birthday AS A_bday
+                FROM Manage AS R_below
+                INNER JOIN Employee AS R_managed
+          WHERE R_below.manages=R_managed.id AND R_managed.lastName IS NOT NULL
+       ) AS R_union0
+       INNER JOIN Employee AS R_who
+ WHERE R_who.lastName="Smith" AND
+                      (R_union0._DISJOINT_=1 AND R_union1.A_who=R_who.id) OR
+                      (R_union0._DISJOINT_=2 AND R_union1.A_who=R_who.id AND R_union1.A_bday=R_who.birthday)
+""").get
+    assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false) === sqlSelect)
+  }
 }