bnode generator for no primary key bnode-generator-for-no-primary-key
authorEric Prud'hommeaux <bertails@w3.org>
Sun, 27 Dec 2009 00:58:09 -0800
branchbnode-generator-for-no-primary-key
changeset 70 7f903d5a115c
parent 69 ed5415596dfe
child 71 7591dc0347b8
bnode generator for no primary key
src/main/scala/RDB2RDFMain.scala
src/test/scala/RDB2RDFTest.scala
--- a/src/main/scala/RDB2RDFMain.scala	Sun Dec 20 09:05:28 2009 -0500
+++ b/src/main/scala/RDB2RDFMain.scala	Sun Dec 27 00:58:09 2009 -0800
@@ -83,7 +83,7 @@
    * type String -> RDFStringConstructor // adds ^^xsd:string
    * type primary key -> RDFNodeConstructor // prefixes with stemURL + relation + attribute  and adds #record
    * */
-  def varConstraint(state:R2RState, constrainMe:RelAliasAttribute, v:Var, db:DatabaseDesc, rel:Relation):R2RState = {
+  def varConstraint(state:R2RState, db:DatabaseDesc, v:Var, rel:Relation, alias:RelAlias, optAttr:Option[Attribute]):R2RState = {
     /* e.g.                                 Employee      _emp.id            
     **                                      Employee      _emp.lastName      
     **                                      Employee      _emp.manager       
@@ -91,30 +91,42 @@
     val reldesc = db.relationdescs(rel)
     if (state.varmap.contains(v)) {
       /* The variable has already been bound. */
-      if (varToAttribute(state.varmap, v) == constrainMe)
-	/* Don't bother stipulating that foo.bar=foo.bar . */
-	state
-      else
-	/* Constraint against the initial binding for this variable. */
-	R2RState(state.joins, state.varmap, state.exprs + PrimaryExpressionEq(varToAttribute(state.varmap, v), RValueAttr(constrainMe)))
+      state.varmap(v) match {
+	case RDFBNoder(relation, relalias) => {
+	  // println(v + " bound to BNode[" + relation + "] and f(" + alias + ", " + optAttr + ")" )
+	  state
+	}
+	case _ => {
+	  // println(v + " bound to " + varToAttribute(state.varmap, v) + " and f(" + alias + ", " + optAttr + ")" )
+	  if (varToAttribute(state.varmap, v) == RelAliasAttribute(alias, optAttr.get))
+	    /* Don't bother stipulating that foo.bar=foo.bar . */
+	    state
+	  else
+	    /* Constraint against the initial binding for this variable. */
+	    R2RState(state.joins, state.varmap, state.exprs + PrimaryExpressionEq(varToAttribute(state.varmap, v), RValueAttr(RelAliasAttribute(alias, optAttr.get))))
+	}
+      }
     } else {
       /* This is a new variable. */
-      val binding = reldesc.primarykey match {
-	case Some(Attribute(constrainMe.attribute.n)) => 
-	  RDFNoder(rel, constrainMe)
+      val binding:SQL2RDFValueMapper = optAttr match {
+	case Some(attr) => {
+	  reldesc.primarykey match {
+	    case Some(Attribute(attr.n)) => 
+	      RDFNoder(rel, RelAliasAttribute(alias, attr))
+	    case _ => {
+	      reldesc.attributes(RelAliasAttribute(alias, attr).attribute) match {
+		case ForeignKey(fkrel, fkattr) =>
+		  RDFNoder(rel, RelAliasAttribute(alias, attr))
+		case Value(SQLDatatype("String")) =>
+		  StringMapper(RelAliasAttribute(alias, attr))
+		case Value(SQLDatatype("Int")) =>
+		  IntMapper(RelAliasAttribute(alias, attr))
+	      }
+	    }
+	  }
+	}
 	case _ => {
-	  if (reldesc.attributes.contains(constrainMe.attribute)) {
-	    reldesc.attributes(constrainMe.attribute) match {
-	      case ForeignKey(fkrel, fkattr) =>
-		RDFNoder(rel, constrainMe)
-	      case Value(SQLDatatype("String")) =>
-		StringMapper(constrainMe)
-	      case Value(SQLDatatype("Int")) =>
-		IntMapper(constrainMe)
-	    }
-	  } else {
-	    RDFBNoder(rel, constrainMe)
-	  }
+	  RDFBNoder(rel, RelAliasAttribute(alias, Attribute(Name("_no_such_attribute"))))
 	}
       }
       R2RState(state.joins, state.varmap + (v -> binding), state.exprs)
@@ -145,11 +157,14 @@
 	val relalias = relAliasFromS(s)
 
 	/* Attributes that come from the subject: */
-	val subjattr = RelAliasAttribute(relalias, pk.attr)
 	val objattr = RelAliasAttribute(relalias, attr)
 	state = s match {
-	  case SUri(u) => uriConstraint(state, subjattr, u)
-	  case SVar(v) => varConstraint(state, subjattr, v, db, rel)
+	  case SUri(u) => uriConstraint(state, RelAliasAttribute(relalias, pk.attr), u)
+	  case SVar(v) => varConstraint(state, db, v, rel, relalias, 
+					db.relationdescs(rel).primarykey match {
+					  case Some(attr) => Some(attr)
+					  case _ => None
+					})
 	}
 	state = R2RState(state.joins + AliasedResource(rel,relalias), state.varmap, state.exprs)
 
@@ -174,7 +189,7 @@
 	state = o match {
 	  case OLit(l) => literalConstraint(state, targetattr, l, dt)
 	  case OUri(u) => uriConstraint    (state, targetattr, u)
-	  case OVar(v) => varConstraint    (state, targetattr, v, db, targetrel)
+	  case OVar(v) => varConstraint    (state, db, v, targetrel, targetattr.relalias, Some(targetattr.attribute))
 	}
       }
 
@@ -200,7 +215,7 @@
       case StringMapper(relalias) => relalias
       case IntMapper(relalias) => relalias
       case RDFNoder(relation, relalias) => relalias
-      case RDFBNoder(relation, relalias) => relalias
+      case RDFBNoder(relation, relalias) => { error("error: " + relalias) }
     }
   }
 
@@ -230,15 +245,20 @@
     }
   }
 
-  def nullGuard(varmap:Map[Var, SQL2RDFValueMapper], vvar:Var):PrimaryExpression = {
+  def nullGuard(varmap:Map[Var, SQL2RDFValueMapper], vvar:Var):Set[PrimaryExpression] = {
     val mapper:SQL2RDFValueMapper = varmap(vvar)
-    val aattr = mapper match {
-      case StringMapper(relalias) => relalias
-      case IntMapper(relalias) => relalias
-      case RDFNoder(relation, relalias) => relalias
-      case RDFBNoder(relation, relalias) => relalias
+    mapper match {
+      case RDFBNoder(relation, relalias) => Set()
+      case _ => {
+	val aattr = mapper match {
+	  case StringMapper(relalias) => relalias
+	  case IntMapper(relalias) => relalias
+	  case RDFNoder(relation, relalias) => relalias
+	  case RDFBNoder(relation, relalias) => error("program flow")
+	}
+	Set(PrimaryExpressionNotNull(aattr))
+      }
     }
-    PrimaryExpressionNotNull(aattr)
   }
 
   def apply (db:DatabaseDesc, sparql:SparqlSelect, stem:StemURI, pk:PrimaryKey) : Select = {
@@ -267,8 +287,9 @@
       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))
+    // val nullExprs = allVars map (nullGuard(r2rState.varmap, _))
+    val nullExprs:Set[PrimaryExpression] = allVars.foldLeft(Set[PrimaryExpression]())((set, vvar) => set ++ nullGuard(r2rState.varmap, vvar))
 
     /* Construct the generated query as an abstract syntax. */
     Select(
--- a/src/test/scala/RDB2RDFTest.scala	Sun Dec 20 09:05:28 2009 -0500
+++ b/src/test/scala/RDB2RDFTest.scala	Sun Dec 27 00:58:09 2009 -0800
@@ -193,9 +193,7 @@
        INNER JOIN Employee AS R_grandManager
  WHERE R_emp.id=R_lower.manages AND R_manager.id=R_lower.manager AND R_manager.id=R_upper.manages AND R_grandManager.id=R_upper.manager AND 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
  AND R_emp.id IS NOT NULL
- AND R_lower.id IS NOT NULL
  AND R_manager.id IS NOT NULL
- AND R_upper.id IS NOT NULL
  AND R_grandManager.id IS NOT NULL
  AND R_emp.birthday IS NOT NULL
  AND R_manager.birthday IS NOT NULL