Author: andy Date: Tue Oct 29 13:41:00 2013 New Revision: 1536710 URL: http://svn.apache.org/r1536710 Log: JENA-577 : Rewrite merging bindings when an OpProject is in the middel of an execution (sub-SELECT).
Added: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProjectMerge.java - copied, changed from r1536659, jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProject2.java Removed: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProject2.java Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProject.java jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectBase.java jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectNamed.java jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingUtils.java jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/main/OpExecutor.java Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProject.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProject.java?rev=1536710&r1=1536709&r2=1536710&view=diff ============================================================================== --- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProject.java (original) +++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProject.java Tue Oct 29 13:41:00 2013 @@ -16,30 +16,23 @@ * limitations under the License. */ -package com.hp.hpl.jena.sparql.engine.binding; +package com.hp.hpl.jena.sparql.engine.binding ; import java.util.Collection ; import com.hp.hpl.jena.sparql.core.Var ; -public class BindingProject extends BindingProjectBase -{ - final Collection<Var> projectionVars ; - - public BindingProject(Collection<Var> vars, Binding bind) - { - this(vars, bind, null) ; - } +/** Project a binding, given a specific collection of visible variables */ +public class BindingProject extends BindingProjectBase { + final Collection<Var> projectionVars ; - public BindingProject(Collection<Var> vars, Binding bind, Binding parent) - { - super(bind, parent) ; + public BindingProject(Collection<Var> vars, Binding bind) { + super(bind) ; this.projectionVars = vars ; } @Override - protected boolean accept(Var var) - { + protected boolean accept(Var var) { return projectionVars.contains(var) ; } } Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectBase.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectBase.java?rev=1536710&r1=1536709&r2=1536710&view=diff ============================================================================== --- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectBase.java (original) +++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectBase.java Tue Oct 29 13:41:00 2013 @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.hp.hpl.jena.sparql.engine.binding; +package com.hp.hpl.jena.sparql.engine.binding ; import java.util.ArrayList ; import java.util.Iterator ; @@ -25,60 +25,43 @@ import java.util.List ; import com.hp.hpl.jena.graph.Node ; import com.hp.hpl.jena.sparql.core.Var ; -public abstract class BindingProjectBase extends BindingBase -{ - private Binding binding ; - private List<Var> actualVars = null ; - - public BindingProjectBase(Binding bind) - { - this(bind, null) ; - } - - public BindingProjectBase(Binding bind, Binding parent) - { - super(parent) ; +/** Common framework for projection; + * the projection policy is provided by + * abstract method {@linkplain #accept(Var)} + */ +public abstract class BindingProjectBase extends BindingBase { + private List<Var> actualVars = null ; + private final Binding binding ; + + public BindingProjectBase(Binding bind) { + super(null) ; binding = bind ; } -// @Override -// protected void add1(Var var, Node node) -// { throw new UnsupportedOperationException("BindingProject.add1") ; } -// -// @Override -// protected void checkAdd1(Var var, Node node) -// {} + protected abstract boolean accept(Var var) ; - protected abstract boolean accept(Var var) ; - @Override - protected boolean contains1(Var var) - { + protected boolean contains1(Var var) { return accept(var) && binding.contains(var) ; } @Override - protected Node get1(Var var) - { - if ( ! accept(var) ) - return null ; + protected Node get1(Var var) { + if ( !accept(var) ) + return null ; return binding.get(var) ; } @Override - protected Iterator<Var> vars1() - { + protected Iterator<Var> vars1() { return actualVars().iterator() ; } - private List<Var> actualVars() - { - if ( actualVars == null ) - { + private List<Var> actualVars() { + if ( actualVars == null ) { actualVars = new ArrayList<Var>() ; Iterator<Var> iter = binding.vars() ; - for ( ; iter.hasNext() ; ) - { + for ( ; iter.hasNext() ; ) { Var v = iter.next() ; if ( accept(v) ) actualVars.add(v) ; @@ -86,27 +69,19 @@ public abstract class BindingProjectBase } return actualVars ; } - + @Override - protected int size1() - { + protected int size1() { return actualVars().size() ; } - - - - // NB is the projection and the binding don't overlap it is also empty. + + // NB is the projection and the binding don't overlap it is also empty. @Override - protected boolean isEmpty1() - { - if ( binding.isEmpty() ) return true ; - if ( size1() == 0 ) return true ; + protected boolean isEmpty1() { + if ( binding.isEmpty() ) + return true ; + if ( size1() == 0 ) + return true ; return false ; -// for ( Var v : projectionVars ) -// { -// if ( binding.contains(v)) -// return false ; -// } -// return true ; } } Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectNamed.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectNamed.java?rev=1536710&r1=1536709&r2=1536710&view=diff ============================================================================== --- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectNamed.java (original) +++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingProjectNamed.java Tue Oct 29 13:41:00 2013 @@ -16,25 +16,21 @@ * limitations under the License. */ -package com.hp.hpl.jena.sparql.engine.binding; +package com.hp.hpl.jena.sparql.engine.binding ; import com.hp.hpl.jena.sparql.core.Var ; -public class BindingProjectNamed extends BindingProjectBase //extends BindingBase -{ - public BindingProjectNamed(Binding bind) - { - this(bind, null) ; - } - - public BindingProjectNamed(Binding bind, Binding parent) - { - super(bind, parent) ; +/** + * Project only named variables (i.e. hide variables used because of + * bNodes or internally generated variables). + */ +public class BindingProjectNamed extends BindingProjectBase { + public BindingProjectNamed(Binding bind) { + super(bind) ; } @Override - protected boolean accept(Var var) - { + protected boolean accept(Var var) { return var.isNamedVar() ; } } Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingUtils.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingUtils.java?rev=1536710&r1=1536709&r2=1536710&view=diff ============================================================================== --- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingUtils.java (original) +++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/binding/BindingUtils.java Tue Oct 29 13:41:00 2013 @@ -16,7 +16,8 @@ * limitations under the License. */ -package com.hp.hpl.jena.sparql.engine.binding; +package com.hp.hpl.jena.sparql.engine.binding ; + import java.util.Iterator ; import org.apache.jena.atlas.logging.Log ; @@ -28,56 +29,70 @@ import com.hp.hpl.jena.sparql.ARQInterna import com.hp.hpl.jena.sparql.core.ResultBinding ; import com.hp.hpl.jena.sparql.core.Var ; -public class BindingUtils -{ - /** Convert a query solution to a binding */ - public static Binding asBinding(QuerySolution qSolution) - { +public class BindingUtils { + /** Convert a query solution to a binding */ + public static Binding asBinding(QuerySolution qSolution) { if ( qSolution == null ) return null ; if ( qSolution instanceof ResultBinding ) // Only named variables. - return new BindingProjectNamed( ((ResultBinding)qSolution).getBinding() ) ; + return new BindingProjectNamed(((ResultBinding)qSolution).getBinding()) ; BindingMap binding = BindingFactory.create() ; addToBinding(binding, qSolution) ; return binding ; } - - public static void addToBinding(BindingMap binding, QuerySolution qSolution) - { + + public static void addToBinding(BindingMap binding, QuerySolution qSolution) { if ( qSolution == null ) return ; - - for ( Iterator<String> iter = qSolution.varNames() ; iter.hasNext() ; ) - { + + for ( Iterator<String> iter = qSolution.varNames() ; iter.hasNext() ; ) { String n = iter.next() ; - + RDFNode x = qSolution.get(n) ; if ( Var.isBlankNodeVarName(n) ) continue ; try { binding.add(Var.alloc(n), x.asNode()) ; - } catch (ARQInternalErrorException ex) - { + } + catch (ARQInternalErrorException ex) { // bad binding attempt. - Log.warn(BindingUtils.class, "Attempt to bind "+n+" when already bound") ; + Log.warn(BindingUtils.class, "Attempt to bind " + n + " when already bound") ; } } } - - public static void addAll(BindingMap dest, Binding src) - { + + public static void addAll(BindingMap dest, Binding src) { Iterator<Var> iter = src.vars() ; - for ( ; iter.hasNext() ; ) - { + for ( ; iter.hasNext() ; ) { Var v = iter.next() ; Node n = src.get(v) ; dest.add(v, n) ; } } - - public static boolean equals(Binding b1, Binding b2) - { - return BindingBase.equals(b1, b2) ; + + /** Merge two bindings, assuming they are compatible. */ + public static Binding merge(Binding bind1, Binding bind2) { + //Create binding from LHS + BindingMap b2 = BindingFactory.create(bind1) ; + Iterator<Var> vIter = bind2.vars() ; + // Add any variables from the RHS + for ( ; vIter.hasNext() ; ) { + Var v = vIter.next() ; + if ( ! b2.contains(v) ) + b2.add(v, bind2.get(v)) ; + else { + // Checking! + Node n1 = bind1.get(v) ; + Node n2 = bind2.get(v) ; + if ( ! n1.equals(n2) ) + Log.warn(BindingUtils.class, "merge: Mismatch : "+n1+" != "+n2); + } + } + return b2 ; + } + + public static boolean equals(Binding b1, Binding b2) { + return BindingBase.equals(b1, b2) ; } } Copied: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProjectMerge.java (from r1536659, jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProject2.java) URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProjectMerge.java?p2=jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProjectMerge.java&p1=jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProject2.java&r1=1536659&r2=1536710&rev=1536710&view=diff ============================================================================== --- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProject2.java (original) +++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/iterator/QueryIterProjectMerge.java Tue Oct 29 13:41:00 2013 @@ -16,7 +16,7 @@ * limitations under the License. */ -package com.hp.hpl.jena.sparql.engine.iterator; +package com.hp.hpl.jena.sparql.engine.iterator ; import java.util.List ; @@ -25,63 +25,50 @@ import com.hp.hpl.jena.sparql.core.Var ; import com.hp.hpl.jena.sparql.engine.ExecutionContext ; import com.hp.hpl.jena.sparql.engine.QueryIterator ; import com.hp.hpl.jena.sparql.engine.binding.Binding ; -import com.hp.hpl.jena.sparql.engine.binding.BindingProject ; +import com.hp.hpl.jena.sparql.engine.binding.BindingUtils ; import com.hp.hpl.jena.sparql.engine.main.OpExecutor ; - -public class QueryIterProject2 extends QueryIterRepeatApply -{ - List<Var> projectionVars ; - private final OpProject opProject ; +/** + * Execute a projection in the middle of an execution. This requires the outcome + * of each stage of execution (substituion evaluation assumed) to be merged with + * the input binding. Bindings should already be compatible, otherwise this code + * should not be used. + */ +public class QueryIterProjectMerge extends QueryIterRepeatApply { + // This is a merge/substitution join + private final OpProject opProject ; private final OpExecutor engine ; - public QueryIterProject2(OpProject opProject, QueryIterator input, OpExecutor engine, ExecutionContext execCxt) - { + public QueryIterProjectMerge(OpProject opProject, QueryIterator input, OpExecutor engine, ExecutionContext execCxt) { super(input, execCxt) ; this.opProject = opProject ; this.engine = engine ; } @Override - protected QueryIterator nextStage(Binding binding) - { - QueryIterator qIter = engine.executeOp(opProject.getSubOp(), QueryIterSingleton.create(binding, getExecContext())) ; - - qIter = new ProjectEnsureBinding(qIter, - new ProjectEnsureBindingConverter(binding, opProject.getVars()), - getExecContext()) ; - // Project - ensure binding vars are visible. + protected QueryIterator nextStage(Binding binding) { + QueryIterator qIter = engine.executeOp(opProject.getSubOp(), + QueryIterSingleton.create(binding, getExecContext())) ; + + qIter = new QueryIterConvert(qIter, + new ProjectEnsureBindingConverter(binding, opProject.getVars()), + getExecContext()) ; return qIter ; } - - static class ProjectEnsureBinding extends QueryIterConvert - { - - public ProjectEnsureBinding(QueryIterator iter, Converter c, ExecutionContext context) - { - super(iter, c, context) ; - } - } - - static class ProjectEnsureBindingConverter implements QueryIterConvert.Converter - { - private final Binding outerBinding ; + static class ProjectEnsureBindingConverter implements QueryIterConvert.Converter { + + private final Binding outerBinding ; private final List<Var> projectionVars ; - public ProjectEnsureBindingConverter(Binding outerBinding, List<Var> vars) - { + public ProjectEnsureBindingConverter(Binding outerBinding, List<Var> vars) { this.outerBinding = outerBinding ; this.projectionVars = vars ; } @Override - public Binding convert(Binding bind) - { - Binding b = new BindingProject(projectionVars, bind, outerBinding) ; - return b ; + public Binding convert(Binding bind) { + return BindingUtils.merge(outerBinding, bind) ; } - } - } Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/main/OpExecutor.java URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/main/OpExecutor.java?rev=1536710&r1=1536709&r2=1536710&view=diff ============================================================================== --- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/main/OpExecutor.java (original) +++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/engine/main/OpExecutor.java Tue Oct 29 13:41:00 2013 @@ -417,7 +417,7 @@ public class OpExecutor } // Nested projected : need to ensure the input is seen. // ROLL into QueryIterProject - QueryIterator qIter = new QueryIterProject2(opProject, input, this, execCxt) ; + QueryIterator qIter = new QueryIterProjectMerge(opProject, input, this, execCxt) ; return qIter ; }