--- a/src/main/scala/RDB2RDFMain.scala Thu Jan 28 16:07:12 2010 -0500
+++ b/src/main/scala/RDB2RDFMain.scala Thu Jan 28 21:49:59 2010 -0500
@@ -378,6 +378,61 @@
}
}
+ /* subselectVars: Promote variables in OPTIONAL or UNION subselects to the
+ * outer varmap/expressions.
+ * <outerState> could be <myState> -- spliting roles could make proofs easier?
+ */
+ def subselectVars(myState:R2RState, v:sparql.Var, optionalAlias:sql.RelAlias,
+ optionalCond:sql.RelationalExpression, outerState:R2RState,
+ optionalState:R2RState, isOpt:Boolean):R2RState = {
+ val varAliasAttr = sql.RelAliasAttribute(optionalAlias, sql.Attribute(attrAliasNameFromVar(v)))
+ if (myState.varmap.contains(v)) {
+ /* The variable has already been bound. */
+ val newMap:Map[sparql.Var, SQL2RDFValueMapper] = if (varToAttribute(myState.varmap, v) == varAliasAttr) {
+ /* Same var was bound earlier. */
+ Map(v -> { myState.varmap(v) match {
+ case IntMapper(binding) => IntMapper(addExpr(binding, varAliasAttr, optionalCond))
+ case StringMapper(binding) => StringMapper(addExpr(binding, varAliasAttr, optionalCond))
+ case DateMapper(binding) => DateMapper(addExpr(binding, varAliasAttr, optionalCond))
+ case RDFNoder(rel, binding) => RDFNoder(rel, addExpr(binding, varAliasAttr, optionalCond))
+ case RDFBNoder(rel, binding) => RDFBNoder(rel, addExpr(binding, varAliasAttr, optionalCond))
+ } } )
+ } else
+ Map()
+ val newConstraints =
+ if (varToAttribute(outerState.varmap, v) != varAliasAttr) {
+ /* Constraint against binding from earlier GP. */
+ val constraint = sql.RelationalExpressionEq(sql.PrimaryExpressionAttr(varAliasAttr),
+ sql.PrimaryExpressionAttr(varToAttribute(outerState.varmap, v)))
+ if (varToAttributeDisjoints(outerState.varmap, v).size > 0)
+ // (union0._DISJOINT_ != 0 OR union0.x=union1.x) AND (union1._DISJOINT_ != 2 OR union0.x=union1.x)
+ varToAttributeDisjoints(outerState.varmap, v) map ((d) =>
+ sql.ExprDisjunction({
+ if (isOpt) Set(d, constraint)
+ else Set(sql.ExprConjunction(Set(d, optionalCond)), constraint)
+ }))
+ else {
+ if (isOpt) Set(constraint)
+ else Set(sql.ExprDisjunction(Set(optionalCond, constraint)))
+ }
+ } else {
+ Set()
+ }
+ R2RState(myState.joins, myState.varmap ++ newMap, myState.exprs ++ newConstraints)
+ } else {
+ /* This variable is new to the outer context. */
+ val p = PartialBinding(Set(BindingConstraint(optionalCond, varAliasAttr)))
+ val mapper:SQL2RDFValueMapper = optionalState.varmap(v) match {
+ case IntMapper(_) => IntMapper(p)
+ case StringMapper(_) => StringMapper(p)
+ case DateMapper(_) => DateMapper(p)
+ case RDFNoder(rel, _) => RDFNoder(rel, p)
+ case RDFBNoder(rel, _) => RDFBNoder(rel, p)
+ }
+ R2RState(myState.joins, myState.varmap + (v -> mapper), myState.exprs)
+ }
+ }
+
def mapGraphPattern(db:sql.DatabaseDesc, state:R2RState, gp:sparql.GraphPattern, enforceForeignKeys:Boolean):R2RState = {
gp match {
case sparql.TableFilter(gp2:sparql.GraphPattern, expr:sparql.Expression) => {
@@ -459,49 +514,8 @@
*/
val disjointCond = sql.RelationalExpressionNe(sql.PrimaryExpressionAttr(sql.RelAliasAttribute(unionAlias, sql.Attribute(sql.Name("_DISJOINT_")))),
sql.PrimaryExpressionTyped(sql.Datatype.INTEGER,sql.Name("" + no)))
- val outerState2 = disjointVars.foldLeft(outerState)((myState, v) => {
- val varAliasAttr = sql.RelAliasAttribute(unionAlias, sql.Attribute(attrAliasNameFromVar(v)))
- if (myState.varmap.contains(v)) {
- /* The variable has already been bound. */
- val newMap:Map[sparql.Var, SQL2RDFValueMapper] = if (varToAttribute(myState.varmap, v) == varAliasAttr) {
- /* Same var was bound in an earlier disjoint. */
- Map(v -> { myState.varmap(v) match {
- case IntMapper(binding) => IntMapper(addExpr(binding, varAliasAttr, disjointCond))
- case StringMapper(binding) => StringMapper(addExpr(binding, varAliasAttr, disjointCond))
- case DateMapper(binding) => DateMapper(addExpr(binding, varAliasAttr, disjointCond))
- case RDFNoder(rel, binding) => RDFNoder(rel, addExpr(binding, varAliasAttr, disjointCond))
- case RDFBNoder(rel, binding) => RDFBNoder(rel, addExpr(binding, varAliasAttr, disjointCond))
- } } )
- } else
- Map()
- val newConstraints =
- if (varToAttribute(outerState.varmap, v) != varAliasAttr) {
- /* Constraint against binding from earlier GP. */
- val constraint = sql.RelationalExpressionEq(sql.PrimaryExpressionAttr(varAliasAttr),
- sql.PrimaryExpressionAttr(varToAttribute(outerState.varmap, v)))
- if (varToAttributeDisjoints(outerState.varmap, v).size > 0)
- // (union0._DISJOINT_ != 0 OR union0.x=union1.x) AND (union1._DISJOINT_ != 2 OR union0.x=union1.x)
- varToAttributeDisjoints(outerState.varmap, v) map ((d) =>
- sql.ExprDisjunction(Set(sql.ExprConjunction(Set(d, disjointCond)), constraint)))
- else
- Set(sql.ExprDisjunction(Set(disjointCond, constraint)))
- } else {
- Set()
- }
- R2RState(myState.joins, myState.varmap ++ newMap, myState.exprs ++ newConstraints)
- } else {
- /* This variable is new to the outer context. */
- val p = PartialBinding(Set(BindingConstraint(disjointCond, varAliasAttr)))
- val mapper:SQL2RDFValueMapper = disjointState.varmap(v) match {
- case IntMapper(_) => IntMapper(p)
- case StringMapper(_) => StringMapper(p)
- case DateMapper(_) => DateMapper(p)
- case RDFNoder(rel, _) => RDFNoder(rel, p)
- case RDFBNoder(rel, _) => RDFBNoder(rel, p)
- }
- R2RState(myState.joins, myState.varmap + (v -> mapper), myState.exprs)
- }
- })
+ val outerState2 = disjointVars.foldLeft(outerState)((myState, v) =>
+ subselectVars(myState, v, unionAlias, disjointCond, outerState, disjointState, false))
(outerState2, no+1)
})
val subselect = sql.Subselect(sql.Union(subselects))
@@ -563,48 +577,13 @@
/* Bind variables to the attributes projected from the subselect; handle
* corefs (equivalence with earlier bindings).
*/
- val outerState2 = optionalVars.foldLeft(R2RState(state_postLeadingTable.joins,
- state_postLeadingTable.varmap,
- Set[sql.Expression]()))((myState, v) => {
- val varAliasAttr = sql.RelAliasAttribute(leftJoinAlias, sql.Attribute(attrAliasNameFromVar(v)))
- if (myState.varmap.contains(v)) {
- /* The variable has already been bound. */
- val newMap:Map[sparql.Var, SQL2RDFValueMapper] = if (varToAttribute(myState.varmap, v) == varAliasAttr) {
- /* Same var was bound in an earlier optional. */
- // myState
- Map(v -> { myState.varmap(v) match {
- case IntMapper(binding) => IntMapper(addExpr(binding, varAliasAttr, optionalCond))
- case StringMapper(binding) => StringMapper(addExpr(binding, varAliasAttr, optionalCond))
- case DateMapper(binding) => DateMapper(addExpr(binding, varAliasAttr, optionalCond))
- case RDFNoder(rel, binding) => RDFNoder(rel, addExpr(binding, varAliasAttr, optionalCond))
- case RDFBNoder(rel, binding) => RDFBNoder(rel, addExpr(binding, varAliasAttr, optionalCond))
- } } )
- } else
- Map()
- val newConstraints = {
- /* Constraint against binding from earlier GP. */
- val constraint = sql.RelationalExpressionEq(sql.PrimaryExpressionAttr(varAliasAttr),
- sql.PrimaryExpressionAttr(varToAttribute(state_postLeadingTable.varmap, v)))
- if (varToAttributeDisjoints(state_postLeadingTable.varmap, v).size > 0)
- // (leftJoin0._DISJOINT_ IS NOT NULL AND leftJoin1._DISJOINT_ IS NOT NULL) OR leftJoin0.x=leftJoin1.x
- varToAttributeDisjoints(state_postLeadingTable.varmap, v) map ((d) => sql.ExprDisjunction(Set(d, constraint)))
- else
- Set(constraint)
- }
- R2RState(myState.joins, myState.varmap ++ newMap, myState.exprs ++ newConstraints)
- } else {
- /* This variable is new to the outer context. */
- val p = PartialBinding(Set(BindingConstraint(optionalCond, varAliasAttr)))
- val mapper:SQL2RDFValueMapper = optionalState.varmap(v) match {
- case IntMapper(binding) => IntMapper(p)
- case StringMapper(binding) => StringMapper(p)
- case DateMapper(binding) => DateMapper(p)
- case RDFNoder(rel, binding) => RDFNoder(rel, p)
- case RDFBNoder(rel, binding) => RDFBNoder(rel, p)
- }
- R2RState(myState.joins, myState.varmap + (v -> mapper), myState.exprs)
- }
- })
+ val outerState2 =
+ optionalVars.foldLeft(
+ R2RState(state_postLeadingTable.joins,
+ state_postLeadingTable.varmap,
+ Set[sql.Expression]()))((myState, v) =>
+ subselectVars(myState, v, leftJoinAlias, optionalCond,
+ state_postLeadingTable, optionalState, true))
/* The final state includes the subselect as a join, the variables bound
* to subselect projection, and no new expresssions. The expressions