--- a/src/main/scala/SparqlToSql.scala Thu May 13 11:45:03 2010 -0400
+++ b/src/main/scala/SparqlToSql.scala Thu May 13 14:36:55 2010 -0400
@@ -390,57 +390,88 @@
/** additional constraint, e.g. R_empid18.empid=18. */
uriConstraint(stateP, sql.RelVarAttr(relvar, db.relationdescs(rel).primarykey.get), parseObjectURI(u))
case sparql.TermVar(v) =>
+ /** assignable binding for novel vars, new constraint for previously bound vars. */
try {
varConstraint(stateP, relvar, db.relationdescs(rel).primarykey, sparql.VarAssignable(v), db, rel)
} catch {
case e:java.util.NoSuchElementException =>
- /** Attribute not found in database description. */
+ /** Tell user that the relation.attribute encoded in the subject was not found in the database description. */
throw new Exception("error processing { " + s + " " + p + " " + o + " } :db.relationdescs(" + rel + ") not found in " + db)
}
- case sparql.TermBNode(b) => try { varConstraint(stateP, relvar, db.relationdescs(rel).primarykey, sparql.BNodeAssignable(b), db, rel) } catch {
- case e:java.util.NoSuchElementException =>
- throw new Exception("error processing { " + s + " " + p + " " + o + " } :db.relationdescs(" + rel + ") not found in " + db)
- }
+ case sparql.TermBNode(b) =>
+ /** assignable binding for novel bnodes, new constraint for previously bound bnodes. */
+ try {
+ varConstraint(stateP, relvar, db.relationdescs(rel).primarykey, sparql.BNodeAssignable(b), db, rel)
+ } catch {
+ case e:java.util.NoSuchElementException =>
+ throw new Exception("error processing { " + s + " " + p + " " + o + " } :db.relationdescs(" + rel + ") not found in " + db)
+ }
case _ => error("illegal SPARQL subject: " + s)
}
+
+ /** Join rel (relation dictated by predicate) AS relvar (alias dicated by subject).
+ * may be redundant as R2RState's joins are a set */
val state_subjJoin = R2RState(state_postSubj.joins + sql.InnerJoin(sql.AliasedResource(rel,relvar), None), state_postSubj.varmap, state_postSubj.exprs)
try { db.relationdescs(rel).attributes(attr) } catch {
+ /** Tell user that the queried attribute was not found in the database description. */
case e:java.util.NoSuchElementException =>
throw new Exception("error processing { " + s + " " + p + " " + o + " } :db.relationdescs(" + rel + ").attributes(" + attr + ") not found in " + db)
}
+
+ /**
+ * fkrel.fkattr (e.g. Employee.manager) may be a foreign key.
+ * Calculate final relvarattr and relation.
+ */
val (targetattr:sql.RelVarAttr, targetrel, dt, state_fkeys:R2RState) = db.relationdescs(rel).attributes(attr) match {
case sql.ForeignKey(fkrel, fkattr) => {
try { db.relationdescs(fkrel).attributes(fkattr) } catch {
+ /** Foreign key relation.attribute was not found in the database description. */
case e:java.util.NoSuchElementException =>
throw new Exception("db.relationdescs(" + fkrel + ").attributes(" + fkattr + ") not found in " + db)
}
val fkdt = db.relationdescs(fkrel).attributes(fkattr) match {
+ /** Foreign key to something which is a foreign key. May have use
+ * cases, but signal error until we figure out that they are. */
case sql.ForeignKey(dfkrel, dfkattr) => error("foreign key " + rel.n + "." + attr.n +
"->" + fkrel.n + "." + fkattr.n +
"->" + dfkrel.n + "." + dfkattr.n)
case sql.Value(x) => x
}
if (enforceForeignKeys) {
+ /**
+ * Create an extra join on the foreign key relvar. For instance,
+ * <code>?task1 <http://hr.example/DB/TaskAssignments#employee> ?who</code>
+ * where TaskAssignments.employee is a foreign key to Employee.empid
+ * will join Employee AS R_who, constrain R_who.empid=R_task1.employee
+ * and bind targetattr:R_who.empid. targetrel:Employee .
+ */
val oRelVar = relVarFromTerm(o)
val fkaliasattr = sql.RelVarAttr(oRelVar, fkattr)
val state_t = R2RState(state_subjJoin.joins + sql.InnerJoin(sql.AliasedResource(fkrel,oRelVar), None),
state_subjJoin.varmap,
state_subjJoin.exprs + sql.RelationalExpressionEq(sql.PrimaryExpressionAttr(fkaliasattr),
sql.PrimaryExpressionAttr(objattr)))
-
+ //println("enforceFKs: <code>"+s+" "+p+" "+o+"</code> where "+rel+"."+attr+" is a foreign key to "+fkrel+"."+fkattr+" will join "+fkrel+" AS "+oRelVar+", constrain "+fkaliasattr+"="+objattr+" and bind targetattr:=" + fkaliasattr + ". targetrel:=" + fkrel + " (instead of " + objattr + ", " + rel + ").")
(fkaliasattr, fkrel, fkdt, state_t)
} else {
+ /**
+ * We're not enforcing foreign keys, so just bind
+ * targetattr:=R_task1.employee, targetrel:=TaskAssignments.
+ */
(objattr, rel, fkdt, state_subjJoin)
}
}
- case sql.Value(dt) => (objattr, rel, dt, state_subjJoin)
+ case sql.Value(dt) =>
+ /** not a foreign key, so use the relvarattr and relation calculated
+ * from the predicate. */
+ (objattr, rel, dt, state_subjJoin)
}
o match {
case sparql.TermLit(l) => literalConstraint(state_fkeys, targetattr, l, dt)
case sparql.TermUri(u) => uriConstraint (state_fkeys, targetattr, parseObjectURI(u))
case sparql.TermVar(v) => varConstraint (state_fkeys, targetattr.relvar, Some(targetattr.attribute), sparql.VarAssignable(v), db, targetrel)
- case sparql.TermBNode(b) => varConstraint (state_fkeys, targetattr.relvar, Some(targetattr.attribute), sparql.BNodeAssignable(b), db, targetrel)
+ case sparql.TermBNode(b) => varConstraint (state_fkeys, targetattr.relvar, Some(targetattr.attribute), sparql.BNodeAssignable(b), db, targetrel)
}
}
case _ => error("illegal SPARQL predicate: " + p)