--- a/src/main/scala/SPARQL.scala Mon Feb 08 09:52:01 2010 -0500
+++ b/src/main/scala/SPARQL.scala Mon Feb 08 11:50:35 2010 -0500
@@ -21,7 +21,29 @@
override def toString = "SELECT "+(attributelist.toList.sortWith((l, r) => l.s < r.s).mkString(", "))
}
-sealed abstract class GraphPattern
+sealed abstract class GraphPattern {
+ def findVars ():Set[Var] = {
+ this match {
+ case TableFilter(gp2:GraphPattern, expr:Expression) =>
+ gp2.findVars
+
+ case TriplesBlock(triplepatterns) =>
+ /* Examine each triple, updating the compilation state. */
+ triplepatterns.foldLeft(Set[Var]())((x, y) => x ++ y.findVars)
+
+ case TableConjunction(list) =>
+ /* Examine each triple, updating the compilation state. */
+ list.foldLeft(Set[Var]())((x, y) => x ++ y.findVars)
+
+ case OptionalGraphPattern(gp2) =>
+ /* Examine each triple, updating the compilation state. */
+ gp2.findVars
+
+ case x => error("no code to handle " + x)
+ }
+ }
+
+}
case class TriplesBlock(triplepatterns:List[TriplePattern]) extends GraphPattern {
override def toString = "{\n " + (triplepatterns.toList.map(s => s.toString.replace("\n", "\n ")).mkString(".\n ")) + "\n}"
}
@@ -39,6 +61,17 @@
case class TriplePattern(s:Term, p:Term, o:Term) {
override def toString = s + " " + p + " " + o
+ def findVars ():Set[Var] = {
+ val varS:Set[Var] = s match {
+ case TermVar(v) => Set(v)
+ case _ => Set()
+ }
+ val varO:Set[Var] = o match {
+ case TermVar(v) => Set(v)
+ case _ => Set()
+ }
+ varS ++ varO
+ }
}
case class Literal(lit:RDFLiteral) {
--- a/src/main/scala/SparqlToSql.scala Mon Feb 08 09:52:01 2010 -0500
+++ b/src/main/scala/SparqlToSql.scala Mon Feb 08 11:50:35 2010 -0500
@@ -287,40 +287,6 @@
}
}
- def findVars(triple:sparql.TriplePattern):Set[sparql.Var] = {
- val sparql.TriplePattern(s, p, o) = triple
- val varS:Set[sparql.Var] = s match {
- case sparql.TermVar(v) => Set(v)
- case _ => Set()
- }
- val varO:Set[sparql.Var] = o match {
- case sparql.TermVar(v) => Set(v)
- case _ => Set()
- }
- varS ++ varO
- }
-
- def findVars(gp:sparql.GraphPattern):Set[sparql.Var] = {
- gp match {
- case sparql.TableFilter(gp2:sparql.GraphPattern, expr:sparql.Expression) =>
- findVars(gp2)
-
- case sparql.TriplesBlock(triplepatterns) =>
- /* Examine each triple, updating the compilation state. */
- triplepatterns.foldLeft(Set[sparql.Var]())((x, y) => x ++ findVars(y))
-
- case sparql.TableConjunction(list) =>
- /* Examine each triple, updating the compilation state. */
- list.foldLeft(Set[sparql.Var]())((x, y) => x ++ findVars(y))
-
- case sparql.OptionalGraphPattern(gp2) =>
- /* Examine each triple, updating the compilation state. */
- findVars(gp2)
-
- case x => error("no code to handle " + x)
- }
- }
-
def bindingConstraintToAttribute(constraint:BindingConstraint):sql.RelVarAttr = {
val BindingConstraint(expr:sql.RelationalExpression, relvarattr:sql.RelVarAttr) = constraint;
relvarattr
@@ -486,10 +452,10 @@
/* Create the select for the nested graph pattern.
*/
val optionalState = mapGraphPattern(db, emptyState, gp, enforceForeignKeys)
- val optionalVars = findVars(gp)
+ val optionalVars = gp.findVars
val disjointNo = sql.NamedAttribute(sql.PrimaryExpressionTyped(sql.Datatype.INTEGER,sql.Name("" + initState.joins.size)),
sql.AttrAlias(sql.Name("_DISJOINT_")))
- val leftJoinVars = findVars(gp).toList
+ val leftJoinVars = gp.findVars.toList
val attrlist:Set[sql.NamedAttribute] = leftJoinVars.foldLeft(Set(disjointNo))((attrs, v) =>
attrs ++ Set(sql.NamedAttribute(varToAttribute(optionalState.varmap, v), sql.AttrAlias(attrAliasNameFromVar(v))))
)
@@ -558,7 +524,7 @@
case sparql.TriplesBlock(triplepatterns) => {
/* Examine each triple, updating the compilation state. */
val state2 = triplepatterns.foldLeft(state)((incState,s) => bindOnPredicate(db, incState, s, enforceForeignKeys))
- val nullExprs = findVars(gp).foldLeft(Set[sql.Expression]())((s, vvar) => {
+ val nullExprs = gp.findVars.foldLeft(Set[sql.Expression]())((s, vvar) => {
if (varToAttributeDisjoints(state2.varmap, vvar).size == 0)
s ++ Set(sql.RelationalExpressionNotNull(sql.PrimaryExpressionAttr(varToAttribute(state2.varmap, vvar))))
else
@@ -580,7 +546,7 @@
Set[sql.Expression]()
)
val unionVars = disjoints.foldLeft(Set[sparql.Var]())((mySet,disjoint) =>
- mySet ++ findVars(disjoint)).toList
+ mySet ++ disjoint.findVars).toList
/* Map the disjoints to subselects.
* <no> is used for uniquely naming flags in the SELECTs used to
@@ -618,7 +584,7 @@
val (state2, _) = disjoints.foldLeft((state, 0))((incPair,disjoint) => {
val (outerState, no) = incPair
val disjointState = mapGraphPattern(db, emptyState, disjoint, enforceForeignKeys)
- val disjointVars = findVars(disjoint)
+ val disjointVars = disjoint.findVars
/* Create a condition to test if this OPTIONAL was matched (called
* _DISJOINT_ as OPTIONAL behaves pretty much like a disjunction).
--- a/src/test/scala/SparqlToSparqlTest.scala Mon Feb 08 09:52:01 2010 -0500
+++ b/src/test/scala/SparqlToSparqlTest.scala Mon Feb 08 11:50:35 2010 -0500
@@ -115,13 +115,6 @@
?pair task:manager ?man .
?man empP:lastName ?mname }
""").get
- SparqlToSparql.Abbreviations.update("<http://xmlns.com/foaf/0.1/last_name>", "foaf:last_name")
- SparqlToSparql.Abbreviations.update("<http://xmlns.com/foaf/0.1/knows>", "foaf:knows")
- SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Employee#lastName>", "Employee:lastName")
- SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Task#drone>", "Task:drone")
- SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Task#manager>", "Task:manager")
- SparqlToSparql.Abbreviations.update("^^http://www.w3.org/2001/XMLSchema#string", "")
-
val transformed = SparqlToSparql(query, List(rule1))
val expected = sparqlParser.parseAll(sparqlParser.select, """
PREFIX empP : <http://hr.example/DB/Employee#>
@@ -136,4 +129,50 @@
assert(transformed === expected)
}
+// test("trans head") {
+// val sparqlParser = Sparql()
+// val query = sparqlParser.parseAll(sparqlParser.select, """
+// PREFIX foaf : <http://xmlns.com/foaf/0.1/>
+// PREFIX xsd : <http://www.w3.org/2001/XMLSchema#>
+// SELECT ?lname {
+// ?who foaf:last_name ?lname .
+// ?who foaf:knows ?whom .
+// ?whom foaf:knows ?whom2 .
+// ?whom2 foaf:last_name "Smith"^^xsd:string }
+// """).get
+// val rule1 = sparqlParser.parseAll(sparqlParser.construct, """
+// PREFIX foaf : <http://xmlns.com/foaf/0.1/>
+// PREFIX empP : <http://hr.example/DB/Employee#>
+// PREFIX task : <http://hr.example/DB/Task#>
+// CONSTRUCT { ?emp foaf:last_name ?wname .
+// ?emp foaf:knows ?man .
+// ?man foaf:last_name ?mname }
+// WHERE { ?emp empP:lastName ?wname .
+// ?pair task:drone ?emp .
+// ?pair task:manager ?man .
+// ?man empP:lastName ?mname }
+// """).get
+// SparqlToSparql.Abbreviations.update("<http://xmlns.com/foaf/0.1/last_name>", "foaf:last_name")
+// SparqlToSparql.Abbreviations.update("<http://xmlns.com/foaf/0.1/knows>", "foaf:knows")
+// SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Employee#lastName>", "Employee:lastName")
+// SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Task#drone>", "Task:drone")
+// SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Task#manager>", "Task:manager")
+// SparqlToSparql.Abbreviations.update("^^http://www.w3.org/2001/XMLSchema#string", "")
+
+// val transformed = SparqlToSparql(query, List(rule1))
+// val expected = sparqlParser.parseAll(sparqlParser.select, """
+// PREFIX empP : <http://hr.example/DB/Employee#>
+// PREFIX task : <http://hr.example/DB/Task#>
+// PREFIX xsd : <http://www.w3.org/2001/XMLSchema#>
+// SELECT ?lname
+// { ?who empP:lastName ?lname .
+// ?pair task:drone ?who .
+// ?pair task:manager ?whom .
+// ?pair2 task:drone ?whom .
+// ?pair2 task:manager ?whom2 .
+// ?whom2 empP:lastName "Smith"^^xsd:string }
+// """).get
+// assert(transformed === expected)
+// }
+
}