From: <jer...@us...> - 2013-11-15 20:19:54
|
Revision: 7558 http://bigdata.svn.sourceforge.net/bigdata/?rev=7558&view=rev Author: jeremy_carroll Date: 2013-11-15 20:19:45 +0000 (Fri, 15 Nov 2013) Log Message: ----------- Additional tests for trac 773 Avoided redundancy by more use of getChildren. Added missing copyright statements. Added additional tests for trac 773 (these show current behavior not desired behavior) Made some functionality protected in ASTPropertyPathOptimizer and ASTRangeCountOptimizer, so that it can be overridden in unit tests. Include cardinality estimates in ALPP displays Refactor optimizer testing, extracting super class. Added unit tests for flatten join optimizer. Modified Paths: -------------- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ArbitraryLengthPathNode.java branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/JoinGroupNode.java branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTOptimizerList.java branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTPropertyPathOptimizer.java branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTRangeCountOptimizer.java branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTStaticJoinOptimizer.java branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestAll.java Added Paths: ----------- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/AbstractOptimizerTestCase.java branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestALPPinTrac773.java branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTFlattenJoinGroupsOptimizer.java Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ArbitraryLengthPathNode.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ArbitraryLengthPathNode.java 2013-11-15 18:31:16 UTC (rev 7557) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/ArbitraryLengthPathNode.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -28,7 +28,7 @@ */ private static final long serialVersionUID = 1L; - interface Annotations extends GroupNodeBase.Annotations { + public interface Annotations extends GroupNodeBase.Annotations { /** * The left term - can be a variable or a constant. @@ -202,7 +202,18 @@ sb.append(s).append(getClass().getSimpleName()); sb.append("(left=").append(left()).append(", right=").append(right()).append(") {"); sb.append(subgroup().toString(indent+1)); - sb.append("\n").append(s).append("}"); + sb.append("\n").append(s); + + final Long rangeCount = (Long) getProperty(AST2BOpBase.Annotations.ESTIMATED_CARDINALITY); + + if (rangeCount != null) { + sb.append(indent(indent + 1)); + sb.append(AST2BOpBase.Annotations.ESTIMATED_CARDINALITY); + sb.append("="); + sb.append(rangeCount.toString()); + sb.append("\n"); + } + sb.append("}"); return sb.toString(); Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/JoinGroupNode.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/JoinGroupNode.java 2013-11-15 18:31:16 UTC (rev 7557) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/JoinGroupNode.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -8,7 +8,6 @@ import com.bigdata.bop.BOp; import com.bigdata.bop.IVariable; import com.bigdata.rdf.internal.constraints.InBOp; -import com.bigdata.rdf.sparql.ast.eval.AST2BOpContext; import com.bigdata.rdf.sparql.ast.service.ServiceNode; /** @@ -179,21 +178,8 @@ */ public List<StatementPatternNode> getStatementPatterns() { - final List<StatementPatternNode> spNodes = - new LinkedList<StatementPatternNode>(); + return getChildren(StatementPatternNode.class); - for (IQueryNode node : this) { - - if (node instanceof StatementPatternNode) { - - spNodes.add((StatementPatternNode) node); - - } - - } - - return spNodes; - } /** @@ -248,21 +234,8 @@ */ public List<ServiceNode> getServiceNodes() { - final List<ServiceNode> serviceNodes = - new LinkedList<ServiceNode>(); + return getChildren(ServiceNode.class); - for (IQueryNode node : this) { - - if (node instanceof ServiceNode) { - - serviceNodes.add((ServiceNode) node); - - } - - } - - return serviceNodes; - } /** @@ -270,21 +243,8 @@ */ public List<NamedSubqueryInclude> getNamedSubqueryIncludes() { - final List<NamedSubqueryInclude> namedSubqueryIncludes = - new LinkedList<NamedSubqueryInclude>(); + return getChildren(NamedSubqueryInclude.class); - for (IQueryNode node : this) { - - if (node instanceof NamedSubqueryInclude) { - - namedSubqueryIncludes.add((NamedSubqueryInclude) node); - - } - - } - - return namedSubqueryIncludes; - } /** @@ -319,21 +279,8 @@ * evaluated left-to-right in the order given in the original query. */ public List<AssignmentNode> getAssignments(){ - - final List<AssignmentNode> assignments = new LinkedList<AssignmentNode>(); - - for (IQueryNode node : this) { - - if (node instanceof AssignmentNode) { - - assignments.add((AssignmentNode) node); - - } - - } - - return assignments; - + + return getChildren(AssignmentNode.class); } /** @@ -341,20 +288,8 @@ */ public List<FilterNode> getAllFiltersInGroup() { - final List<FilterNode> filters = new LinkedList<FilterNode>(); + return getChildren(FilterNode.class); - for (IQueryNode node : this) { - - if (node instanceof FilterNode) { - - filters.add((FilterNode) node); - - } - - } - - return filters; - } /** Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTOptimizerList.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTOptimizerList.java 2013-11-15 18:31:16 UTC (rev 7557) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTOptimizerList.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -27,6 +27,8 @@ package com.bigdata.rdf.sparql.ast.optimizers; +import java.util.Arrays; +import java.util.Collection; import java.util.LinkedList; import org.apache.log4j.Logger; @@ -53,10 +55,12 @@ */ private static final long serialVersionUID = 1L; - public ASTOptimizerList() { - + public ASTOptimizerList(Collection<IASTOptimizer> c) { + super(c); } - + public ASTOptimizerList(IASTOptimizer ... optimizers) { + this(Arrays.asList(optimizers)); + } public boolean add(final IASTOptimizer opt) { if(opt == null) @@ -95,7 +99,7 @@ if (log.isDebugEnabled()) log.debug("Rewritten AST:\n" + queryNode); - + } return queryNode; Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTPropertyPathOptimizer.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTPropertyPathOptimizer.java 2013-11-15 18:31:16 UTC (rev 7557) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTPropertyPathOptimizer.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -335,7 +335,12 @@ return v; } - private VarNode anonVar(final String anon) { + /** + * Override during testing to give predictable results + * @param anon + * @return + */ + protected VarNode anonVar(final String anon) { VarNode v = new VarNode(anon+UUID.randomUUID().toString()); v.setAnonymous(true); return v; Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTRangeCountOptimizer.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTRangeCountOptimizer.java 2013-11-15 18:31:16 UTC (rev 7557) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/java/com/bigdata/rdf/sparql/ast/optimizers/ASTRangeCountOptimizer.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -87,37 +87,8 @@ if (sp.getProperty(Annotations.ESTIMATED_CARDINALITY) == null) { - final IV<?, ?> s = getIV(sp.s(), exogenousBindings); - final IV<?, ?> p = getIV(sp.p(), exogenousBindings); - final IV<?, ?> o = getIV(sp.o(), exogenousBindings); - final IV<?, ?> c = getIV(sp.c(), exogenousBindings); - - final RangeNode rangeNode = sp.getRange(); - final RangeBOp range = rangeNode != null ? rangeNode.getRangeBOp() : null; - - final IAccessPath<?> ap = db.getAccessPath(s, p, o, c, range); - - final long cardinality = ap.rangeCount(false/* exact */); + estimateCardinality(sp, db, exogenousBindings); - // Annotate with the fast range count. - sp.setProperty(Annotations.ESTIMATED_CARDINALITY, cardinality); - - /* - * Annotate with the index which would be used if we did not run - * access path "as-bound". This is the index that will be used - * if we wind up doing a hash join for this predicate. - * - * TODO It would make sense to lift this annotation into a - * different AST optimizer so it is always present. An - * optimization for index locality for as-bound evaluation - * depends on the presence of this annotation. - * - * @see https://sourceforge.net/apps/trac/bigdata/ticket/150" - * (Choosing the index for testing fully bound access paths - * based on index locality) - */ - sp.setProperty(Annotations.ORIGINAL_INDEX, ap.getKeyOrder()); - } } @@ -125,6 +96,51 @@ } /** + * For testing purposes we can override this method. + * @param sp + * @param db + * @param exogenousBindings + */ + protected void estimateCardinality(StatementPatternNode sp, final AbstractTripleStore db, + final IBindingSet exogenousBindings) { + final IV<?, ?> s = getIV(sp.s(), exogenousBindings); + final IV<?, ?> p = getIV(sp.p(), exogenousBindings); + final IV<?, ?> o = getIV(sp.o(), exogenousBindings); + final IV<?, ?> c = getIV(sp.c(), exogenousBindings); + + estimateCardinalities(sp, s, p, o, c, db); + } + + protected void estimateCardinalities(StatementPatternNode sp, final IV<?, ?> s, final IV<?, ?> p, + final IV<?, ?> o, final IV<?, ?> c, final AbstractTripleStore db) { + final RangeNode rangeNode = sp.getRange(); + final RangeBOp range = rangeNode != null ? rangeNode.getRangeBOp() : null; + + final IAccessPath<?> ap = db.getAccessPath(s, p, o, c, range); + + final long cardinality = ap.rangeCount(false/* exact */); + + // Annotate with the fast range count. + sp.setProperty(Annotations.ESTIMATED_CARDINALITY, cardinality); + + /* + * Annotate with the index which would be used if we did not run + * access path "as-bound". This is the index that will be used + * if we wind up doing a hash join for this predicate. + * + * TODO It would make sense to lift this annotation into a + * different AST optimizer so it is always present. An + * optimization for index locality for as-bound evaluation + * depends on the presence of this annotation. + * + * @see https://sourceforge.net/apps/trac/bigdata/ticket/150" + * (Choosing the index for testing fully bound access paths + * based on index locality) + */ + sp.setProperty(Annotations.ORIGINAL_INDEX, ap.getKeyOrder()); + } + + /** * Helper method grabs the IV out of the TermNode, doing the appropriate * NULL and constant/var checks. * Added: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/AbstractOptimizerTestCase.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/AbstractOptimizerTestCase.java (rev 0) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/AbstractOptimizerTestCase.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -0,0 +1,439 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2013. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ +package com.bigdata.rdf.sparql.ast.optimizers; + +import org.openrdf.model.impl.URIImpl; +import org.openrdf.query.algebra.StatementPattern.Scope; + +import com.bigdata.bop.IBindingSet; +import com.bigdata.bop.ModifiableBOpBase; +import com.bigdata.bop.NV; +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.sparql.ast.ASTBase; +import com.bigdata.rdf.sparql.ast.ASTContainer; +import com.bigdata.rdf.sparql.ast.AbstractASTEvaluationTestCase; +import com.bigdata.rdf.sparql.ast.ArbitraryLengthPathNode; +import com.bigdata.rdf.sparql.ast.AssignmentNode; +import com.bigdata.rdf.sparql.ast.ConstantNode; +import com.bigdata.rdf.sparql.ast.GraphPatternGroup; +import com.bigdata.rdf.sparql.ast.GroupMemberNodeBase; +import com.bigdata.rdf.sparql.ast.IGroupMemberNode; +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.PathNode; +import com.bigdata.rdf.sparql.ast.PathNode.*; +import com.bigdata.rdf.sparql.ast.ProjectionNode; +import com.bigdata.rdf.sparql.ast.PropertyPathNode; +import com.bigdata.rdf.sparql.ast.PropertyPathUnionNode; +import com.bigdata.rdf.sparql.ast.QueryBase; +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.TermNode; +import com.bigdata.rdf.sparql.ast.UnionNode; +import com.bigdata.rdf.sparql.ast.VarNode; +import com.bigdata.rdf.sparql.ast.eval.AST2BOpContext; + +public abstract class AbstractOptimizerTestCase extends AbstractASTEvaluationTestCase { + + public interface Annotations extends + com.bigdata.rdf.sparql.ast.GraphPatternGroup.Annotations, + com.bigdata.rdf.sparql.ast.ArbitraryLengthPathNode.Annotations, + com.bigdata.rdf.sparql.ast.eval.AST2BOpBase.Annotations { + } + + enum HelperFlag { + ZERO_OR_ONE { + @Override + public void apply(ASTBase sp) { + setPathMod(((ArbitraryLengthPathNode) sp), PathMod.ZERO_OR_ONE); + } + }, + + ZERO_OR_MORE { + @Override + public void apply(ASTBase sp) { + setPathMod(((ArbitraryLengthPathNode) sp), PathMod.ZERO_OR_MORE); + } + + }, + + ONE_OR_MORE { + @Override + public void apply(ASTBase sp) { + setPathMod(((ArbitraryLengthPathNode) sp), PathMod.ONE_OR_MORE); + } + + }, + DEFAULT_CONTEXTS { + @Override + public void apply(ASTBase sp) { + ((StatementPatternNode) sp).setScope(Scope.DEFAULT_CONTEXTS); + } + }, + NAMED_CONTEXTS { + @Override + public void apply(ASTBase sp) { + ((StatementPatternNode) sp).setScope(Scope.DEFAULT_CONTEXTS); + } + }, + OPTIONAL { + @Override + public void apply(ASTBase sp) { + ((ModifiableBOpBase) sp) + .setProperty(Annotations.OPTIONAL, true); + } + }, + DISTINCT { + @Override + public void apply(ASTBase rslt) { + ((QueryBase) rslt).getProjection().setDistinct(true); + } + }; + + /** + * + * @param target + * @throws ClassCastException + * If there is a mismatch between the flag and its usage. + */ + abstract public void apply(ASTBase target); + + private static void setPathMod(ArbitraryLengthPathNode alp, PathMod mod ) { + alp.setProperty(Annotations.LOWER_BOUND, mod == PathMod.ONE_OR_MORE ? 1L : 0L); + alp.setProperty(Annotations.UPPER_BOUND,mod == PathMod.ZERO_OR_ONE ? 1L : Long.MAX_VALUE); + + } + }; + + /** + * The purpose of this class is to make the tests look like the old + * comments. The first example + * {@link TestASTStaticJoinOptimizer#test_simpleOptional01A()} is based on + * the comments of + * {@link TestASTStaticJoinOptimizer#test_simpleOptional01()} and + * demonstrates that the comment is out of date. + * + * NB: Given this goal, several Java naming conventions are ignored. e.g. + * methods whose names are ALLCAPS or the same as ClassNames + * + * Also, note that the intent is that this class be used in + * anonymous subclasses with a single invocation of the {@link #test()} method, + * and the two fields {@link #given} and {@link #expected} initialized + * in the subclasses constructor (i.e. inside a second pair of braces). + * + * All of the protected members are wrappers around constructors, + * to allow the initialization of these two fields, to have a style + * much more like Prolog than Java. + * + * @author jeremycarroll + * + */ + @SuppressWarnings("rawtypes") + public abstract class Helper { + protected QueryRoot given, expected; + /** + * Variables + */ + protected final String w = "w", x = "x", y = "y", z = "z"; + /** + * Constants ... + */ + protected final IV a = iv("a"), b = iv("b"), c = iv("c"), d = iv("d"), + e = iv("e"), f = iv("f"), g = iv("g"), h = iv("h"); + private VarNode rightVar; + private VarNode leftVar; + int varCount = 0; + + private IV iv(String id) { + return makeIV(new URIImpl("http://example/" + id)); + } + + protected QueryRoot select(VarNode[] varNodes, + NamedSubqueryRoot namedSubQuery, JoinGroupNode where, + HelperFlag... flags) { + QueryRoot rslt = select(varNodes, where, flags); + rslt.getNamedSubqueriesNotNull().add(namedSubQuery); + return rslt; + } + + protected QueryRoot select(VarNode[] varNodes, JoinGroupNode where, + HelperFlag... flags) { + + QueryRoot select = new QueryRoot(QueryType.SELECT); + final ProjectionNode projection = new ProjectionNode(); + for (VarNode varNode : varNodes) + projection.addProjectionVar(varNode); + + select.setProjection(projection); + select.setWhereClause(where); + for (HelperFlag flag : flags) + flag.apply(select); + return select; + } + + protected QueryRoot select(VarNode varNode, + NamedSubqueryRoot namedSubQuery, JoinGroupNode where, + HelperFlag... flags) { + return select(new VarNode[] { varNode }, namedSubQuery, where, + flags); + } + + protected QueryRoot select(VarNode varNode, JoinGroupNode where, + HelperFlag... flags) { + return select(new VarNode[] { varNode }, where, flags); + } + + protected NamedSubqueryRoot namedSubQuery(String name, VarNode varNode, + JoinGroupNode where) { + final NamedSubqueryRoot namedSubquery = new NamedSubqueryRoot( + QueryType.SELECT, name); + final ProjectionNode projection = new ProjectionNode(); + namedSubquery.setProjection(projection); + projection.addProjectionExpression(new AssignmentNode(varNode, + new VarNode(varNode))); + namedSubquery.setWhereClause(where); + return namedSubquery; + } + + protected GroupMemberNodeBase namedSubQueryInclude(String name) { + return new NamedSubqueryInclude(name); + } + + protected VarNode leftVar() { + leftVar = newAlppVar("-tVarLeft-",leftVar); + return leftVar; + } + protected VarNode rightVar() { + rightVar = newAlppVar("-tVarRight-",rightVar); + return rightVar; + } + + private VarNode newAlppVar(String prefix,VarNode v) { + if (v != null) { + return v; + } + v = varNode(prefix+varCount++); + v.setAnonymous(true); + return v ; + + } + + protected ArbitraryLengthPathNode arbitartyLengthPropertyPath(TermNode left, TermNode right, + HelperFlag card, JoinGroupNode joinGroupNode) { + assert leftVar != null; + assert rightVar != null; + ArbitraryLengthPathNode rslt = new ArbitraryLengthPathNode(left, right, leftVar, rightVar, PathMod.ONE_OR_MORE); + card.apply(rslt); + rslt.setArg(0, joinGroupNode); + leftVar = null; + rightVar = null; + return rslt; + } + + + protected VarNode[] varNodes(String... names) { + VarNode rslt[] = new VarNode[names.length]; + for (int i = 0; i < names.length; i++) + rslt[i] = varNode(names[i]); + return rslt; + } + + protected VarNode varNode(String varName) { + return new VarNode(varName); + } + + protected TermNode constantNode(IV iv) { + return new ConstantNode(iv); + } + protected TermNode constantNode(String c) { + return new ConstantNode(iv(c)); + } + + protected PropertyPathNode propertyPathNode(final TermNode s, String pattern, final TermNode o) { + return new PropertyPathNode(s, pathNode(pattern), o); + } + + /** + * This method is only implemented in part. The issue is what patterns are supported. + * The desired support as of the intended contract of this method is that pattern + * can be any sparql property path expression without any whitespace, and where + * every property in the path is reduced to a single letter a-z. + * e.g. "(a/b?/c)+|a|c*" + * + * The current support is that parenthesis, alternatives and negated properties are not supported. + * + * @param pattern + * @return + */ + protected PathNode pathNode(String pattern) { + final String seq[] = pattern.split("/"); + final PathElt elements[] = new PathElt[seq.length]; + PathMod mod = null; + for (int i =0;i<seq.length;i++) { + final String s = seq[i]; + boolean inverse = s.charAt(0)=='^'; + switch (s.charAt(s.length()-1)) { + case '*': + mod = PathMod.ZERO_OR_MORE; + break; + case '+': + mod = PathMod.ONE_OR_MORE; + break; + case '?': + mod = PathMod.ZERO_OR_ONE; + break; + } + String c = s.substring(inverse?1:0,s.length() - (mod!=null?1:0)); + elements[i] = new PathElt(constantNode(c),inverse,mod); + + } + return new PathNode(new PathAlternative(new PathSequence(elements))); + } + + /** + * Create a statement pattern node. The additional arguments after the s, p, o, + * are: + * <ol> + * <li>A context node: must be first (i.e. fourth)</li> + * <li>integer cardinality</li> + * <li>HelperFlag's</li> + * </ol> + * @param s + * @param p + * @param o + * @param more + * @return + */ + protected StatementPatternNode statementPatternNode(TermNode s, + TermNode p, TermNode o, Object ... more) { + StatementPatternNode rslt = newStatementPatternNode(s, p, o); + if (more.length>0) { + int i = 0; + if (more[0] instanceof TermNode) { + rslt.setC((TermNode)more[0]); + i = 1; + } + for (;i<more.length;i++) { + if (more[i] instanceof Integer) { + rslt.setProperty(Annotations.ESTIMATED_CARDINALITY, Long.valueOf((int)more[i])); + } else { + HelperFlag flag = (HelperFlag)more[i]; + flag.apply(rslt); + } + } + } + return rslt; + } + + @SuppressWarnings("unchecked") + private <E extends IGroupMemberNode, T extends GraphPatternGroup<E>> T initGraphPatternGroup( + T rslt, Object... statements) { + for (Object mem : statements) { + if (mem instanceof IGroupMemberNode) { + rslt.addChild((E) mem); + } else { + ((HelperFlag) mem).apply(rslt); + } + } + return rslt; + } + + protected JoinGroupNode joinGroupNode(TermNode context,Object... statements) { + JoinGroupNode rslt = joinGroupNode(statements); + rslt.setContext(context); + return rslt; + } + protected JoinGroupNode joinGroupNode(Object... statements) { + return initGraphPatternGroup(new JoinGroupNode(), statements); + } + + protected PropertyPathUnionNode propertyPathUnionNode(Object... statements) { + return initGraphPatternGroup(new PropertyPathUnionNode(), + statements); + } + + protected UnionNode unionNode(Object... statements) { + return initGraphPatternGroup(new UnionNode(), statements); + + } + + protected JoinGroupNode where(GroupMemberNodeBase... statements) { + return joinGroupNode((Object[]) statements); + } + + public void test() { + final IASTOptimizer rewriter = newOptimizer(); + + final AST2BOpContext context = new AST2BOpContext(new ASTContainer( + given), store); + + final IQueryNode actual = rewriter.optimize(context, given, + new IBindingSet[] {}); + + assertSameAST(expected, actual); + } + } + + public AbstractOptimizerTestCase(String name) { + super(name); + } + + public AbstractOptimizerTestCase() { + super(); + } + + protected StatementPatternNode newStatementPatternNode(final TermNode s, final TermNode p, final TermNode o) { + return newStatementPatternNode(s, p, o, -1, false); + } + protected StatementPatternNode newStatementPatternNode( + final TermNode s, final TermNode p, final TermNode o, + final long cardinality) { + return newStatementPatternNode(s, p, o, cardinality, false); + } + + protected StatementPatternNode newStatementPatternNode( + final TermNode s, final TermNode p, final TermNode o, + final long cardinality, final boolean optional) { + + final StatementPatternNode sp = new StatementPatternNode(s, p, o); + + if (cardinality != -1) { + sp.setProperty(Annotations.ESTIMATED_CARDINALITY, cardinality); + } + + if (optional) { + + sp.setOptional(true); + + } + + return sp; + + } + + abstract IASTOptimizer newOptimizer() ; +} Added: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestALPPinTrac773.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestALPPinTrac773.java (rev 0) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestALPPinTrac773.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -0,0 +1,350 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2013. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ + +package com.bigdata.rdf.sparql.ast.optimizers; + +import static com.bigdata.rdf.sparql.ast.optimizers.AbstractOptimizerTestCase.HelperFlag.*; + +import com.bigdata.rdf.internal.IV; +import com.bigdata.rdf.sparql.ast.ArbitraryLengthPathNode; +import com.bigdata.rdf.sparql.ast.StatementPatternNode; +import com.bigdata.rdf.sparql.ast.VarNode; +import com.bigdata.rdf.store.AbstractTripleStore; + +/** + * Trac733 shows some strange behavior, this test case is intended + * to explore that. + * + * The basic issues concerns the order of execution of arbitrary length propery + * paths and other bits of the query. The observed behavior was that + * adding additional braces, changing the grouping had surprising effects, + * and that the default choice of order was often poor. + * + * With this first commit we capture the incorrect behavior. + * + */ +public class TestALPPinTrac773 extends AbstractOptimizerTestCase { + + private class NotNestedHelper extends Helper { + public NotNestedHelper(HelperFlag zero_or_one_to_one_or_more, String sym) { + String pattern = "c" + sym; + + given = select( varNode(z), + where ( + + joinGroupNode(propertyPathNode(varNode(x),pattern, constantNode(b))), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + propertyPathNode(varNode(x),pattern, varNode(z)), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054) + ) ); + + varCount = 0; + // we have to evaluate this one earlier in order to get the anonymous variable numbering + // lined up. Really we should compare the result with expected wise to + // the unimportance of the name of anonymous variables. + ArbitraryLengthPathNode alpp = arbitartyLengthPropertyPath(varNode(x), varNode(z), zero_or_one_to_one_or_more, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ); + expected = select( varNode(z), + where ( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), zero_or_one_to_one_or_more, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ), + alpp, + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431) + ) ); + varCount = 0; + + } + } + private class NestedHelper extends Helper { + + public NestedHelper(HelperFlag zero_or_one_to_one_or_more, String sym) { + String pattern = "c" + sym; + + given = select( varNode(z), + where ( + joinGroupNode(propertyPathNode(varNode(x),pattern, constantNode(b))), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + joinGroupNode(propertyPathNode(varNode(x),pattern, varNode(z))), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054) + ) ); + + varCount = 0; + expected = select( varNode(z), + where ( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), zero_or_one_to_one_or_more, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ), + arbitartyLengthPropertyPath(varNode(x), varNode(z), zero_or_one_to_one_or_more, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431) + ) ); + varCount = 0; + + } + } + public TestALPPinTrac773() { + } + + public TestALPPinTrac773(String name) { + super(name); + } + @Override + IASTOptimizer newOptimizer() { + return new ASTOptimizerList( + new ASTPropertyPathOptimizer() { + private int counter = 0; + + @Override + protected VarNode anonVar(final String anon) { + VarNode v = new VarNode(anon+counter++); + v.setAnonymous(true); + return v; + } + }, + new ASTRangeCountOptimizer(){ + @Override + + + protected void estimateCardinalities(StatementPatternNode sp, final IV<?, ?> s, final IV<?, ?> p, + final IV<?, ?> o, final IV<?, ?> c, final AbstractTripleStore db) { + if (o != null) + sp.setProperty(Annotations.ESTIMATED_CARDINALITY, 26l); + else + sp.setProperty(Annotations.ESTIMATED_CARDINALITY, 3135l); + } + + }, + new ASTFlattenJoinGroupsOptimizer(), + new ASTStaticJoinOptimizer()); + } + + + public void testSimpleALPP() { + + new Helper(){{ + + given = select( varNode(x), + where ( + joinGroupNode( + propertyPathNode(varNode(x),"c*", constantNode(b)) + ) + ) ); + + + expected = select( varNode(x), + where ( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ) + ) ); + + }}.test(); + } + public void testNestedPartway() { + + new Helper(){{ + + given = select( varNode(z), + where ( + joinGroupNode( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ) + + ), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + joinGroupNode( + arbitartyLengthPropertyPath(varNode(x), varNode(z), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ) + + ), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054) + ) ); + + varCount = 0; + expected = select( varNode(z), + where ( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + arbitartyLengthPropertyPath(varNode(x), varNode(z), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054) + ) ); + + }}.test(); + } + public void testNotNestedPartway() { + + new Helper(){{ + + given = select( varNode(z), + where ( + joinGroupNode( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ) + + ), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + arbitartyLengthPropertyPath(varNode(x), varNode(z), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054) + ) ); + + varCount = 0; + expected = select( varNode(z), + where ( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + arbitartyLengthPropertyPath(varNode(x), varNode(z), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054) + ) ); + + }}.test(); + } + public void testNestedStar() { + + new NestedHelper(ZERO_OR_MORE,"*"){{ + // currently not correctly optimized. + // TODO: this expected result is incorrect. + + expected = select( varNode(z), + where ( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + arbitartyLengthPropertyPath(varNode(x), varNode(z), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054) + ) ); + + }}.test(); + } + public void testNotNestedStar() { + new NotNestedHelper(ZERO_OR_MORE,"*"){{ + // currently not correctly optimized. + // TODO: this expected result is incorrect. + + ArbitraryLengthPathNode alpp = arbitartyLengthPropertyPath(varNode(x), varNode(z), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ); + expected = select( varNode(z), + where ( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), ZERO_OR_MORE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054), + alpp + ) ); + + }}.test(); + } + public void testNestedPlus() { + + new NestedHelper(ONE_OR_MORE,"+").test(); + } + public void testNotNestedPlus() { + + new NotNestedHelper(ONE_OR_MORE,"+").test(); + } + public void testNestedQuestionMark() { + + new NestedHelper(ZERO_OR_ONE,"?"){{ + // currently not correctly optimized. + // TODO: this expected result is incorrect. + + expected = select( varNode(z), + where ( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), ZERO_OR_ONE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + arbitartyLengthPropertyPath(varNode(x), varNode(z), ZERO_OR_ONE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054) + ) ); + + }}.test(); + } + public void testNotNestedQuestionMark() { + + new NotNestedHelper(ZERO_OR_ONE,"?"){{ + // currently not correctly optimized. + // TODO: this expected result is incorrect. + + ArbitraryLengthPathNode alpp = arbitartyLengthPropertyPath(varNode(x), varNode(z), ZERO_OR_ONE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 3135) + ) ); + expected = select( varNode(z), + where ( + arbitartyLengthPropertyPath(varNode(x), constantNode(b), ZERO_OR_ONE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar(), 26) + ) ), + statementPatternNode(varNode(y), constantNode(c), varNode(x), 15431), + statementPatternNode(varNode(z), constantNode(a), varNode(w), 2054), + alpp + ) ); + + }}.test(); + } +} Added: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTFlattenJoinGroupsOptimizer.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTFlattenJoinGroupsOptimizer.java (rev 0) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTFlattenJoinGroupsOptimizer.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -0,0 +1,123 @@ +/** + +Copyright (C) SYSTAP, LLC 2006-2013. All rights reserved. + +Contact: + SYSTAP, LLC + 4501 Tower Road + Greensboro, NC 27410 + lic...@bi... + +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 +*/ + +package com.bigdata.rdf.sparql.ast.optimizers; + +import static com.bigdata.rdf.sparql.ast.optimizers.AbstractOptimizerTestCase.HelperFlag.*; + + +public class TestASTFlattenJoinGroupsOptimizer extends AbstractOptimizerTestCase { + + public TestASTFlattenJoinGroupsOptimizer(String name) { + super(name); + } + + public TestASTFlattenJoinGroupsOptimizer() { + } + @Override + IASTOptimizer newOptimizer() { + return new ASTFlattenJoinGroupsOptimizer(); + } + + public void testBasicFlattening() { + + new Helper(){{ + + given = select( varNode(z), + where ( + joinGroupNode( + statementPatternNode(varNode(x), constantNode(c), constantNode(d)), + joinGroupNode( statementPatternNode(varNode(x), constantNode(e), varNode(z)) ), + joinGroupNode( statementPatternNode(varNode(x), constantNode(f), varNode(z)) ) + ) + ), + DISTINCT ); + + + expected = select( varNode(z), + where ( + statementPatternNode(varNode(x), constantNode(c), constantNode(d)), + statementPatternNode(varNode(x), constantNode(e), varNode(z)), + statementPatternNode(varNode(x), constantNode(f), varNode(z)) + ), + DISTINCT ); + + }}.test(); + } + public void testContextChange() { + + new Helper(){{ + + given = select( varNode(z), + where ( + joinGroupNode( + statementPatternNode(varNode(x), constantNode(c), constantNode(d)), + joinGroupNode( varNode(w), + statementPatternNode(varNode(x), constantNode(e), varNode(z), varNode(w), NAMED_CONTEXTS) ), + joinGroupNode( statementPatternNode(varNode(x), constantNode(f), varNode(z), DEFAULT_CONTEXTS) ) + ) + ), + DISTINCT ); + + + expected = select( varNode(z), + where ( + statementPatternNode(varNode(x), constantNode(c), constantNode(d)), + statementPatternNode(varNode(x), constantNode(e), varNode(z), varNode(w), NAMED_CONTEXTS), + statementPatternNode(varNode(x), constantNode(f), varNode(z), DEFAULT_CONTEXTS) + ), + DISTINCT ); + + }}.test(); + } + + public void testSingleALPP() { + + new Helper(){{ + + given = select( varNode(z), + where ( + joinGroupNode( + arbitartyLengthPropertyPath(varNode(x), varNode(y), ZERO_OR_ONE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar()) + ) ) + + ) + ) ); + + varCount = 0; + + expected = select( varNode(z), + where ( + arbitartyLengthPropertyPath(varNode(x), varNode(y), ZERO_OR_ONE, + joinGroupNode( + statementPatternNode(leftVar(), constantNode(c), rightVar()) + ) ) + ) ); + + }}.test(); + } + +} Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTStaticJoinOptimizer.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTStaticJoinOptimizer.java 2013-11-15 18:31:16 UTC (rev 7557) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestASTStaticJoinOptimizer.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -32,225 +32,36 @@ import org.openrdf.model.vocabulary.RDF; import com.bigdata.bop.IBindingSet; -import com.bigdata.bop.ModifiableBOpBase; import com.bigdata.rdf.internal.IV; -import com.bigdata.rdf.sparql.ast.ASTBase; import com.bigdata.rdf.sparql.ast.ASTContainer; -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.GraphPatternGroup; -import com.bigdata.rdf.sparql.ast.GroupMemberNodeBase; -import com.bigdata.rdf.sparql.ast.IGroupMemberNode; 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.QueryHints; 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.TermNode; -import com.bigdata.rdf.sparql.ast.UnionNode; import com.bigdata.rdf.sparql.ast.VarNode; import com.bigdata.rdf.sparql.ast.eval.AST2BOpContext; import com.bigdata.rdf.sparql.ast.service.ServiceNode; import com.bigdata.rdf.store.BDS; -import com.bigdata.rdf.sparql.ast.PropertyPathUnionNode; +import static com.bigdata.rdf.sparql.ast.optimizers.AbstractOptimizerTestCase.HelperFlag.*; /** * Test suite for {@link ASTStaticJoinOptimizer}. */ -public class TestASTStaticJoinOptimizer extends AbstractASTEvaluationTestCase { +public class TestASTStaticJoinOptimizer extends AbstractOptimizerTestCase +{ - public interface Annotations extends - com.bigdata.rdf.sparql.ast.GraphPatternGroup.Annotations, - com.bigdata.rdf.sparql.ast.eval.AST2BOpBase.Annotations { - } - enum HelperFlag { - OPTIONAL { - @Override - public void apply(ASTBase sp) { - ((ModifiableBOpBase) sp) - .setProperty(Annotations.OPTIONAL, true); - } - }, - DISTINCT { - @Override - public void apply(ASTBase rslt) { - ((QueryBase) rslt).getProjection().setDistinct(true); - } - }; - - /** - * - * @param target - * @throws ClassCastException - * If there is a mismatch between the flag and its usage. - */ - abstract public void apply(ASTBase target); - }; - - /** - * The purpose of this class is to make the tests look like the old - * comments. The first example - * {@link TestASTStaticJoinOptimizer#test_simpleOptional01A()} is based on - * the comments of - * {@link TestASTStaticJoinOptimizer#test_simpleOptional01()} and - * demonstrates that the comment is out of date. - * - * NB: Given this goal, several Java naming conventions are ignored. e.g. - * methods whose names are ALLCAPS or the same as ClassNames - * - * Also, note that the intent is that this class be used in - * anonymous subclasses with a single invocation of the {@link #test()} method, - * and the two fields {@link #given} and {@link #expected} initialized - * in the subclasses constructor (i.e. inside a second pair of braces). - * - * All of the protected members are wrappers around constructors, - * to allow the initialization of these two fields, to have a style - * much more like Prolog than Java. - * - * @author jeremycarroll - * - */ - @SuppressWarnings("rawtypes") - public abstract class Helper { - protected QueryRoot given, expected; - protected final String w = "w", x = "x", y = "y", z = "z"; - protected final IV a = iv("a"), b = iv("b"), c = iv("c"), d = iv("d"), - e = iv("e"), f = iv("f"), g = iv("g"), h = iv("h"); - - protected final HelperFlag OPTIONAL = HelperFlag.OPTIONAL; - protected final HelperFlag DISTINCT = HelperFlag.DISTINCT; - - private IV iv(String id) { - return makeIV(new URIImpl("http://example/" + id)); - } - - protected QueryRoot select(VarNode[] varNodes, - NamedSubqueryRoot namedSubQuery, JoinGroupNode where, - HelperFlag... flags) { - QueryRoot rslt = select(varNodes, where, flags); - rslt.getNamedSubqueriesNotNull().add(namedSubQuery); - return rslt; - } - - protected QueryRoot select(VarNode[] varNodes, JoinGroupNode where, - HelperFlag... flags) { - - QueryRoot select = new QueryRoot(QueryType.SELECT); - final ProjectionNode projection = new ProjectionNode(); - for (VarNode varNode : varNodes) - projection.addProjectionVar(varNode); - - select.setProjection(projection); - select.setWhereClause(where); - for (HelperFlag flag : flags) - flag.apply(select); - return select; - } - - protected QueryRoot select(VarNode varNode, - NamedSubqueryRoot namedSubQuery, JoinGroupNode where, - HelperFlag... flags) { - return select(new VarNode[] { varNode }, namedSubQuery, where, - flags); - } - - protected QueryRoot select(VarNode varNode, JoinGroupNode where, - HelperFlag... flags) { - return select(new VarNode[] { varNode }, where, flags); - } - - protected NamedSubqueryRoot namedSubQuery(String name, VarNode varNode, - JoinGroupNode where) { - final NamedSubqueryRoot namedSubquery = new NamedSubqueryRoot( - QueryType.SELECT, name); - final ProjectionNode projection = new ProjectionNode(); - namedSubquery.setProjection(projection); - projection.addProjectionExpression(new AssignmentNode(varNode, - new VarNode(varNode))); - - namedSubquery.setWhereClause(where); - return namedSubquery; - } - - protected GroupMemberNodeBase namedSubQueryInclude(String name) { - return new NamedSubqueryInclude(name); - } - - protected VarNode[] varNodes(String... names) { - VarNode rslt[] = new VarNode[names.length]; - for (int i = 0; i < names.length; i++) - rslt[i] = varNode(names[i]); - return rslt; - } - - protected VarNode varNode(String varName) { - return new VarNode(varName); - } - - protected TermNode constantNode(IV iv) { - return new ConstantNode(iv); - } - - protected StatementPatternNode statementPatternNode(TermNode s, - TermNode p, TermNode o, long cardinality, HelperFlag... flags) { - StatementPatternNode rslt = newStatementPatternNode(s, p, o, - cardinality); - for (HelperFlag flag : flags) { - flag.apply(rslt); - } - return rslt; - } - - @SuppressWarnings("unchecked") - private <E extends IGroupMemberNode, T extends GraphPatternGroup<E>> T initGraphPatternGroup( - T rslt, Object... statements) { - for (Object mem : statements) { - if (mem instanceof IGroupMemberNode) { - rslt.addChild((E) mem); - } else { - ((HelperFlag) mem).apply(rslt); - } - } - return rslt; - } - - protected JoinGroupNode joinGroupNode(Object... statements) { - return initGraphPatternGroup(new JoinGroupNode(), statements); - } - - protected PropertyPathUnionNode propertyPathUnionNode( - Object... statements) { - return initGraphPatternGroup(new PropertyPathUnionNode(), - statements); - } - - protected UnionNode unionNode(Object... statements) { - return initGraphPatternGroup(new UnionNode(), statements); - - } - - protected JoinGroupNode where(GroupMemberNodeBase... statements) { - return joinGroupNode((Object[]) statements); - } - - public void test() { - final IASTOptimizer rewriter = new ASTStaticJoinOptimizer(); - - final AST2BOpContext context = new AST2BOpContext(new ASTContainer( - given), store); - - final IQueryNode actual = rewriter.optimize(context, given, - new IBindingSet[] {}); - - assertSameAST(expected, actual); - } + @Override + protected ASTStaticJoinOptimizer newOptimizer() { + return new ASTStaticJoinOptimizer(); } + public void test_simpleOptional01A() { new Helper() {{ given = select( varNode(x), @@ -281,6 +92,7 @@ * */ public TestASTStaticJoinOptimizer() { + super(); } /** @@ -1911,14 +1723,7 @@ } - private StatementPatternNode newStatementPatternNode( - final TermNode s, final TermNode p, final TermNode o, - final long cardinality) { - return newStatementPatternNode(s, p, o, cardinality, false); - - } - /* * * prefix skos: <http://www.w3.org/2004/02/skos/core#> @@ -2225,23 +2030,6 @@ } - private StatementPatternNode newStatementPatternNode( - final TermNode s, final TermNode p, final TermNode o, - final long cardinality, final boolean optional) { - - final StatementPatternNode sp = new StatementPatternNode(s, p, o); - - sp.setProperty(Annotations.ESTIMATED_CARDINALITY, cardinality); - - if (optional) { - - sp.setOptional(true); - - } - - return sp; - - } private StatementPatternNode runFirst(final StatementPatternNode sp) { sp.setProperty(QueryHints.RUN_FIRST, true); Modified: branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestAll.java =================================================================== --- branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestAll.java 2013-11-15 18:31:16 UTC (rev 7557) +++ branches/BIGDATA_RELEASE_1_3_0/bigdata-rdf/src/test/com/bigdata/rdf/sparql/ast/optimizers/TestAll.java 2013-11-15 20:19:45 UTC (rev 7558) @@ -138,6 +138,10 @@ // Test suite for resolving mock IVs. suite.addTestSuite(TestASTBatchResolveTermsOptimizer.class); + + suite.addTestSuite(TestASTFlattenJoinGroupsOptimizer.class); + + suite.addTestSuite(TestALPPinTrac773.class); return suite; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |