--- a/src/main/scala/RDB2RDFMain.scala Sat Jan 02 18:34:46 2010 -0500
+++ b/src/main/scala/RDB2RDFMain.scala Sun Jan 03 03:01:12 2010 -0500
@@ -216,6 +216,14 @@
/* Examine each triple, updating the compilation state. */
triplepatterns.foldLeft(Set[Var]())((x, y) => x ++ findVars(y))
+ case TableConjunction(list) =>
+ /* Examine each triple, updating the compilation state. */
+ list.foldLeft(Set[Var]())((x, y) => x ++ findVars(y))
+
+ case OptionalGraphPattern(gp2) =>
+ /* Examine each triple, updating the compilation state. */
+ findVars(gp2)
+
case x => error("no code to handle " + x)
}
}
@@ -364,84 +372,73 @@
val subselect = Subselect(Union(disjoints))
R2RState(state.joins + InnerJoin(AliasedResource(subselect,unionAlias)), state2.varmap, state2.exprs)
}
- // case OptionalGraphPattern(gp) => {
- // val leftJoinAlias = RelAlias(Name("R_leftJoin" + state.joins.size))
- // val initDisjoints:Set[Select] = Set()
- // val emptyState = R2RState(
- // Set[Join](),
- // Map[Var, SQL2RDFValueMapper](),
- // Set[Expression]()
- // )
- // val leftJoinVars = list.foldLeft(Set[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, enforeForeignKeys)
- // val disjointVars = findVars(disjoint)
- // val disjointNo = NamedAttribute(ConstInt("" + no), AttrAlias(Name("_DISJOINT_")))
- // val disjointNoAliasAttr = RelAliasAttribute(leftJoinAlias, Attribute(Name("_DISJOINT_")))
- // val disjointCond = RelationalExpressionNe(disjointNoAliasAttr, RValueTyped(SQLDatatype.INTEGER,Name("" + no)))
-
- // val attrlist:Set[NamedAttribute] = leftJoinVars.foldLeft(Set(disjointNo))((attrs, v) => {
- // val attrOrNull = if (disjointState.varmap.contains(v)) varToAttribute(disjointState.varmap, v) else ConstNULL()
- // attrs ++ Set(NamedAttribute(attrOrNull, AttrAlias(Name("A_" + v.s))))
- // })
+ case OptionalGraphPattern(gp) => {
+ val leftJoinAlias = RelAlias(Name("R_opt" + state.joins.size))
+ val initDisjoints:Set[Select] = Set()
+ val emptyState = R2RState(
+ Set[Join](),
+ Map[Var, SQL2RDFValueMapper](),
+ Set[Expression]()
+ )
+ val optionalState = mapGraphPattern(db, emptyState, gp, pk, enforeForeignKeys)
+ val optionalVars = findVars(gp)
- // val subselect = Select(
- // AttributeList(attrlist),
- // TableList(disjointState.joins),
- // disjointState.exprs.size match {
- // case 0 => None
- // case 1 => Some(disjointState.exprs.toList(0))
- // case _ => Some(ExprConjunction(disjointState.exprs))
- // }
- // )
- // val outerState2 = disjointVars.foldLeft(outerState)((myState, v) => {
- // val varAliasAttr = RelAliasAttribute(leftJoinAlias, Attribute(Name("A_" + v.s)))
- // if (myState.varmap.contains(v)) {
- // /* The variable has already been bound. */
- // val newMap:Map[Var, SQL2RDFValueMapper] = if (varToAttribute(myState.varmap, v) == varAliasAttr) {
- // /* Same var was bound in an earlier disjoint. */
- // val oldDisjoints = varToAttributeDisjoints(myState.varmap, v)
- // // myState
- // Map(v -> { disjointState.varmap(v) match {
- // case IntMapper(_, _) => IntMapper(varAliasAttr, oldDisjoints + disjointCond)
- // case StringMapper(_, _) => StringMapper(varAliasAttr, oldDisjoints + disjointCond)
- // case DateMapper(_, _) => DateMapper(varAliasAttr, oldDisjoints + disjointCond)
- // case RDFNoder(rel, _, _) => RDFNoder(rel, varAliasAttr, oldDisjoints + disjointCond)
- // case RDFBNoder(rel, _, _) => RDFBNoder(rel, varAliasAttr, oldDisjoints + disjointCond)
- // } } )
- // } else
- // Map()
- // val newConstraints =
- // if (varToAttribute(outerState.varmap, v) != varAliasAttr) {
- // /* Constraint against binding from earlier GP. */
- // val constraint = RelationalExpressionEq(varToAttribute(outerState.varmap, v), RValueAttr(varAliasAttr))
- // if (varToAttributeDisjoints(outerState.varmap, v).size > 0)
- // // (leftJoin0._DISJOINT_ != 0 AND leftJoin1._DISJOINT_ != 2) OR leftJoin0.x=leftJoin1.x
- // varToAttributeDisjoints(outerState.varmap, v) map ((d) => ExprDisjunction(Set(ExprConjunction(Set(d, disjointCond)), constraint)))
- // else
- // Set(ExprDisjunction(Set(disjointCond, constraint)))
- // } else {
- // Set()
- // }
- // R2RState(myState.joins, myState.varmap ++ newMap, myState.exprs ++ newConstraints)
- // } else {
- // /* This variable is new to the outer context. */
- // val mapper:SQL2RDFValueMapper = disjointState.varmap(v) match {
- // case IntMapper(_, _) => IntMapper(varAliasAttr, Set(disjointCond))
- // case StringMapper(_, _) => StringMapper(varAliasAttr, Set(disjointCond))
- // case DateMapper(_, _) => DateMapper(varAliasAttr, Set(disjointCond))
- // case RDFNoder(rel, _, _) => RDFNoder(rel, varAliasAttr, Set(disjointCond))
- // case RDFBNoder(rel, _, _) => RDFBNoder(rel, varAliasAttr, Set(disjointCond))
- // }
- // R2RState(myState.joins, myState.varmap + (v -> mapper), myState.exprs)
- // }
- // })
- // (outerState2, outerDisjoints ++ Set(subselect), no+1)
- // })
- // val subselect = Subselect(Union(disjoints))
- // R2RState(state.joins + InnerJoin(AliasedResource(subselect,unionAlias)), state2.varmap, state2.exprs)
- // }
+ val leftJoinVars = findVars(gp).toList
+ val attrlist:Set[NamedAttribute] = leftJoinVars.foldLeft(Set[NamedAttribute]())((attrs, v) =>
+ attrs ++ Set(NamedAttribute(varToAttribute(optionalState.varmap, v), AttrAlias(Name("A_" + v.s))))
+ )
+
+ val subselect = Select(
+ AttributeList(attrlist),
+ TableList(optionalState.joins),
+ optionalState.exprs.size match {
+ case 0 => None
+ case 1 => Some(optionalState.exprs.toList(0))
+ case _ => Some(ExprConjunction(optionalState.exprs))
+ }
+ )
+
+ val outerState2 = optionalVars.foldLeft(R2RState(state.joins, state.varmap, Set[Expression]()))((myState, v) => {
+ val varAliasAttr = RelAliasAttribute(leftJoinAlias, Attribute(Name("A_" + v.s)))
+ if (myState.varmap.contains(v)) {
+ /* The variable has already been bound. */
+ val newMap:Map[Var, SQL2RDFValueMapper] = if (varToAttribute(myState.varmap, v) == varAliasAttr) {
+ /* Same var was already bound. */
+ error("Variable " + v + " already bound to " + varAliasAttr)
+ } else
+ Map()
+ val newConstraints = {
+ /* Constraint against binding from earlier GP. */
+ val constraint = RelationalExpressionEq(varToAttribute(state.varmap, v), RValueAttr(varAliasAttr))
+ if (varToAttributeDisjoints(state.varmap, v).size > 0)
+ // (leftJoin0._DISJOINT_ != 0 AND leftJoin1._DISJOINT_ != 2) OR leftJoin0.x=leftJoin1.x
+ varToAttributeDisjoints(state.varmap, v) map ((d) => ExprDisjunction(Set(d, constraint)))
+ else
+ Set(constraint)
+ }
+ println("" + v + " begets " + newMap + " and " + newConstraints)
+ R2RState(myState.joins, myState.varmap ++ newMap, myState.exprs ++ newConstraints)
+ } else {
+ /* This variable is new to the outer context. */
+ val mapper:SQL2RDFValueMapper = optionalState.varmap(v) match {
+ case IntMapper(_, _) => IntMapper(varAliasAttr, Set())
+ case StringMapper(_, _) => StringMapper(varAliasAttr, Set())
+ case DateMapper(_, _) => DateMapper(varAliasAttr, Set())
+ case RDFNoder(rel, _, _) => RDFNoder(rel, varAliasAttr, Set())
+ case RDFBNoder(rel, _, _) => RDFBNoder(rel, varAliasAttr, Set())
+ }
+ R2RState(myState.joins, myState.varmap + (v -> mapper), myState.exprs)
+ }
+ })
+ val join = LeftOuterJoin(AliasedResource(Subselect(subselect), leftJoinAlias),
+ outerState2.exprs.size match {
+ case 0 => error ("Nested GP has no variables shared with its context; cowaredly refusing to join ON 1.")
+ case 1 => outerState2.exprs.toList(0)
+ case _ => ExprConjunction(outerState2.exprs)
+ }
+ )
+ R2RState(state.joins + join, outerState2.varmap, state.exprs)
+ }
case x => error("no code to handle " + x)
}
}
--- a/src/test/scala/RDB2RDFTest.scala Sat Jan 02 18:34:46 2010 -0500
+++ b/src/test/scala/RDB2RDFTest.scala Sun Jan 03 03:01:12 2010 -0500
@@ -417,39 +417,88 @@
assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false) === sqlSelect)
}
-// test("transform nestOpt") {
-// val sparqlParser = Sparql()
-// val sparqlSelect = sparqlParser.parseAll(sparqlParser.select, """
-// PREFIX emplP: <http://hr.example/DB/Employee#>
-// PREFIX mangP: <http://hr.example/DB/Manage#>
+ test("transform optJoin1") {
+ val sparqlParser = Sparql()
+ val sparqlSelect = sparqlParser.parseAll(sparqlParser.select, """
+PREFIX emplP: <http://hr.example/DB/Employee#>
+PREFIX mangP: <http://hr.example/DB/Manage#>
-// SELECT ?empName ?managName ?grandManagName
-// WHERE { ?emp emplP:lastName ?empName
-// OPTIONAL { ?mang mangP:manages ?emp .
-// ?mang mangP:manager ?manager .
-// ?manager emplP:lastName ?managName
-// OPTIONAL { ?grandMang mangP:manages ?manager .
-// ?grandMang mangP:manager ?grandManager .
-// ?grandManager emplP:lastName ?grandManagName } }
-// }
-// """).get
-// val sqlParser = Sql()
-// val sqlSelect = sqlParser.parseAll(sqlParser.select, """
-// SELECT R_emp.lastName AS A_empName, R_opt1.A_managName AS A_managName, R_opt1.A_grandManagName AS A_grandManagName
-// FROM Employee AS R_emp
-// LEFT OUTER JOIN (
-// SELECT R_opt1.A_grandManagName AS A_grandManagName, R_manager.lastName AS A_managName, R_mang.manages AS R_emp, R_mang.manager AS A_manager
-// FROM Manage AS R_mang
-// INNER JOIN Employee AS R_manager
-// LEFT OUTER JOIN (
-// SELECT R_grandManager.lastName AS A_grandManagName, R_grandMang.manages AS A_manager
-// FROM Manage AS R_grandMang
-// INNER JOIN Employee AS R_grandManager
-// ) AS R_opt1 ON R_opt1.manager=R_mang.manager
-// WHERE R_manager.id=R_mang.manager AND R_grandManager.id=R_grandMang.manager
-// ) AS R_opt1 ON opt1.emp=R_emp.id
-// WHERE R_emp.lastName IS NOT NULL
-// """).get
-// assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id"))), false) === sqlSelect)
-// }
+SELECT ?empName ?managName ?grandManagName
+ WHERE { ?emp emplP:lastName ?empName
+ OPTIONAL { ?mang mangP:manages ?emp .
+ ?mang mangP:manager ?manager .
+ ?manager emplP:lastName ?managName .
+ ?grandMang mangP:manages ?manager .
+ ?grandMang mangP:manager ?grandManager .
+ ?grandManager emplP:lastName ?grandManagName } }
+""").get
+ val sqlParser = Sql()
+ val sqlSelect = sqlParser.parseAll(sqlParser.select, """
+SELECT R_emp.lastName AS A_empName, R_opt1.A_managName AS A_managName, R_opt1.A_grandManagName AS A_grandManagName
+ FROM Employee AS R_emp
+ LEFT OUTER JOIN (
+ SELECT R_grandManager.lastName AS A_grandManagName, R_manager.lastName AS A_managName, R_mang.manages AS A_emp,
+ R_grandMang.manager AS A_grandManager,
+ R_mang.id AS A_mang,
+ R_mang.manager AS A_manager,
+ R_grandMang.id AS A_grandMang
+ FROM Manage AS R_mang
+ INNER JOIN Employee AS R_manager
+ INNER JOIN Manage AS R_grandMang
+ INNER JOIN Employee AS R_grandManager
+ WHERE R_mang.manager=R_manager.id AND R_mang.manager=R_grandMang.manages AND R_grandMang.manager=R_grandManager.id
+ AND (R_grandMang.manager IS NOT NULL)
+ AND (R_mang.manages IS NOT NULL)
+ AND (R_mang.id IS NOT NULL)
+ AND (R_grandManager.lastName IS NOT NULL)
+ AND (R_mang.manager IS NOT NULL)
+ AND (R_manager.lastName IS NOT NULL)
+ AND (R_grandMang.id IS NOT NULL)
+ ) 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) === sqlSelect)
+ }
+
+ test("transform nestOpt") {
+ val sparqlParser = Sparql()
+ val sparqlSelect = sparqlParser.parseAll(sparqlParser.select, """
+PREFIX emplP: <http://hr.example/DB/Employee#>
+PREFIX mangP: <http://hr.example/DB/Manage#>
+
+SELECT ?empName ?managName ?grandManagName
+ WHERE { ?emp emplP:lastName ?empName
+ OPTIONAL { ?mang mangP:manages ?emp .
+ ?mang mangP:manager ?manager .
+ ?manager emplP:lastName ?managName
+ OPTIONAL { ?grandMang mangP:manages ?manager .
+ ?grandMang mangP:manager ?grandManager .
+ ?grandManager emplP:lastName ?grandManagName } }
+ }
+""").get
+ val sqlParser = Sql()
+ val sqlSelect = sqlParser.parseAll(sqlParser.select, """
+SELECT R_emp.lastName AS A_empName, R_opt1.A_managName AS A_managName, R_opt1.A_grandManagName AS A_grandManagName
+ FROM Employee AS R_emp
+ LEFT OUTER JOIN (
+ SELECT R_opt2.A_grandManagName AS A_grandManagName, R_manager.lastName AS A_managName, R_mang.manages AS A_emp, R_mang.manager AS A_manager,
+ R_mang.id AS A_mang, R_opt2.A_grandMang AS A_grandMang, R_opt2.A_grandManager AS A_grandManager
+ FROM Manage AS R_mang
+ INNER JOIN Employee AS R_manager
+ LEFT OUTER JOIN (
+ SELECT R_grandManager.lastName AS A_grandManagName, R_grandMang.manages AS A_manager,
+ R_grandMang.id AS A_grandMang, R_grandMang.manager AS A_grandManager
+ FROM Manage AS R_grandMang
+ INNER JOIN Employee AS R_grandManager
+ WHERE R_grandMang.manager=R_grandManager.id AND R_grandMang.manages IS NOT NULL AND R_grandMang.manager IS NOT NULL
+ AND R_grandManager.lastName IS NOT NULL AND R_grandMang.id IS NOT NULL
+ ) AS R_opt2 ON R_mang.manager=R_opt2.A_manager
+ WHERE R_mang.manager=R_manager.id
+ AND R_mang.manages IS NOT NULL AND R_mang.id IS NOT NULL AND R_mang.manager IS NOT NULL AND R_manager.lastName IS NOT NULL
+ ) 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) === sqlSelect)
+ }
}