~ refactored nested subselects in UNIONs
authorEric Prud'hommeaux <eric@w3.org>
Thu, 20 May 2010 12:55:21 +0200
changeset 197 88b71c4aa8d8
parent 196 df3c379243a2
child 198 c86f39305813
~ refactored nested subselects in UNIONs
src/main/scala/SparqlToSql.scala
--- a/src/main/scala/SparqlToSql.scala	Thu May 20 11:55:05 2010 +0200
+++ b/src/main/scala/SparqlToSql.scala	Thu May 20 12:55:21 2010 +0200
@@ -897,13 +897,26 @@
 	  mySet ++ disjoint.findVars).toList // all variables nested in the disjoints.
 
 	/**
-	 * Map the disjoints to subselects.
+	 * Map the list of disjoints to a list of nested R2RStates, nested variable lists, and unique SQL constants identifying that disjoint.
 	 * Non-Functional var <code>number</code> is used for projecting unique
 	 * constants to indicate which disjoint produced a tuple.
 	 */
 	var number = 0
-	val subselects = disjoints.foldLeft(Set[sql.Select]())((subselects, disjoint) => {
+	val nestedStates = disjoints.map(disjoint => {
 	  val disjointState = mapGraphPattern(db, emptyState, disjoint, enforceForeignKeys)
+	  val disjointVars = disjoint.findVars
+	  val uniqueConst = sql.PrimaryExpressionTyped(sql.Datatype.INTEGER,sql.Name("" + number))
+	  number = number + 1 // non-functional, but clearer than wrapping as a parameter in a foldLeft
+	  (disjointState, disjointVars, uniqueConst)
+	})
+
+	/**
+	 * Map the list of nested R2RStates to a set of subselects.
+	 * <code>uniqueConst</code> is used for projecting a value
+	 * to indicate which disjoint produced a tuple.
+	 */
+	val subselects = nestedStates.foldLeft(Set[sql.Select]())((subselects, state) => {
+	  val (disjointState, disjointVars, uniqueConst) = state
 	  /**
 	   * Select a constant as _DISJOINT_ so later constraints can be
 	   * sensitive to whether a variable was bound.
@@ -914,7 +927,7 @@
 	   * coreference constraints against ?v2 should only be enforced for
 	   * tuples from the right side of this union.
 	   */
-	  val pathNo = sql.NamedAttribute(sql.PrimaryExpressionTyped(sql.Datatype.INTEGER,sql.Name("" + number)),
+	  val pathNo = sql.NamedAttribute(uniqueConst,
 					  sql.AttrAlias(sql.Name("_DISJOINT_")))
 
 	  val attrlist:Set[sql.NamedAttribute] = unionVars.foldLeft(Set(pathNo))((attrs, v) => {
@@ -931,24 +944,21 @@
 	      case _ => Some(sql.ExprConjunction(disjointState.exprs))
 	    }
 	  )
-	  number = number + 1 // non-functional, but clearer than wrapping as a parameter in a foldLeft
 	  subselects + subselect
 	})
 
 	/**
 	 * Connect the variables projected from the nested selects into the outer variable bindings and constraints.
 	 * <code>state2</code> will have no additional tables in the TableList.
-	 * <code>number</code> is again used for projecting unique
-	 * constants to indicate which disjoint produced a tuple.
+	 * <code>uniqueConst</code> is used this time to constraint coreferences between the
+	 * subselects and the outer context.
 	 */
-	number = 0
-	val state2 = disjoints.foldLeft(state)((outerState, disjoint) => {
-	  val disjointState = mapGraphPattern(db, emptyState, disjoint, enforceForeignKeys)
-	  val disjointVars = disjoint.findVars
+	val state2 = nestedStates.foldLeft(state)((outerState, state) => {
+	  val (disjointState, disjointVars, uniqueConst) = state
 
 	  /** Create a condition to test if this disjoint was matched. */
 	  val disjointCond = sql.RelationalExpressionNe(sql.PrimaryExpressionAttr(sql.RelVarAttr(unionAlias, sql.Attribute(sql.Name("_DISJOINT_")))),
-							sql.PrimaryExpressionTyped(sql.Datatype.INTEGER,sql.Name("" + number)))
+							uniqueConst)
 	  val outerState2 = disjointVars.foldLeft(outerState)((myState, v) =>
 	      subselectVars(myState, sparql.VarAssignable(v), unionAlias, disjointCond, outerState.varmap, disjointState.varmap, false))
 	  number = number + 1 // non-functional, but clearer than wrapping as a parameter in a foldLeft