+ recursive GraphPattern
authorEric Prud'hommeaux <bertails@w3.org>
Sun, 27 Dec 2009 16:44:52 -0800
changeset 74 462bd3ddfc3f
parent 73 853d9bcb1e41
child 75 82826db7819c
+ recursive GraphPattern
src/main/scala/RDB2RDFMain.scala
src/main/scala/SPARQL.scala
src/test/scala/SparqlTest.scala
--- a/src/main/scala/RDB2RDFMain.scala	Sun Dec 27 15:05:58 2009 -0800
+++ b/src/main/scala/RDB2RDFMain.scala	Sun Dec 27 16:44:52 2009 -0800
@@ -196,6 +196,15 @@
     varS ++ varO
   }
 
+  def findVars(gp:GraphPattern):Set[Var] = {
+    gp match {
+      case BasicGraphPattern(triplepatterns, filter:SparqlExpression) => {
+	/* Examine each triple, updating the compilation state. */
+	triplepatterns.foldLeft(Set[Var]())((x, y) => x ++ findVars(y))
+      }
+    }
+  }
+
   def varToAttribute(varmap:Map[Var, SQL2RDFValueMapper], vvar:Var):RelAliasAttribute = {
     varmap(vvar) match {
       case StringMapper(relalias) => relalias
@@ -205,8 +214,8 @@
     }
   }
 
-  def filter(varmap:Map[Var, SQL2RDFValueMapper], f:SparqlPrimaryExpression):PrimaryExpression = {
-    val (lTerm:Term, rTerm:Term, sqlexpr:((RelAliasAttribute,RValueAttr)=>PrimaryExpression)) = f match {
+  def filter2expr(varmap:Map[Var, SQL2RDFValueMapper], f:SparqlPrimaryExpression):PrimaryExpression = {
+    val (lTerm:Term, rTerm:Term, sqlexpr) = f match { // sqlexpr::((RelAliasAttribute,RValueAttr)=>PrimaryExpression)
       case SparqlPrimaryExpressionEq(l, r) => (l.term, r.term, PrimaryExpressionEq(_,_))
       case SparqlPrimaryExpressionLt(l, r) => (l.term, r.term, PrimaryExpressionLt(_,_))
     }
@@ -242,6 +251,27 @@
     PrimaryExpressionNotNull(aattr)
   }
 
+  def mapGraphPattern(db:DatabaseDesc, stateP:R2RState, gp:GraphPattern, pk:PrimaryKey, enforeForeignKeys:Boolean):R2RState = {
+    var state = stateP
+    gp match {
+      case BasicGraphPattern(triplepatterns, filter:SparqlExpression) => {
+	/* Examine each triple, updating the compilation state. */
+	triplepatterns.foreach(s => state = bindOnPredicate(db, state, s, pk, true))
+
+	/* Add constraints for all the FILTERS */
+	val filterExprs:Set[PrimaryExpression] =
+	  filter.conjuncts.toSet map ((x:SparqlPrimaryExpression) => filter2expr(state.varmap, x))
+
+	// val allVars:Set[Var] = triples.triplepatterns.foldLeft(Set[Var]())((x, y) => x ++ findVars(y))
+	val allVars:Set[Var] = findVars(gp)
+	val nullExprs = allVars map (nullGuard(state.varmap, _))
+	//val exprWithNull = allVars.foldLeft(exprs)((exprs,s) => nullGuard(exprs, r2rState.varmap, s))
+
+	R2RState(state.joins, state.varmap, state.exprs ++ filterExprs ++ nullExprs)
+      }
+    }
+  }
+
   def apply (db:DatabaseDesc, sparql:SparqlSelect, stem:StemURI, pk:PrimaryKey) : Select = {
     val SparqlSelect(attrs, triples) = sparql
 
@@ -252,8 +282,7 @@
       Set[PrimaryExpression]()
     )
 
-    /* Examine each triple, updating the compilation state. */
-    triples.triplepatterns.foreach(s => r2rState = bindOnPredicate(db, r2rState, s, pk, true))
+    r2rState = mapGraphPattern(db, r2rState, sparql.gp, pk, true)
 
     /* Select the attributes corresponding to the variables
      * in the SPARQL SELECT.  */
@@ -262,20 +291,11 @@
       NamedAttribute(varToAttribute(r2rState.varmap, vvar), AttrAlias(Name("A_" + vvar.s)))
     )
 
-    /* Add constraints for all the FILTERS */
-
-    val filterExprs:Set[PrimaryExpression] =
-      triples.filter.conjuncts.toSet map ((x:SparqlPrimaryExpression) => filter(r2rState.varmap, x))
-
-    val allVars:Set[Var] = triples.triplepatterns.foldLeft(Set[Var]())((x, y) => x ++ findVars(y))
-    val nullExprs = allVars map (nullGuard(r2rState.varmap, _))
-    //val exprWithNull = allVars.foldLeft(exprs)((exprs,s) => nullGuard(exprs, r2rState.varmap, s))
-
     /* Construct the generated query as an abstract syntax. */
     Select(
       AttributeList(attrlist),
       TableList(r2rState.joins),
-      Expression(r2rState.exprs ++ filterExprs ++ nullExprs)
+      Expression(r2rState.exprs)
 //      Expression(exprWithNull)
     )
   }
--- a/src/main/scala/SPARQL.scala	Sun Dec 27 15:05:58 2009 -0800
+++ b/src/main/scala/SPARQL.scala	Sun Dec 27 16:44:52 2009 -0800
@@ -11,14 +11,15 @@
 
 import MyParsers._
 
-case class SparqlSelect(attrs:SparqlAttributeList, triples:BasicGraphPattern)
+case class SparqlSelect(attrs:SparqlAttributeList, gp:GraphPattern)
 case class SparqlAttributeList(attributelist:List[Var])
 
-case class BasicGraphPattern(triplepatterns:List[TriplePattern], filter:SparqlExpression)
+sealed abstract class GraphPattern
+case class BasicGraphPattern(triplepatterns:List[TriplePattern], filter:SparqlExpression) extends GraphPattern
+case class GroupGraphPattern(gps:List[GraphPattern]) extends GraphPattern
+
 case class TriplePattern(s:S, p:P, o:O)
-
 case class ObjUri(stem:Stem, rel:Rel, attr:Attr, v:CellValue)
-
 case class CellValue(s:String)
 
 sealed abstract class S
@@ -57,7 +58,7 @@
 case class Sparql() extends JavaTokenParsers {
 
   def select:Parser[SparqlSelect] =
-    "SELECT" ~ attributelist ~ "{" ~ basicgraphpattern ~ "}" ^^ { case "SELECT"~a~"{"~t~"}" => SparqlSelect(a, t) }
+    "SELECT" ~ attributelist ~ "{" ~ graphpattern ~ "}" ^^ { case "SELECT"~a~"{"~t~"}" => SparqlSelect(a, t) }
 
   def filter:Parser[SparqlExpression] =
     "FILTER" ~ "(" ~ expression ~ ")" ^^ { case "FILTER"~"("~expression~")" => expression }
@@ -82,6 +83,16 @@
   def attributelist:Parser[SparqlAttributeList] =
     rep(varr) ^^ { SparqlAttributeList(_) }
 
+  def graphpattern:Parser[GraphPattern] = (
+      // "{"~graphpattern~"}" ^^ { case "{"~x~"}" => GroupGraphPattern(List(x)) }
+      groupgraphpattern ^^ { ggp => ggp }
+    | basicgraphpattern ^^ { bgp => bgp }
+  )
+
+  def groupgraphpattern:Parser[GraphPattern] = (
+      "{"~graphpattern~"}" ^^ { case "{"~x~"}" => GroupGraphPattern(List(x)) }
+  )
+
   def basicgraphpattern:Parser[BasicGraphPattern] =
     repsep(triplepattern, ".") ~ opt(filter) ^^ {
       case pats~filter =>
--- a/src/test/scala/SparqlTest.scala	Sun Dec 27 15:05:58 2009 -0800
+++ b/src/test/scala/SparqlTest.scala	Sun Dec 27 16:44:52 2009 -0800
@@ -162,13 +162,13 @@
     a.parseAll(a.select, e).get
   }
 
-//   test("parse a nested bgp") {
-//     val a = Sparql()
-//     val e = """
-// SELECT ?x { { ?x <p> ?y} }
-// """
-//     a.parseAll(a.select, e).get
-//   }
+  test("parse a nested bgp") {
+    val a = Sparql()
+    val e = """
+SELECT ?x { { ?x <p> ?y} }
+"""
+    a.parseAll(a.select, e).get
+  }
 
 //   test("parse a conjunction") {
 //     val a = Sparql()