transform filter1
authorEric Prud'hommeaux <bertails@w3.org>
Wed, 16 Dec 2009 12:52:23 -0500
changeset 49 6663b4a69f56
parent 48 9191563eff96
child 50 9df8a5aabf5c
transform filter1
src/main/scala/RDB2RDFMain.scala
src/test/scala/RDB2RDFTest.scala
--- a/src/main/scala/RDB2RDFMain.scala	Tue Dec 15 21:08:44 2009 -0500
+++ b/src/main/scala/RDB2RDFMain.scala	Wed Dec 16 12:52:23 2009 -0500
@@ -130,22 +130,21 @@
 	val sconstraint:Option[Expression] = s match {
 	  case SUri(u) => {
 	    uriConstraint(subjattr, u)
-	    // joins = joins ::: List(Join(RelAsRelAlias(Relation(Name("Employee")),RelAlias(Name("R_emp"))),None))
 	    None
 	  }
 	  case SVar(v) => {
 	    val binding:SQL2RDFValueMapper = varConstraint(subjattr, v, db, rel)
 	    varmap += v -> binding
-	    // println(toString(binding))
 	    None
 	  }
 	}
-	joined contains(relalias) match {
+	val sjoin = joined contains(relalias) match {
 	  case false => {
-	    joins = joins ::: List(Join(RelAsRelAlias(rel,relalias), sconstraint))
+	    //joins = joins ::: List(Join(RelAsRelAlias(rel,relalias), sconstraint))
 	    joined = joined + relalias
+	    Some(RelAsRelAlias(rel,relalias))
 	  }
-	  case true => null
+	  case true => None
 	}
 	val target = db.relationdescs(rel).attributes(attr) match {
 	  case ForeignKey(fkrel, fkattr) => {
@@ -176,10 +175,21 @@
 
 	    joined contains(oRelAlias) match {
 	      case false => {
+
+		sjoin match { // complex dance to keep joins ordered -- ouch!
+		  case Some(x) => joins = joins ::: List(Join(x, sconstraint))
+		  case None => 
+		}
+
 		joins = joins ::: List(Join(RelAsRelAlias(fkrel,oRelAlias), Some(Expression(conjuncts))))
 		joined = joined + oRelAlias
 	      }
-	      case true => null
+	      case true => {
+		sjoin match {
+		  case Some(x) => joins = joins ::: List(Join(x, Some(Expression(conjuncts))))
+		  case None => 
+		}
+	      }
 	    }
 	  }
 	  case Value(dt) => {
@@ -196,6 +206,11 @@
 		varmap += v -> binding
 	      }
 	    }
+	    sjoin match {
+	      case Some(x) => joins = joins ::: List(Join(x, sconstraint))
+	      case None => 
+	    }
+
 	  }
 	}
 
@@ -205,18 +220,45 @@
     R2RState(joined, allVars, inConstraint, joins, varmap, exprs)
   }
 
-  def project(varmap:Map[Var, SQL2RDFValueMapper], vvar:Var):NamedAttribute = {
-    val mapper:SQL2RDFValueMapper = varmap(vvar)
-    val aattr = mapper match {
+  def varToAttribute(varmap:Map[Var, SQL2RDFValueMapper], vvar:Var):RelAliasAttribute = {
+    varmap(vvar) match {
       case StringMapper(relalias) => relalias
       case IntMapper(relalias) => relalias
       case RDFNoder(relation, relalias) => relalias
     }
-    NamedAttribute(aattr, AttrAlias(Name("A_" + vvar.s)))
   }
 
-  def nullGuard(notNulls:List[PrimaryExpression], inConstraint:Set[Var], varmap:Map[Var, SQL2RDFValueMapper], vvar:Var):List[PrimaryExpression] = {
-    var ret = notNulls
+  def filter(exprsP:List[PrimaryExpression], inConstraintP:Set[Var], varmap:Map[Var, SQL2RDFValueMapper], f:SparqlPrimaryExpression):Tuple2[List[PrimaryExpression], Set[Var]] = {
+    var exprs = exprsP
+    var inConstraint = inConstraintP
+    // var f = SparqlPrimaryExpressionEq
+    // val e:SparqlPrimaryExpression = f(SparqlTermExpression(Term(TermVar(Var("a")))), SparqlTermExpression(Term(TermVar(Var("a")))))
+    val tup:Tuple3[Term, Term, String] = f match {
+      case SparqlPrimaryExpressionEq(l, r) => (l.term, r.term, "==")
+      case SparqlPrimaryExpressionLt(l, r) => (l.term, r.term, "<")
+      }
+    val l = tup._1 match {
+      case TermUri(obj) => null // :ObjUri
+      case TermVar(v) => { // :Var
+	inConstraint += v
+	varToAttribute(varmap, v)
+      }
+      case TermLit(lit) => null // :SparqlLiteral
+    } 
+    val r = tup._2 match {
+      case TermUri(obj) => null // :ObjUri
+      case TermVar(v) => { // :Var
+	inConstraint += v
+	RValueAttr(varToAttribute(varmap, v))
+      }
+      case TermLit(lit) => null // :SparqlLiteral => RValueTyped(SQLDatatype, lit.n)
+    }
+    exprs = exprs ::: List(tup._3 match { case "==" => PrimaryExpressionEq(l, r) case _ => PrimaryExpressionLt(l, r) })
+    (exprs, inConstraint)
+  }
+
+  def nullGuard(exprs:List[PrimaryExpression], inConstraint:Set[Var], varmap:Map[Var, SQL2RDFValueMapper], vvar:Var):List[PrimaryExpression] = {
+    var ret = exprs
     inConstraint contains(vvar) match {
       case false => {
 	val mapper:SQL2RDFValueMapper = varmap(vvar)
@@ -227,7 +269,7 @@
 	}
 	ret = ret ::: List(PrimaryExpressionNotNull(aattr))
       }
-      case true => null
+      case true => 
     }
     ret
   }
@@ -251,15 +293,29 @@
     /* Select the attributes corresponding to the variables
      * in the SPARQL SELECT.  */
     var attrlist:List[NamedAttribute] = List()
-    attrs.attributelist.foreach(s => attrlist = attrlist ::: List(project(r2rState.varmap, s)))
+    attrs.attributelist.foreach(vvar => attrlist = attrlist ::: List(
+      NamedAttribute(varToAttribute(r2rState.varmap, vvar), AttrAlias(Name("A_" + vvar.s)))
+    ))
+
+    var exprs:List[PrimaryExpression] = r2rState.exprs
+    var inConstraint:Set[Var] = r2rState.inConstraint
+
+    /* Add constraints for all the FILTERS */
+    triples.filter match {
+      case Some(x) => x.conjuncts.foreach(f => {
+	val pair = filter(exprs, inConstraint, r2rState.varmap, f)
+	exprs = pair._1
+	inConstraint = pair._2
+      })
+      case None => 
+    }
 
     /* Add null guards for attributes associated with variables which
      * are not optional and have not been used in constraints. */
-    var notNulls:List[PrimaryExpression] = r2rState.exprs
-    r2rState.allVars.foreach(s => notNulls = nullGuard(notNulls, r2rState.inConstraint, r2rState.varmap, s))
-    val where = notNulls.size match {
+    r2rState.allVars.foreach(s => exprs = nullGuard(exprs, inConstraint, r2rState.varmap, s))
+    val where = exprs.size match {
       case 0 => None
-      case _ => Some(Expression(notNulls))
+      case _ => Some(Expression(exprs))
     }
 
     /* Construct the generated query as an abstract syntax. */
--- a/src/test/scala/RDB2RDFTest.scala	Tue Dec 15 21:08:44 2009 -0500
+++ b/src/test/scala/RDB2RDFTest.scala	Wed Dec 16 12:52:23 2009 -0500
@@ -144,13 +144,11 @@
     val sqlSelect = sqlParser.parseAll(sqlParser.select, """
 SELECT R_emp.lastName AS A_empName, R_grandManager.lastName AS A_grandManagName
   FROM Employee AS R_emp
-       INNER JOIN Manage AS R_lower ON R_lower.manages=R_emp.id
+       INNER JOIN Manage AS R_lower ON R_emp.id=R_lower.manages
        INNER JOIN Employee AS R_manager ON R_manager.id=R_lower.manager
-                                         AND R_manager.birthday < R_emp.birthday
-       INNER JOIN Manage AS R_upper ON R_upper.manages=R_manager.id
+       INNER JOIN Manage AS R_upper ON R_manager.id=R_upper.manages
        INNER JOIN Employee AS R_grandManager ON R_grandManager.id=R_upper.manager
-                                         AND R_grandManager.birthday < R_manager.birthday
- WHERE R_emp.lastName IS NOT NULL AND R_grandManager.lastName IS NOT NULL
+ WHERE R_manager.birthday < R_emp.birthday AND R_grandManager.birthday < R_manager.birthday AND R_emp.lastName IS NOT NULL AND R_grandManager.lastName IS NOT NULL
 """).get
     assert(RDB2RDF(db2, sparqlSelect, StemURI("http://hr.example/DB/"), PrimaryKey(Attribute(Name("id")))) === sqlSelect)
   }