--- a/src/main/scala/SPARQL.scala Sat Jun 12 09:37:34 2010 -0400
+++ b/src/main/scala/SPARQL.scala Sat Jun 12 17:14:07 2010 -0400
@@ -8,7 +8,7 @@
val uri = """[a-zA-Z0-9:/#_\.\-]+""".r
val integer = """[0-9]+""".r
- val name = """[a-zA-Z][a-zA-Z0-9_]*|[a-zA-Z_][a-zA-Z0-9_]+""".r
+ val name = """[a-zA-Z][a-zA-Z0-9_-]*|[a-zA-Z_][a-zA-Z0-9_]+""".r
var prefixes:Map[String, String] = Map()
var bnodes:Map[String, BNode] = Map()
var nextBNode = 1
@@ -16,8 +16,13 @@
import MyParsers._
-case class Select(attrs:SparqlAttributeList, gp:GraphPattern) {
- override def toString = attrs+"\n"+gp
+case class Select(distinct:Boolean, attrs:SparqlAttributeList, gp:GraphPattern, order:List[OrderElt], offset:Option[Int], limit:Option[Int]) {
+ override def toString =
+ { if (distinct) "DISTINCT " else "" }+
+ attrs+"\n"+gp+
+ { if (order.size > 0) { "ORDER BY " + order.map(o => o.toString).mkString(" ") } else "" }+
+ { if (offset.isDefined) {"OFFSET " + offset } else "" }+
+ { if (limit.isDefined) {"LIMIT " + limit } else "" }
}
case class Construct(head:TriplesBlock, gp:GraphPattern)
case class SparqlAttributeList(attributelist:List[Var]) {
@@ -223,7 +228,12 @@
sealed abstract class PrimaryExpression
case class PrimaryExpressionEq(left:SparqlTermExpression, right:SparqlTermExpression) extends PrimaryExpression
case class PrimaryExpressionLt(left:SparqlTermExpression, right:SparqlTermExpression) extends PrimaryExpression
-case class SparqlTermExpression(term:Term)
+case class PrimaryExpressionGt(left:SparqlTermExpression, right:SparqlTermExpression) extends PrimaryExpression
+case class SparqlTermExpression(term:Term) extends PrimaryExpression
+
+case class OrderElt(desc:Boolean, expr:Expression) {
+ override def toString = { if (desc) "DESC" else "ASC" } + "(" + expr.toString + ")"
+}
sealed trait Term
case class TermUri(u:Uri) extends Term {
@@ -243,7 +253,24 @@
case class Sparql() extends JavaTokenParsers {
def select:Parser[Select] =
- rep(prefixdecls) ~ "SELECT" ~ attributelist ~ opt("WHERE") ~ groupgraphpattern ^^ { case x~"SELECT"~a~w~gp => Select(a, gp) }
+ rep(prefixdecls) ~ "SELECT" ~ opt("DISTINCT") ~ attributelist ~ opt("WHERE") ~ groupgraphpattern ~ opt(order) ~ opt(offset) ~ opt(limit) ^^ {
+ case x~"SELECT"~d~a~w~gp~ord~off~lim => Select(d.isDefined, a, gp, ord.getOrElse(List[OrderElt]()), off, lim)
+ }
+
+ def order:Parser[List[OrderElt]] =
+ "ORDER" ~ "BY" ~ rep(orderelt) ^^ { case o~b~elts => elts }
+
+ def orderelt:Parser[OrderElt] = (
+ "ASC" ~ "(" ~ expression ~ ")" ^^ { case a~o~expr~c => OrderElt(false, expr) }
+ | "DESC" ~ "(" ~ expression ~ ")" ^^ { case a~o~expr~c => OrderElt(true, expr) }
+ | varr ^^ { case v => OrderElt(false, Expression(List(SparqlTermExpression(TermVar(v))))) }
+ )
+
+ def offset:Parser[Int] =
+ "OFFSET" ~ integer ^^ { case o~i => i.toInt }
+
+ def limit:Parser[Int] =
+ "LIMIT" ~ integer ^^ { case o~i => i.toInt }
def construct:Parser[Construct] =
rep(prefixdecls) ~ "CONSTRUCT" ~ constructpattern ~ opt("WHERE") ~ groupgraphpattern ^^ { case x~"CONSTRUCT"~a~w~gp => Construct(a, gp) }
@@ -266,6 +293,9 @@
{ case left ~ "=" ~ right => PrimaryExpressionEq(left, right) }
| value ~ "<" ~ value ^^
{ case left ~ "<" ~ right => PrimaryExpressionLt(left, right) }
+ | value ~ ">" ~ value ^^
+ { case left ~ ">" ~ right => PrimaryExpressionGt(left, right) }
+ | value
)
def value:Parser[SparqlTermExpression] = (
--- a/src/main/scala/SQL.scala Sat Jun 12 09:37:34 2010 -0400
+++ b/src/main/scala/SQL.scala Sat Jun 12 17:14:07 2010 -0400
@@ -116,6 +116,9 @@
case class RelationalExpressionLt(l:Expression, r:Expression) extends RelationalExpression {
override def toString = l + "<" + r
}
+case class RelationalExpressionGt(l:Expression, r:Expression) extends RelationalExpression {
+ override def toString = l + ">" + r
+}
case class RelationalExpressionNull(l:Expression) extends RelationalExpression { // Expression?
override def toString = l + " IS NULL"
}
@@ -406,6 +409,7 @@
case RelationalExpressionEq(l, r) => findNonNullRelVarAttrs(l) ++ findNonNullRelVarAttrs(r)
case RelationalExpressionNe(l, r) => findNonNullRelVarAttrs(l) ++ findNonNullRelVarAttrs(r)
case RelationalExpressionLt(l, r) => findNonNullRelVarAttrs(l) ++ findNonNullRelVarAttrs(r)
+ case RelationalExpressionGt(l, r) => findNonNullRelVarAttrs(l) ++ findNonNullRelVarAttrs(r)
case e:PrimaryExpressionTyped => Set()
case PrimaryExpressionAttr(a) => Set(a)
case e:ConstNULL => Set()
@@ -428,6 +432,7 @@
case e:RelationalExpressionEq => Some(e)
case e:RelationalExpressionNe => Some(e)
case e:RelationalExpressionLt => Some(e)
+ case e:RelationalExpressionGt => Some(e)
case e:PrimaryExpressionTyped => Some(e)
case e:PrimaryExpressionAttr => Some(e)
case e:ConstNULL => Some(e)
@@ -457,6 +462,7 @@
}
case e:RelationalExpressionNe => Some(e)
case e:RelationalExpressionLt => Some(e)
+ case e:RelationalExpressionGt => Some(e)
case e:PrimaryExpressionTyped => Some(e)
case e:PrimaryExpressionAttr => Some(e)
case e:ConstNULL => Some(e)
--- a/src/main/scala/SparqlToSparql.scala Sat Jun 12 09:37:34 2010 -0400
+++ b/src/main/scala/SparqlToSparql.scala Sat Jun 12 17:14:07 2010 -0400
@@ -302,8 +302,10 @@
})
//println("ruleMap: " + ruleMap)
sparql.Select(
+ false,
query.attrs,
- mapGraphPattern(query.gp, ruleMap, "_")
+ mapGraphPattern(query.gp, ruleMap, "_"),
+ List[sparql.OrderElt](), None, None
)
}
--- a/src/main/scala/SparqlToSparqlToSql.scala Sat Jun 12 09:37:34 2010 -0400
+++ b/src/main/scala/SparqlToSparqlToSql.scala Sat Jun 12 17:14:07 2010 -0400
@@ -40,8 +40,10 @@
val (p, pselects, pconsts) = substituteVar(triple.p, "P", triple);
val (o, oselects, oconsts) = substituteVar(triple.o, "O", triple);
val select = sparql.Select(
+ false,
sparql.SparqlAttributeList(sselects ++ pselects ++ oselects),
- sparql.TriplesBlock(List(sparql.TriplePattern(s, p, o)))
+ sparql.TriplesBlock(List(sparql.TriplePattern(s, p, o))),
+ List[sparql.OrderElt](), None, None
)
/* Convert to equivalent SQL SELECT. */
--- a/src/main/scala/SparqlToSql.scala Sat Jun 12 09:37:34 2010 -0400
+++ b/src/main/scala/SparqlToSql.scala Sat Jun 12 17:14:07 2010 -0400
@@ -599,6 +599,8 @@
val (lTerm:sparql.Term, rTerm:sparql.Term, sqlexpr) = f match {
case sparql.PrimaryExpressionEq(l, r) => (l.term, r.term, sql.RelationalExpressionEq(_,_))
case sparql.PrimaryExpressionLt(l, r) => (l.term, r.term, sql.RelationalExpressionLt(_,_))
+ case sparql.PrimaryExpressionGt(l, r) => (l.term, r.term, sql.RelationalExpressionGt(_,_))
+ case sparql.SparqlTermExpression(t) => error("not implemented") // (l.term, r.term, sql.PrimaryExpressionAttr(_,_))
}
lTerm match {
@@ -994,7 +996,7 @@
* @return an SQL query corresponding to sparquery
*/
def apply (db:sql.DatabaseDesc, sparquery:sparql.Select, stem:StemURI, enforceForeignKeys:Boolean, concat:Boolean) : (sql.Select, Map[sparql.Assignable, SQL2RDFValueMapper]) = {
- val sparql.Select(attrs, triples) = sparquery
+ val sparql.Select(_, attrs, triples, _, _, _) = sparquery
/** Create an object to hold our compilation state. */
val initState = R2RState(
--- a/src/test/scala/SparqlTest.scala Sat Jun 12 09:37:34 2010 -0400
+++ b/src/test/scala/SparqlTest.scala Sat Jun 12 17:14:07 2010 -0400
@@ -100,13 +100,15 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("empName"), Var("manageName"))),
TriplesBlock(
List(
TriplePattern(
TermVar(Var("emp")),
TermUri(Uri("http://hr.example/DB/Employee#lastName")),
- TermVar(Var("empName"))))))
+ TermVar(Var("empName"))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -121,13 +123,15 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("empName"), Var("manageName"))),
TriplesBlock(
List(
TriplePattern(
TermVar(Var("emp")),
TermUri(Uri("http://hr.example/DB/Employee#lastName")),
- TermVar(Var("empName"))))))
+ TermVar(Var("empName"))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -141,6 +145,7 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("empName"), Var("manageName"))),
TableFilter(
TriplesBlock(
@@ -153,7 +158,8 @@
PrimaryExpressionLt(SparqlTermExpression(TermVar(Var("manBday"))),
SparqlTermExpression(TermVar(Var("empBday")))),
PrimaryExpressionLt(SparqlTermExpression(TermVar(Var("grandManBday"))),
- SparqlTermExpression(TermVar(Var("manBday"))))))))
+ SparqlTermExpression(TermVar(Var("manBday"))))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -168,6 +174,7 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("empName"), Var("manageName"))),
TriplesBlock(
List(
@@ -182,7 +189,8 @@
TriplePattern(
TermVar(Var("manager")),
TermUri(Uri("http://hr.example/DB/Employee#lastName")),
- TermVar(Var("managName"))))))
+ TermVar(Var("managName"))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -214,13 +222,15 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("x"))),
TriplesBlock(
List(
TriplePattern(
TermVar(Var("x")),
TermUri(Uri("http://hr.example/DB/Employee#manager")),
- TermVar(Var("y"))))))
+ TermVar(Var("y"))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -231,6 +241,7 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("x"))),
TableConjunction(List(
TriplesBlock(
@@ -244,7 +255,8 @@
TriplePattern(
TermVar(Var("x")),
TermUri(Uri("http://hr.example/DB/Employee#manager")),
- TermVar(Var("y"))))))))
+ TermVar(Var("y"))))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -255,6 +267,7 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("x"))),
TableDisjunction(List(
TriplesBlock(
@@ -268,7 +281,8 @@
TriplePattern(
TermVar(Var("x")),
TermUri(Uri("http://hr.example/DB/Employee#manager")),
- TermVar(Var("y"))))))))
+ TermVar(Var("y"))))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -279,6 +293,7 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("x"))),
TableConjunction(List(
TriplesBlock(
@@ -293,7 +308,8 @@
TriplePattern(
TermVar(Var("x")),
TermUri(Uri("http://hr.example/DB/Employee#manager")),
- TermVar(Var("y")))))))))
+ TermVar(Var("y")))))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -304,6 +320,7 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("x"))),
OptionalGraphPattern(
TriplesBlock(
@@ -311,7 +328,8 @@
TriplePattern(
TermVar(Var("x")),
TermUri(Uri("http://hr.example/DB/Employee#manager")),
- TermVar(Var("y")))))))
+ TermVar(Var("y")))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -322,6 +340,7 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("x"))),
TableConjunction(List(
TriplesBlock(
@@ -336,7 +355,8 @@
TriplePattern(
TermVar(Var("x")),
TermUri(Uri("http://hr.example/DB/Employee#manager")),
- TermVar(Var("y")))))))))
+ TermVar(Var("y")))))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -355,6 +375,7 @@
"""
val tps =
Select(
+ false,
SparqlAttributeList(List(Var("name"))),
TableConjunction(List(
TriplesBlock(
@@ -393,7 +414,8 @@
TermVar(Var("managed")),
TermUri(Uri("http://hr.example/DB/Employee#lastName")),
TermVar(Var("name")))
- )))))))
+ )))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
@@ -411,13 +433,14 @@
FILTER ( ?emp1Name < ?emp2Name && ?emp2Name < ?emp3Name && ?emp3Name < ?emp4Name) }
"""
val tps =
- Select(SparqlAttributeList(List(Var("emp1Name"), Var("emp2Name"), Var("emp3Name"))),
+ Select(false, SparqlAttributeList(List(Var("emp1Name"), Var("emp2Name"), Var("emp3Name"))),
TableFilter(TableConjunction(List(TriplesBlock(List(TriplePattern(TermVar(Var("emp1")), TermUri(Uri("http://hr.example/DB/Employee#lastName")), TermVar(Var("emp1Name"))))),
OptionalGraphPattern(TriplesBlock(List(TriplePattern(TermVar(Var("emp1")), TermUri(Uri("http://hr.example/DB/Employee#birthday")), TermVar(Var("birthday")))))),
TriplesBlock(List(TriplePattern(TermVar(Var("emp2")), TermUri(Uri("http://hr.example/DB/Employee#lastName")), TermVar(Var("emp2Name"))))),
OptionalGraphPattern(TriplesBlock(List(TriplePattern(TermVar(Var("emp2")), TermUri(Uri("http://hr.example/DB/Employee#birthday")), TermVar(Var("birthday")))))),
TriplesBlock(List(TriplePattern(TermVar(Var("emp4")),TermUri(Uri("http://hr.example/DB/Employee#birthday")),TermVar(Var("birthday"))))))),
- Expression(List(PrimaryExpressionLt(SparqlTermExpression(TermVar(Var("emp1Name"))),SparqlTermExpression(TermVar(Var("emp2Name")))), PrimaryExpressionLt(SparqlTermExpression(TermVar(Var("emp2Name"))),SparqlTermExpression(TermVar(Var("emp3Name")))), PrimaryExpressionLt(SparqlTermExpression(TermVar(Var("emp3Name"))),SparqlTermExpression(TermVar(Var("emp4Name"))))))))
+ Expression(List(PrimaryExpressionLt(SparqlTermExpression(TermVar(Var("emp1Name"))),SparqlTermExpression(TermVar(Var("emp2Name")))), PrimaryExpressionLt(SparqlTermExpression(TermVar(Var("emp2Name"))),SparqlTermExpression(TermVar(Var("emp3Name")))), PrimaryExpressionLt(SparqlTermExpression(TermVar(Var("emp3Name"))),SparqlTermExpression(TermVar(Var("emp4Name"))))))),
+ List[OrderElt](), None, None)
assert(tps === a.parseAll(a.select, e).get)
}
--- a/src/test/scala/SparqlToSparqlToSqlTest.scala Sat Jun 12 09:37:34 2010 -0400
+++ b/src/test/scala/SparqlToSparqlToSqlTest.scala Sat Jun 12 17:14:07 2010 -0400
@@ -95,7 +95,8 @@
FROM Employee AS R_S
WHERE (R_S.empid IS NOT NULL)
AND (R_S.lastName IS NOT NULL)
-""").get
+""" //"
+ ).get
assert(expected === view)
}
@@ -343,4 +344,92 @@
// assert(expected === view)
// }
+ /* ========== DiabeticPatient database tests ==========
+ *
+ */
+ val bsbmDdl = """
+CREATE TABLE Person (ID INT PRIMARY KEY, MiddleName STRING, DateOfBirth DATE, SexDE INT, PRIMARY KEY (ID), FOREIGN KEY (SexDE) REFERENCES Sex_DE(ID));
+CREATE TABLE Sex_DE (ID INT PRIMARY KEY, EntryName STRING);
+CREATE TABLE Item_Medication (ID INT PRIMARY KEY, PRIMARY KEY (ID), PatientID INT, FOREIGN KEY (PatientID) REFERENCES Person(ID), PerformedDTTM DATE, EntryName STRING);
+CREATE TABLE Medication (ID INT PRIMARY KEY, PRIMARY KEY (ID), ItemID INT, FOREIGN KEY (ItemID) REFERENCES Item_Medication(ID), MedDictDE INT, FOREIGN KEY (MedDictDE) REFERENCES Medication_DE(ID), DaysToTake INT);
+CREATE TABLE Medication_DE (ID INT PRIMARY KEY, NDC INT);
+CREATE TABLE NDCcodes (ID INT PRIMARY KEY, NDC INT, ingredient INT);
+"""
+ val bsbmDb:DatabaseDesc = DDLParser.parseAll(DDLParser.ddl, bsbmDdl).get
+ val delme = Sparql() // re-use ConstructParser ?
+ val db2bsbm = delme.parseAll(delme.construct, """
+PREFIX map: <file:/E:/code/d2r-server-0.4/d2r-mapping.n3#>
+PREFIX vocab: <vocab/>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
+PREFIX d2rq: <http://www.wiwiss.fu-berlin.de/suhl/bizer/D2RQ/0.1#>
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+PREFIX bsbm: <http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/vocabulary/>
+PREFIX bsbm-inst: <http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/instances/>
+PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX rev: <http://purl.org/stuff/rev#>
+
+PREFIX offer: <http://bsbm.example/db/offer#>
+PREFIX person: <http://bsbm.example/db/person#>
+PREFIX producer: <http://bsbm.example/db/producer#>
+PREFIX product: <http://bsbm.example/db/product#>
+PREFIX productfeatureproduct: <http://bsbm.example/db/productfeatureproduct#>
+PREFIX producttypeproduct: <http://bsbm.example/db/producttypeproduct#>
+PREFIX productfeature: <http://bsbm.example/db/productfeature#>
+PREFIX producttype: <http://bsbm.example/db/producttype#>
+PREFIX review: <http://bsbm.example/db/review#>
+PREFIX vendor: <http://bsbm.example/db/vendor#>
+
+PREFIX tr: <http://www.w3.org/2008/04/SPARQLfed/#>
+
+CONSTRUCT {
+<s> <p> <o> .
+} WHERE {
+<s> <p> <o> .
+}""" //"
+ ).get
+ test("bsbm1") {
+ val sparqlParser = Sparql()
+ val bsbmQuery = sparqlParser.parseAll(sparqlParser.select, """
+PREFIX bsbm-inst: <http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/instances/>
+PREFIX bsbm: <http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/vocabulary/>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+
+SELECT DISTINCT ?product ?label
+WHERE {
+ ?product rdfs:label ?label .
+ ?product a <http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/instances/ProductType59> .
+ ?product bsbm:productFeature <http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/instances/ProductFeature5> .
+ ?product bsbm:productFeature <http://www4.wiwiss.fu-berlin.de/bizer/bsbm/v01/instances/ProductFeature7> .
+?product bsbm:productPropertyNumeric1 ?value1 .
+ FILTER (?value1 > 578)
+ }
+ORDER BY ?label
+LIMIT 10
+""").get
+
+ val stemQuery = sparqlParser.parseAll(sparqlParser.select, """
+SELECT ?o WHERE { ?s <p> ?o }
+""").get
+ val sqlParser = Sql()
+ val sqlQuery = sqlParser.parseAll(sqlParser.select, """
+SELECT R_emp.empid AS emp
+ FROM Employee AS R_emp
+ WHERE R_emp.empid IS NOT NULL AND R_emp.lastName="Smith"
+""").get
+// val asStem = SparqlToSparql(bsbmQuery, List(db2bsbm))
+// if (!(asStem == stemQuery)) {
+// println(asStem.toString())
+// println("---")
+// println(stemQuery.toString())
+// }
+// assert(asStem == stemQuery)
+// val asSql = SparqlToSql(bsbmDb, asStem, StemURI("http://hospital.example/DB/"), false, false)._1
+// assert(asSql === sqlQuery)
+// val output = """
+// """
+ }
+
}