com.bigdata.rdf.sparql.ast.optimizers.TestASTEmptyGroupOptimizer Maven / Gradle / Ivy
Show all versions of bigdata-rdf-test Show documentation
/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
[email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Created on Aug 29, 2011
*/
package com.bigdata.rdf.sparql.ast.optimizers;
import org.openrdf.model.impl.LiteralImpl;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.model.vocabulary.DC;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.query.algebra.StatementPattern.Scope;
import com.bigdata.bop.IBindingSet;
import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.internal.VTE;
import com.bigdata.rdf.internal.XSD;
import com.bigdata.rdf.internal.impl.TermId;
import com.bigdata.rdf.sparql.ast.AbstractASTEvaluationTestCase;
import com.bigdata.rdf.sparql.ast.AssignmentNode;
import com.bigdata.rdf.sparql.ast.ConstantNode;
import com.bigdata.rdf.sparql.ast.FilterNode;
import com.bigdata.rdf.sparql.ast.FunctionNode;
import com.bigdata.rdf.sparql.ast.FunctionRegistry;
import com.bigdata.rdf.sparql.ast.IQueryNode;
import com.bigdata.rdf.sparql.ast.JoinGroupNode;
import com.bigdata.rdf.sparql.ast.NamedSubqueryInclude;
import com.bigdata.rdf.sparql.ast.NamedSubqueryRoot;
import com.bigdata.rdf.sparql.ast.ProjectionNode;
import com.bigdata.rdf.sparql.ast.QueryBase;
import com.bigdata.rdf.sparql.ast.QueryNodeWithBindingSet;
import com.bigdata.rdf.sparql.ast.QueryRoot;
import com.bigdata.rdf.sparql.ast.QueryType;
import com.bigdata.rdf.sparql.ast.StatementPatternNode;
import com.bigdata.rdf.sparql.ast.SubqueryRoot;
import com.bigdata.rdf.sparql.ast.UnionNode;
import com.bigdata.rdf.sparql.ast.ValueExpressionNode;
import com.bigdata.rdf.sparql.ast.VarNode;
import com.bigdata.rdf.store.BDS;
import com.bigdata.rdf.vocab.decls.FOAFVocabularyDecl;
/**
* Test suite for {@link ASTEmptyGroupOptimizer}.
*
* TODO Test for removal of empty UNIONs. Empty UNIONs can arise through pruning
* based on unknown IVs, or filters which are provably false. However, I would
* expect the pruning logic to eliminate the empty group in such cases.
*
* @author Bryan Thompson
* @version $Id: TestASTEmptyGroupOptimizer.java 5302 2011-10-07 14:28:03Z
* thompsonbry $
*/
public class TestASTEmptyGroupOptimizer extends AbstractASTEvaluationTestCase {
/**
*
*/
public TestASTEmptyGroupOptimizer() {
}
/**
* @param name
*/
public TestASTEmptyGroupOptimizer(String name) {
super(name);
}
/**
* Given
*
*
* SELECT VarNode(subj)
* JoinGroupNode {
* JoinGroupNode [context=VarNode(g)] {
* StatementPatternNode(VarNode(lit), ConstantNode(bd:search), ConstantNode("mike"), VarNode(g), NAMED_CONTEXTS)
* StatementPatternNode(VarNode(subj), VarNode(p), VarNode(lit), VarNode(g), NAMED_CONTEXTS)
* }
* }
*
*
* Replace the outer {@link JoinGroupNode} with the inner
* {@link JoinGroupNode}.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void test_eliminateJoinGroup01() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
final IV bdSearchIV = TermId.mockIV(VTE.URI);
bdSearchIV.setValue(store.getValueFactory().createURI(
BDS.SEARCH.toString()));
final IV mikeIV = TermId.mockIV(VTE.LITERAL);
mikeIV.setValue(store.getValueFactory().createLiteral("mike"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
final JoinGroupNode graphGroup = new JoinGroupNode();
whereClause.addChild(graphGroup);
graphGroup.setContext(new VarNode("g"));
graphGroup.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.NAMED_CONTEXTS));
graphGroup.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.NAMED_CONTEXTS));
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
whereClause.setContext(new VarNode("g"));
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.NAMED_CONTEXTS));
whereClause.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.NAMED_CONTEXTS));
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Unit test for
*
*
* { {} } => {}
*
*/
public void test_eliminateJoinGroup02() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
// { {} }
final JoinGroupNode whereClause = new JoinGroupNode(new JoinGroupNode());
given.setWhereClause(whereClause);
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
// {}
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Unit test for
*
*
* { { {} } } => {}
*
*/
public void test_eliminateJoinGroup03() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
// { { {} } }
final JoinGroupNode whereClause = new JoinGroupNode(
new JoinGroupNode(new JoinGroupNode()));
given.setWhereClause(whereClause);
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Unit test verifies that the rewrite of an embedded sole GRAPH pattern is
* the lifting of that GRAPH pattern (rather than replacing it with an empty
* non-GRAPH group).
*
*
* { GRAPH foo {} } => GRAPH foo {}
*
*/
public void test_eliminateJoinGroup04() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
// { GRAPH ?g {} }
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
final JoinGroupNode graphGroup = new JoinGroupNode(new JoinGroupNode());
graphGroup.setContext(new VarNode("g"));
whereClause.addChild(graphGroup);
System.err.println("given:"+given);
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
// GRAPH ?g {}
final JoinGroupNode graphGroup = new JoinGroupNode(new JoinGroupNode());
graphGroup.setContext(new VarNode("g"));
expected.setWhereClause(graphGroup);
System.err.println("expected:"+expected);
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* For this AST we need to replace the root {@link JoinGroupNode} with its
* child {@link UnionNode}. This means setting the child {@link UnionNode}
* as the whereClause on the {@link QueryBase}.
*
*
* SELECT DISTINCT VarNode(s) VarNode(o)
* JoinGroupNode {
* UnionNode {
* JoinGroupNode {
* StatementPatternNode(VarNode(s), ConstantNode(TermId(2U)[http://example/p]), VarNode(o), DEFAULT_CONTEXTS)
* }
* JoinGroupNode {
* StatementPatternNode(VarNode(s), ConstantNode(TermId(3U)[http://example/q]), VarNode(o), DEFAULT_CONTEXTS)
* }
* }
* }
*
*
* @throws Exception
*/
public void test_eliminateJoinGroup05() throws Exception {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
@SuppressWarnings("rawtypes")
final IV p = makeIV(new URIImpl("http://example/p"));
@SuppressWarnings("rawtypes")
final IV q = makeIV(new URIImpl("http://example/q"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("s"));
projection.addProjectionVar(new VarNode("o"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
final UnionNode union = new UnionNode();
final JoinGroupNode joinGroup1 = new JoinGroupNode(
new StatementPatternNode(new VarNode("s"),
new ConstantNode(p), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
final JoinGroupNode joinGroup2 = new JoinGroupNode(
new StatementPatternNode(new VarNode("s"),
new ConstantNode(q), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
whereClause.addChild(union);
union.addChild(joinGroup1);
union.addChild(joinGroup2);
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("s"));
projection.addProjectionVar(new VarNode("o"));
final UnionNode union = new UnionNode();
final JoinGroupNode joinGroup1 = new JoinGroupNode(
new StatementPatternNode(new VarNode("s"),
new ConstantNode(p), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
final JoinGroupNode joinGroup2 = new JoinGroupNode(
new StatementPatternNode(new VarNode("s"),
new ConstantNode(q), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
expected.setWhereClause(union);
union.addChild(joinGroup1);
union.addChild(joinGroup2);
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* For this AST we need to left the {@link UnionNode} up to replace its
* empty parent {@link JoinGroupNode}. The difference between this test
* and test 05 is that the parent is not the root of the where clause.
*
*
* SELECT DISTINCT VarNode(s) VarNode(o)
* JoinGroupNode {
* StatementPatternNode(VarNode(s), ConstantNode(TermId(4U)[http://example/x]), ConstantNode(TermId(5U)[http://example/y]), DEFAULT_CONTEXTS)
* JoinGroupNode {
* UnionNode {
* JoinGroupNode {
* StatementPatternNode(VarNode(s), ConstantNode(TermId(2U)[http://example/p]), VarNode(o), DEFAULT_CONTEXTS)
* }
* JoinGroupNode {
* StatementPatternNode(VarNode(s), ConstantNode(TermId(3U)[http://example/q]), VarNode(o), DEFAULT_CONTEXTS)
* }
* }
* }
* }
*
*
* @throws Exception
*/
public void test_eliminateJoinGroup06() throws Exception {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
@SuppressWarnings("rawtypes")
final IV p = makeIV(new URIImpl("http://example/p"));
@SuppressWarnings("rawtypes")
final IV q = makeIV(new URIImpl("http://example/q"));
@SuppressWarnings("rawtypes")
final IV x = makeIV(new URIImpl("http://example/x"));
@SuppressWarnings("rawtypes")
final IV y = makeIV(new URIImpl("http://example/y"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("s"));
projection.addProjectionVar(new VarNode("o"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
final UnionNode union = new UnionNode();
final JoinGroupNode joinGroup1 = new JoinGroupNode(
new StatementPatternNode(new VarNode("s"),
new ConstantNode(p), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
final JoinGroupNode joinGroup2 = new JoinGroupNode(
new StatementPatternNode(new VarNode("s"),
new ConstantNode(q), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
union.addChild(joinGroup1);
union.addChild(joinGroup2);
final JoinGroupNode emptyJoinGroup = new JoinGroupNode();
emptyJoinGroup.addChild(union);
whereClause.addChild(new StatementPatternNode(new VarNode("s"),
new ConstantNode(x), new ConstantNode(y), null/* c */,
Scope.DEFAULT_CONTEXTS));
whereClause.addChild(emptyJoinGroup);
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("s"));
projection.addProjectionVar(new VarNode("o"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
final UnionNode union = new UnionNode();
final JoinGroupNode joinGroup1 = new JoinGroupNode(
new StatementPatternNode(new VarNode("s"),
new ConstantNode(p), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
final JoinGroupNode joinGroup2 = new JoinGroupNode(
new StatementPatternNode(new VarNode("s"),
new ConstantNode(q), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
union.addChild(joinGroup1);
union.addChild(joinGroup2);
whereClause.addChild(new StatementPatternNode(new VarNode("s"),
new ConstantNode(x), new ConstantNode(y), null/* c */,
Scope.DEFAULT_CONTEXTS));
whereClause.addChild(union);
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Rewrite:
*
*
* SELECT ?x ?o
* WHERE {
* ?x rdfs:label ?o .
* {
* SELECT ?x WHERE {?x rdf:type foaf:Person}
* }
* }
*
*
* to
*
*
* SELECT ?x ?o
* WHERE {
* ?x rdfs:label ?o .
* SELECT ?x WHERE {?x rdf:type foaf:Person}
* }
*
*
* @throws Exception
*/
public void test_eliminateJoinGroup07() throws Exception {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
@SuppressWarnings("rawtypes")
final IV rdfsLabel = makeIV(RDFS.LABEL);
@SuppressWarnings("rawtypes")
final IV rdfType = makeIV(RDF.TYPE);
@SuppressWarnings("rawtypes")
final IV foafPerson = makeIV(FOAFVocabularyDecl.Person);
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
// Sub-Select
final SubqueryRoot subqueryRoot = new SubqueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
subqueryRoot.setProjection(projection);
final JoinGroupNode whereClause = new JoinGroupNode();
subqueryRoot.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("x"),
new ConstantNode(rdfType), new ConstantNode(foafPerson),
null/* c */, Scope.DEFAULT_CONTEXTS));
}
// QueryRoot
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("x"));
projection.addProjectionVar(new VarNode("o"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("x"),
new ConstantNode(rdfsLabel), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
final JoinGroupNode joinGroup = new JoinGroupNode();
whereClause.addChild(joinGroup);
joinGroup.addChild(subqueryRoot);
}
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
// Sub-Select
final SubqueryRoot subqueryRoot = new SubqueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
subqueryRoot.setProjection(projection);
final JoinGroupNode whereClause = new JoinGroupNode();
subqueryRoot.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("x"),
new ConstantNode(rdfType), new ConstantNode(foafPerson),
null/* c */, Scope.DEFAULT_CONTEXTS));
}
// QueryRoot
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("x"));
projection.addProjectionVar(new VarNode("o"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("x"),
new ConstantNode(rdfsLabel), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
whereClause.addChild(subqueryRoot);
}
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Given:
*
*
* PREFIX :
* SELECT ?v
* { :x :p ?v . { FILTER(?v = 1) } }
*
*
* Verify that the FILTER is NOT lifted out of the join group.
*
* Note: This is Filter-nested - 2
(Filter on variable ?v which
* is not in scope) from the DAWG test suite. In this case, the filter can
* not be lifted because that change would violate the bottom up semantics
* for this query. In general, the lifting of filters which MAY be lifted
* should be handled by the {@link ASTLiftPreFiltersOptimizer} class. That
* class is designed to recognize pre-filters, which are filters whose
* variables are all known bound on entry to the group and, hence, could be
* run against the parent group.
*/
public void test_emptyGroupOptimizer_doNotLiftFilter() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
@SuppressWarnings("rawtypes")
final IV x = makeIV(new URIImpl("http://example/x"));
@SuppressWarnings("rawtypes")
final IV p = makeIV(new URIImpl("http://example/p"));
@SuppressWarnings("rawtypes")
final IV ONE = makeIV(new LiteralImpl("1",XSD.INTEGER));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
// QueryRoot
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("v"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new ConstantNode(x),
new ConstantNode(p), new VarNode("v"), null/* c */,
Scope.DEFAULT_CONTEXTS));
final JoinGroupNode joinGroup = new JoinGroupNode(true/*optional*/);
whereClause.addChild(joinGroup);
joinGroup.addChild(new FilterNode(new FunctionNode(
FunctionRegistry.EQ, null/* scalarValues */,
new ValueExpressionNode[] { new VarNode("v"),
new ConstantNode(ONE) })));
}
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
// QueryRoot
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("v"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new ConstantNode(x),
new ConstantNode(p), new VarNode("v"), null/* c */,
Scope.DEFAULT_CONTEXTS));
final JoinGroupNode joinGroup = new JoinGroupNode(true/*optional*/);
whereClause.addChild(joinGroup);
joinGroup.addChild(new FilterNode(new FunctionNode(
FunctionRegistry.EQ, null/* scalarValues */,
new ValueExpressionNode[] { new VarNode("v"),
new ConstantNode(ONE) })));
}
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Verify that we do not lift something out of an optional group as that
* would destroy the optional semantics of the thing lifted.
*
* SELECT ?x ?o
* WHERE {
* ?x rdfs:label ?o .
* OPTIONAL {
* ?x rdf:type foaf:Person
* }
* }
*
*/
public void test_emptyGroupOptimizer_doNotLiftFromOptionalGroup() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
@SuppressWarnings("rawtypes")
final IV rdfsLabel = makeIV(RDFS.LABEL);
@SuppressWarnings("rawtypes")
final IV rdfType = makeIV(RDF.TYPE);
@SuppressWarnings("rawtypes")
final IV foafPerson = makeIV(FOAFVocabularyDecl.Person);
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
// QueryRoot
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("x"));
projection.addProjectionVar(new VarNode("o"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("x"),
new ConstantNode(rdfsLabel), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
final JoinGroupNode joinGroup = new JoinGroupNode(true/*optional*/);
whereClause.addChild(joinGroup);
joinGroup.addChild(new StatementPatternNode(new VarNode("x"),
new ConstantNode(rdfType), new ConstantNode(foafPerson),
null/* c */, Scope.DEFAULT_CONTEXTS));
}
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
// QueryRoot
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("x"));
projection.addProjectionVar(new VarNode("o"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("x"),
new ConstantNode(rdfsLabel), new VarNode("o"), null/* c */,
Scope.DEFAULT_CONTEXTS));
final JoinGroupNode joinGroup = new JoinGroupNode(true/*optional*/);
whereClause.addChild(joinGroup);
joinGroup.addChild(new StatementPatternNode(new VarNode("x"),
new ConstantNode(rdfType), new ConstantNode(foafPerson),
null/* c */, Scope.DEFAULT_CONTEXTS));
}
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
*
* WITH {
* QueryType: SELECT
* SELECT ( VarNode(_var1) AS VarNode(_var1) )
* JoinGroupNode {
* StatementPatternNode(VarNode(_var1), ConstantNode(TermId(1U)[http://example/a]), ConstantNode(TermId(2U)[http://example/b]), DEFAULT_CONTEXTS)
* }
* } AS _set1
* QueryType: SELECT
* SELECT VarNode(_var1) VarNode(_var2) VarNode(_var4)
* JoinGroupNode {
* JoinGroupNode {
* JoinGroupNode {
* INCLUDE _set1
* }
* StatementPatternNode(VarNode(_var1), ConstantNode(TermId(3U)[http://example/c]), VarNode(_var2), DEFAULT_CONTEXTS) [simpleOptional]
* StatementPatternNode(VarNode(_var12), ConstantNode(TermId(6U)[http://example/d]), VarNode(_var1), DEFAULT_CONTEXTS)
* StatementPatternNode(VarNode(_var12), ConstantNode(TermId(7U)[http://example/e]), VarNode(_var4), DEFAULT_CONTEXTS)
* }
* }
*
*
* @throws Exception
*/
public void test_eliminateJoinGroup08() throws Exception {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
@SuppressWarnings("rawtypes")
final IV a = makeIV(new URIImpl("http://example/a"));
@SuppressWarnings("rawtypes")
final IV b = makeIV(new URIImpl("http://example/b"));
@SuppressWarnings("rawtypes")
final IV c = makeIV(new URIImpl("http://example/c"));
@SuppressWarnings("rawtypes")
final IV d = makeIV(new URIImpl("http://example/d"));
@SuppressWarnings("rawtypes")
final IV e = makeIV(new URIImpl("http://example/e"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final NamedSubqueryRoot namedSubquery = new NamedSubqueryRoot(QueryType.SELECT, "_set1");
{
final ProjectionNode projection = new ProjectionNode();
namedSubquery.setProjection(projection);
projection.addProjectionExpression(new AssignmentNode(new VarNode("_var1"), new VarNode("_var1")));
final JoinGroupNode joinGroup1 = new JoinGroupNode(
new StatementPatternNode(new VarNode("_var1"),
new ConstantNode(a), new ConstantNode(b), null/* c */,
Scope.DEFAULT_CONTEXTS));
namedSubquery.setWhereClause(joinGroup1);
}
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("_var1"));
projection.addProjectionVar(new VarNode("_var2"));
projection.addProjectionVar(new VarNode("_var4"));
final JoinGroupNode joinGroup1 = new JoinGroupNode();
final JoinGroupNode joinGroup2 = new JoinGroupNode();
final JoinGroupNode joinGroup3 = new JoinGroupNode();
final JoinGroupNode joinGroup4 = new JoinGroupNode();
joinGroup4.addChild(joinGroup3);
joinGroup3.addChild(joinGroup2);
joinGroup2.addChild(joinGroup1);
joinGroup2.addChild(new StatementPatternNode(new VarNode("_var1"),
new ConstantNode(c), new VarNode("_var2"), null/* c */,
Scope.DEFAULT_CONTEXTS));
joinGroup2.addChild(new StatementPatternNode(new VarNode("_var12"),
new ConstantNode(d), new VarNode("_var1"), null/* c */,
Scope.DEFAULT_CONTEXTS));
joinGroup2.addChild(new StatementPatternNode(new VarNode("_var12"),
new ConstantNode(e), new VarNode("_var4"), null/* c */,
Scope.DEFAULT_CONTEXTS));
joinGroup1.addChild(new NamedSubqueryInclude("_set1"));
given.setWhereClause(joinGroup4);
given.getNamedSubqueriesNotNull().add(namedSubquery);
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final NamedSubqueryRoot namedSubquery = new NamedSubqueryRoot(QueryType.SELECT, "_set1");
{
final ProjectionNode projection = new ProjectionNode();
namedSubquery.setProjection(projection);
projection.addProjectionExpression(new AssignmentNode(new VarNode("_var1"), new VarNode("_var1")));
final JoinGroupNode joinGroup1 = new JoinGroupNode(
new StatementPatternNode(new VarNode("_var1"),
new ConstantNode(a), new ConstantNode(b), null/* c */,
Scope.DEFAULT_CONTEXTS));
namedSubquery.setWhereClause(joinGroup1);
}
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.setDistinct(true);
projection.addProjectionVar(new VarNode("_var1"));
projection.addProjectionVar(new VarNode("_var2"));
projection.addProjectionVar(new VarNode("_var4"));
final JoinGroupNode joinGroup1 = new JoinGroupNode();
// final JoinGroupNode joinGroup2 = new JoinGroupNode();
// joinGroup2.addChild(new NamedSubqueryInclude("_set1"));
// joinGroup1.addChild(joinGroup2);
joinGroup1.addChild(new NamedSubqueryInclude("_set1"));
joinGroup1.addChild(new StatementPatternNode(new VarNode("_var1"),
new ConstantNode(c), new VarNode("_var2"), null/* c */,
Scope.DEFAULT_CONTEXTS));
joinGroup1.addChild(new StatementPatternNode(new VarNode("_var12"),
new ConstantNode(d), new VarNode("_var1"), null/* c */,
Scope.DEFAULT_CONTEXTS));
joinGroup1.addChild(new StatementPatternNode(new VarNode("_var12"),
new ConstantNode(e), new VarNode("_var4"), null/* c */,
Scope.DEFAULT_CONTEXTS));
expected.setWhereClause(joinGroup1);
expected.getNamedSubqueriesNotNull().add(namedSubquery);
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Given
*
*
* SELECT VarNode(subj)
* JoinGroupNode {
* StatementPatternNode(VarNode(lit), ConstantNode(bd:search), ConstantNode("mike"), VarNode(g), NAMED_CONTEXTS)
* StatementPatternNode(VarNode(subj), VarNode(p), VarNode(lit), VarNode(g), NAMED_CONTEXTS)
* JoinGroupNode {
* }
* JoinGroupNode {
* JoinGroupNode {
* }
* }
* }
*
*
* Remove the inner {@link JoinGroupNode}s.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void test_eliminateJoinGroup09() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
final IV bdSearchIV = TermId.mockIV(VTE.URI);
bdSearchIV.setValue(store.getValueFactory().createURI(
BDS.SEARCH.toString()));
final IV mikeIV = TermId.mockIV(VTE.LITERAL);
mikeIV.setValue(store.getValueFactory().createLiteral("mike"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode graphGroup = new JoinGroupNode();
graphGroup.addChild(new JoinGroupNode());
graphGroup.addChild(new JoinGroupNode(new JoinGroupNode()));
graphGroup.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.NAMED_CONTEXTS));
graphGroup.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.NAMED_CONTEXTS));
given.setWhereClause(graphGroup);
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.NAMED_CONTEXTS));
whereClause.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.NAMED_CONTEXTS));
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Top-level UNION optimizations. We should look at the plan after join
* attachment. If there is just a child union (because either there is no
* filter or because there is a filter and it was attached to the union)
* then we should either lift the UNION and evaluate it directly or (if we
* do not permit that structure) make the join group evaluation a nop in
* which it just enters the child (the union) and evaluates that.
*
*
* SELECT DISTINCT ?subjectUri ?p ?rightValue ?leftValue
* WHERE {
* {
* ?subjectUri rdf:type .
* ?subjectUri ?p ?rightValue .
* ?rightValue rdf:type ?otherValueType .
* } UNION {
* ?subjectUri rdf:type .
* ?leftValue ?p ?subjectUri .
* ?leftValue rdf:type ?otherValueType .
* }
* FILTER(sameTerm(?otherValueType,
* 'http://test.org/someOtherType/1')
* sameTerm(?otherValueType,
* 'http://test.org/someOtherType/2'))
* }
*
*
* @see https://sourceforge.net/apps/trac/bigdata/ticket/416
*/
public void test_ticket416() throws Exception {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
final IV,?> type = makeIV(RDF.TYPE);
final IV,?> a = makeIV(new URIImpl("http://example/a"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
projection.addProjectionVar(new VarNode("s"));
projection.addProjectionVar(new VarNode("p"));
projection.addProjectionVar(new VarNode("r"));
projection.addProjectionVar(new VarNode("l"));
projection.setDistinct(true);
final UnionNode union = new UnionNode(); // outer
final JoinGroupNode left = new JoinGroupNode();
left.addChild(new StatementPatternNode(
new VarNode("s"),
new ConstantNode(type),
new ConstantNode(a)));
left.addChild(new StatementPatternNode(
new VarNode("s"),
new VarNode("p"),
new VarNode("r")));
left.addChild(new StatementPatternNode(
new VarNode("r"),
new ConstantNode(type),
new VarNode("type")));
final JoinGroupNode right = new JoinGroupNode();
right.addChild(new StatementPatternNode(
new VarNode("s"),
new ConstantNode(type),
new ConstantNode(a)));
right.addChild(new StatementPatternNode(
new VarNode("l"),
new VarNode("p"),
new VarNode("s")));
right.addChild(new StatementPatternNode(
new VarNode("l"),
new ConstantNode(type),
new VarNode("type")));
union.addChild(left);
union.addChild(right);
final JoinGroupNode where = new JoinGroupNode();
where.addChild(union);
given.setProjection(projection);
given.setWhereClause(where);
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
projection.addProjectionVar(new VarNode("s"));
projection.addProjectionVar(new VarNode("p"));
projection.addProjectionVar(new VarNode("r"));
projection.addProjectionVar(new VarNode("l"));
projection.setDistinct(true);
final UnionNode union = new UnionNode(); // outer
final JoinGroupNode left = new JoinGroupNode();
left.addChild(new StatementPatternNode(
new VarNode("s"),
new ConstantNode(type),
new ConstantNode(a)));
left.addChild(new StatementPatternNode(
new VarNode("s"),
new VarNode("p"),
new VarNode("r")));
left.addChild(new StatementPatternNode(
new VarNode("r"),
new ConstantNode(type),
new VarNode("type")));
final JoinGroupNode right = new JoinGroupNode();
right.addChild(new StatementPatternNode(
new VarNode("s"),
new ConstantNode(type),
new ConstantNode(a)));
right.addChild(new StatementPatternNode(
new VarNode("l"),
new VarNode("p"),
new VarNode("s")));
right.addChild(new StatementPatternNode(
new VarNode("l"),
new ConstantNode(type),
new VarNode("type")));
union.addChild(left);
union.addChild(right);
expected.setProjection(projection);
expected.setWhereClause(union);
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Given
*
*
* SELECT VarNode(subj)
* StatementPatternNode(VarNode(lit), ConstantNode(bd:search), ConstantNode("mike"), VarNode(g), DEFAULT_CONTEXTS)
* JoinGroupNode [minus] {
* StatementPatternNode(VarNode(subj), VarNode(p), VarNode(lit), VarNode(g), NAMED_CONTEXTS)
* }
*
*
* There is no change. The top-level join group is unchanged since the MINUS
* is not semantically empty and hence can not be lifted into it.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void test_eliminateJoinGroup10_minus() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
final IV bdSearchIV = TermId.mockIV(VTE.URI);
bdSearchIV.setValue(store.getValueFactory().createURI(
BDS.SEARCH.toString()));
final IV mikeIV = TermId.mockIV(VTE.LITERAL);
mikeIV.setValue(store.getValueFactory().createLiteral("mike"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup = new JoinGroupNode();
whereClause.addChild(minusGroup);
minusGroup.setMinus(true);
minusGroup.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.NAMED_CONTEXTS));
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup = new JoinGroupNode();
whereClause.addChild(minusGroup);
minusGroup.setMinus(true);
minusGroup.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.NAMED_CONTEXTS));
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Given
*
*
* SELECT VarNode(subj)
* StatementPatternNode(VarNode(lit), ConstantNode(bd:search), ConstantNode("mike"), VarNode(g), DEFAULT_CONTEXTS)
* JoinGroupNode [minus] {
* JoinGroupNode [context=VarNode(g)] {
* StatementPatternNode(VarNode(subj), VarNode(p), VarNode(lit), VarNode(g), NAMED_CONTEXTS)
* }
* }
*
*
* There is no change. The top-level join group is unchanged since the MINUS
* is not semantically empty and hence can not be lifted into it. The NAMED
* GRAPH join group is NOT lifted since MINUS is not semantically empty and
* is does not share the same context as the inner join group.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void test_eliminateJoinGroup11_minus() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
final IV bdSearchIV = TermId.mockIV(VTE.URI);
bdSearchIV.setValue(store.getValueFactory().createURI(
BDS.SEARCH.toString()));
final IV mikeIV = TermId.mockIV(VTE.LITERAL);
mikeIV.setValue(store.getValueFactory().createLiteral("mike"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup = new JoinGroupNode();
whereClause.addChild(minusGroup);
minusGroup.setMinus(true);
final JoinGroupNode graphGroup = new JoinGroupNode();
minusGroup.addChild(graphGroup);
graphGroup.setContext(new VarNode("g"));
graphGroup.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.NAMED_CONTEXTS));
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup = new JoinGroupNode();
whereClause.addChild(minusGroup);
minusGroup.setMinus(true);
final JoinGroupNode graphGroup = new JoinGroupNode();
minusGroup.addChild(graphGroup);
graphGroup.setContext(new VarNode("g"));
graphGroup.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.NAMED_CONTEXTS));
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Given
*
*
* SELECT VarNode(subj)
* StatementPatternNode(VarNode(lit), ConstantNode(bd:search), ConstantNode("mike"), VarNode(g), DEFAULT_CONTEXTS)
* JoinGroupNode [minus] {
* JoinGroupNode [minus] {
* StatementPatternNode(VarNode(subj), VarNode(p), VarNode(lit), VarNode(g), DEFAULT_CONTEXTS)
* }
* }
*
*
* The inner MINUS group can not replace the outer MINUS. This case actually
* corresponds to subtracting the solutions of the inner MINUS group from
* the solutions of the outer MINUS group (an empty set).
*
* Note: For this case, we could just wipe out both of the MINUS groups
* since subtracting anything from an empty set yields an empty set for the
* MINUS groups and subtracting an empty set from the parent yeilds whatever
* solutions are in the parent. I.e., the MINUS groups reduce to a NOP. In
* fact, this probably is done by the {@link ASTBottomUpOptimizer} since
* there will not be any shared variables between the first level MINUS and
* the outer parent group.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void test_eliminateJoinGroup12_minus() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
final IV bdSearchIV = TermId.mockIV(VTE.URI);
bdSearchIV.setValue(store.getValueFactory().createURI(
BDS.SEARCH.toString()));
final IV mikeIV = TermId.mockIV(VTE.LITERAL);
mikeIV.setValue(store.getValueFactory().createLiteral("mike"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup = new JoinGroupNode();
whereClause.addChild(minusGroup);
minusGroup.setMinus(true);
final JoinGroupNode minusGroup2 = new JoinGroupNode();
minusGroup.addChild(minusGroup2);
minusGroup2.setMinus(true);
minusGroup2.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup = new JoinGroupNode();
whereClause.addChild(minusGroup);
minusGroup.setMinus(true);
final JoinGroupNode minusGroup2 = new JoinGroupNode();
minusGroup.addChild(minusGroup2);
minusGroup2.setMinus(true);
minusGroup2.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* Given
*
*
* SELECT VarNode(subj)
* StatementPatternNode(VarNode(lit), ConstantNode(bd:search), ConstantNode("mike"), VarNode(g), DEFAULT_CONTEXTS)
* JoinGroupNode [minus] {
* StatementPatternNode(VarNode(lit), ConstantNode(bd:search), ConstantNode("rdf"), VarNode(g), DEFAULT_CONTEXTS)
* JoinGroupNode [minus] {
* StatementPatternNode(VarNode(subj), VarNode(p), VarNode(lit), VarNode(g), DEFAULT_CONTEXTS)
* }
* }
*
*
* This must be evaluated as G0 - (G1 - (G2))
. The two MINUS
* groups may not be combined.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void test_eliminateJoinGroup13_minus() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
final IV bdSearchIV = TermId.mockIV(VTE.URI);
bdSearchIV.setValue(store.getValueFactory().createURI(
BDS.SEARCH.toString()));
final IV mikeIV = TermId.mockIV(VTE.LITERAL);
mikeIV.setValue(store.getValueFactory().createLiteral("mike"));
final IV rdfIV = TermId.mockIV(VTE.LITERAL);
rdfIV.setValue(store.getValueFactory().createLiteral("rdf"));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup = new JoinGroupNode();
whereClause.addChild(minusGroup);
minusGroup.setMinus(true);
minusGroup.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(rdfIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup2 = new JoinGroupNode();
minusGroup.addChild(minusGroup2);
minusGroup2.setMinus(true);
minusGroup2.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.addProjectionVar(new VarNode("subj"));
final JoinGroupNode whereClause = new JoinGroupNode();
expected.setWhereClause(whereClause);
whereClause.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(mikeIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup = new JoinGroupNode();
whereClause.addChild(minusGroup);
minusGroup.setMinus(true);
minusGroup.addChild(new StatementPatternNode(new VarNode("lit"),
new ConstantNode(bdSearchIV), new ConstantNode(rdfIV),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
final JoinGroupNode minusGroup2 = new JoinGroupNode();
minusGroup.addChild(minusGroup2);
minusGroup2.setMinus(true);
minusGroup2.addChild(new StatementPatternNode(new VarNode("subj"),
new VarNode("p"), new VarNode("lit"),
new VarNode("g"), Scope.DEFAULT_CONTEXTS));
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
/**
* A test case where we can not eliminate an empty join group in a UNION.
*
*
* PREFIX dc:
* PREFIX :
* PREFIX ns:
*
* SELECT ?book
* {
* {}
* UNION
* { ?book dc:title ?title }
* }
*
*
* @see UNION
* with Empty Group Pattern
*/
@SuppressWarnings("unchecked")
public void test_union_01() {
/*
* Note: DO NOT share structures in this test!!!!
*/
final IBindingSet[] bsets = new IBindingSet[]{};
@SuppressWarnings("rawtypes")
final IV dcTitle = TermId.mockIV(VTE.URI);
dcTitle.setValue(store.getValueFactory().createURI(
DC.TITLE.stringValue()));
// The source AST.
final QueryRoot given = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
given.setProjection(projection);
projection.addProjectionVar(new VarNode("book"));
final JoinGroupNode whereClause = new JoinGroupNode();
given.setWhereClause(whereClause);
final UnionNode union = new UnionNode();
whereClause.addChild(union);
final JoinGroupNode emptyGroup = new JoinGroupNode();
final JoinGroupNode otherGroup = new JoinGroupNode();
otherGroup.addChild(new StatementPatternNode(new VarNode("book"),
new ConstantNode(dcTitle), new VarNode("title")));
union.addChild(emptyGroup);
union.addChild(otherGroup);
}
// The expected AST after the rewrite.
final QueryRoot expected = new QueryRoot(QueryType.SELECT);
{
final ProjectionNode projection = new ProjectionNode();
expected.setProjection(projection);
projection.addProjectionVar(new VarNode("book"));
final UnionNode union = new UnionNode();
expected.setWhereClause(union);
final JoinGroupNode emptyGroup = new JoinGroupNode();
final JoinGroupNode otherGroup = new JoinGroupNode();
otherGroup.addChild(new StatementPatternNode(new VarNode("book"),
new ConstantNode(dcTitle), new VarNode("title")));
union.addChild(emptyGroup);
union.addChild(otherGroup);
}
final IASTOptimizer rewriter = new ASTEmptyGroupOptimizer();
final IQueryNode actual = rewriter.optimize(null/* AST2BOpContext */,
new QueryNodeWithBindingSet(given, bsets)).getQueryNode();
assertSameAST(expected, actual);
}
}