Skip to content

Commit

Permalink
GH-2140 Unions can now be created without a new scope and will be han…
Browse files Browse the repository at this point in the history
…dled more efficiently.

Signed-off-by: Håvard Ottestad <hmottestad@gmail.com>
  • Loading branch information
hmottestad committed Apr 28, 2020
1 parent 8df7144 commit 7104576
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
/**
* A query optimizer that (partially) normalizes query models to a canonical form. Note: this implementation does not
* yet cover all query node types.
*
*
* @author Arjohn Kampman
*/
public class QueryModelNormalizer extends AbstractQueryModelVisitor<RuntimeException> implements QueryOptimizer {
Expand Down Expand Up @@ -67,15 +67,15 @@ public void meet(Join join) {
Union union = (Union) leftArg;
Join leftJoin = new Join(union.getLeftArg(), rightArg.clone());
Join rightJoin = new Join(union.getRightArg(), rightArg.clone());
Union newUnion = new Union(leftJoin, rightJoin);
Union newUnion = new Union(leftJoin, rightJoin, union.isNewScope());
join.replaceWith(newUnion);
newUnion.visit(this);
} else if (rightArg instanceof Union) {
// sort unions above joins
Union union = (Union) rightArg;
Join leftJoin = new Join(leftArg.clone(), union.getLeftArg());
Join rightJoin = new Join(leftArg.clone(), union.getRightArg());
Union newUnion = new Union(leftJoin, rightJoin);
Union newUnion = new Union(leftJoin, rightJoin, union.isNewScope());
join.replaceWith(newUnion);
newUnion.visit(this);
} else if (leftArg instanceof LeftJoin && isWellDesigned(((LeftJoin) leftArg))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ protected void handleClose() throws QueryEvaluationException {
}

private boolean isOutOfScopeForLeftArgBindings(TupleExpr expr) {
if (expr instanceof Union) {
if (expr instanceof Union && ((Union) expr).isNewScope()) {
return true;
}
return TupleExprs.isGraphPatternGroup(expr) && !(expr instanceof Filter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,36 @@
*/
public class Union extends BinaryTupleOperator {

// Used to differentiate between Unions introduced by the user that require a new scope and unions introduced for
// evaluation or performance purposes that do not introduce a new scope. This means that they can be executed more
// efficiently.
private boolean newScope;

/*--------------*
* Constructors *
*--------------*/

public Union() {
this(true);
}

public Union(boolean newScope) {
this.newScope = newScope;
}

/**
* Creates a new union operator that operates on the two specified arguments.
*
*
* @param leftArg The left argument of the union operator.
* @param rightArg The right argument of the union operator.
*/
public Union(TupleExpr leftArg, TupleExpr rightArg) {
this(leftArg, rightArg, true);
}

public Union(TupleExpr leftArg, TupleExpr rightArg, boolean newScope) {
super(leftArg, rightArg);
this.newScope = newScope;
}

/*---------*
Expand Down Expand Up @@ -69,6 +84,16 @@ public int hashCode() {

@Override
public Union clone() {
return (Union) super.clone();
Union clone = (Union) super.clone();
clone.newScope = this.newScope;
return clone;
}

public boolean isNewScope() {
return newScope;
}

public void setNewScope(boolean newScope) {
this.newScope = newScope;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1187,7 +1187,7 @@ public Object visit(ASTPathAlternative pathAltNode, Object data) throws VisitorE

if (altCount > 1) {
GraphPattern parentGP = graphPattern;
Union union = new Union();
Union union = new Union(false);
Union currentUnion = union;
for (int i = 0; i < altCount - 1; i++) {
graphPattern = new GraphPattern(parentGP);
Expand All @@ -1200,7 +1200,7 @@ public Object visit(ASTPathAlternative pathAltNode, Object data) throws VisitorE
arg = graphPattern.buildTupleExpr();
currentUnion.setRightArg(arg);
} else {
Union newUnion = new Union();
Union newUnion = new Union(false);
currentUnion.setRightArg(newUnion);
currentUnion = newUnion;
}
Expand Down Expand Up @@ -1595,7 +1595,7 @@ private TupleExpr handlePathModifiers(Scope scope, Var subjVar, TupleExpr te, Va
// upperbound is fixed-length

// create set of unions for all path lengths between lower and upper bound.
Union union = new Union();
Union union = new Union(false);
Union currentUnion = union;

for (long length = lowerBound; length < upperBound; length++) {
Expand All @@ -1607,7 +1607,7 @@ private TupleExpr handlePathModifiers(Scope scope, Var subjVar, TupleExpr te, Va
path = createPath(scope, subjVar, te, endVar, contextVar, length + 1);
currentUnion.setRightArg(path);
} else {
Union nextUnion = new Union();
Union nextUnion = new Union(false);
currentUnion.setRightArg(nextUnion);
currentUnion = nextUnion;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import org.apache.commons.io.IOUtils;
import org.eclipse.rdf4j.IsolationLevels;
import org.eclipse.rdf4j.common.concurrent.locks.Properties;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.vocabulary.FOAF;
Expand Down Expand Up @@ -619,4 +618,94 @@ public void testTimeout() {

}

@Test
public void testAlternatePath() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
connection.begin();
for (int i = 0; i < 10; i++) {
connection.add(vf.createBNode(i + ""), RDF.TYPE, vf.createBNode((i + 1) + ""));
connection.add(vf.createBNode(i + ""), RDF.TYPE, vf.createBNode((i - 1) + ""));

connection.add(vf.createBNode(i + ""), RDF.TYPE, vf.createBNode((i + 2) + ""));
connection.add(vf.createBNode(i + ""), RDF.TYPE, vf.createBNode((i - 2) + ""));
}

connection.add(vf.createBNode("0"), RDFS.LABEL, vf.createLiteral("label"));

connection.commit();
}

try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(String.join("\n", "",
"PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>",
"select * where {",
" ?a (a|^a)* ?c. ?c (a|^a) ?b .",
" ?b rdfs:label ?type .",
"}"));

query.setMaxExecutionTime(1);

String actual = query.explain(Explanation.Level.Executed).toString();

assertEquals("Projection (resultSizeActual=84)\n" +
" ProjectionElemList\n" +
" ProjectionElem \"a\"\n" +
" ProjectionElem \"c\"\n" +
" ProjectionElem \"b\"\n" +
" ProjectionElem \"type\"\n" +
" Join (JoinIterator) (resultSizeActual=84)\n" +
" StatementPattern (costEstimate=1, resultSizeEstimate=1, resultSizeActual=1)\n" +
" Var (name=b)\n" +
" Var (name=_const_9285ccfc_uri, value=http://www.w3.org/2000/01/rdf-schema#label, anonymous)\n"
+
" Var (name=type)\n" +
" Union (resultSizeActual=84)\n" +
" Join (JoinIterator) (resultSizeActual=28)\n" +
" StatementPattern (costEstimate=2, resultSizeEstimate=40, resultSizeActual=2)\n" +
" Var (name=c)\n" +
" Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" Var (name=b)\n" +
" ArbitraryLengthPath (costEstimate=9, resultSizeEstimate=82, resultSizeActual=28)\n" +
" Var (name=a)\n" +
" Union\n" +
" StatementPattern (resultSizeEstimate=40)\n" +
" Var (name=a)\n" +
" Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" Var (name=c)\n" +
" StatementPattern (resultSizeEstimate=40)\n" +
" Var (name=c)\n" +
" Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" Var (name=a)\n" +
" Var (name=c)\n" +
" Join (JoinIterator) (resultSizeActual=56)\n" +
" StatementPattern (costEstimate=2, resultSizeEstimate=40, resultSizeActual=4)\n" +
" Var (name=b)\n" +
" Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" Var (name=c)\n" +
" ArbitraryLengthPath (costEstimate=9, resultSizeEstimate=82, resultSizeActual=56)\n" +
" Var (name=a)\n" +
" Union\n" +
" StatementPattern (resultSizeEstimate=40)\n" +
" Var (name=a)\n" +
" Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" Var (name=c)\n" +
" StatementPattern (resultSizeEstimate=40)\n" +
" Var (name=c)\n" +
" Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" Var (name=a)\n" +
" Var (name=c)\n", actual);

System.out.println(actual);
}
sailRepository.shutDown();

}

}

0 comments on commit 7104576

Please sign in to comment.