Skip to content

Commit

Permalink
Merge with 99d6d16cd25cd644a90131948b234fc01881bee9
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Baechle committed Jul 31, 2012
2 parents 3976adc + 9c43096 commit d34081d
Show file tree
Hide file tree
Showing 18 changed files with 230 additions and 86 deletions.
4 changes: 2 additions & 2 deletions src/main/java/org/brackit/xquery/XQuery.java
Expand Up @@ -112,7 +112,7 @@ public void serialize(QueryContext ctx, PrintStream out)

public void serialize(QueryContext ctx, PrintWriter out)
throws QueryException {
Sequence result = run(ctx, false);
Sequence result = run(ctx, true);
if (result == null) {
return;
}
Expand All @@ -122,7 +122,7 @@ public void serialize(QueryContext ctx, PrintWriter out)
}

public void serialize(QueryContext ctx, Serializer serializer) throws QueryException {
Sequence result = run(ctx, false);
Sequence result = run(ctx, true);
if (result == null) {
return;
}
Expand Down
Expand Up @@ -98,9 +98,11 @@ protected AST visit(AST node) {
boolean isLastStep = (i + 1 == stepCount);
if ((!isDescOrDescOSStep) || (isLastStep)) {
step.setProperty("skipDDO", Boolean.TRUE);
}
if (isDescOrDescOSStep) {
// be conservative:
// stop trying to skip DDO after a '//'
break;
return node;
}
} else if (isBackwardStep(step)) {

Expand Down
@@ -0,0 +1,79 @@
/*
* [New BSD License]
* Copyright (c) 2011-2012, Brackit Project Team <info@brackit.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Brackit Project Team nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.brackit.xquery.compiler.optimizer.walker.topdown;

import static org.brackit.xquery.module.Namespaces.FN_NSURI;
import static org.brackit.xquery.module.Namespaces.FN_PREFIX;

import org.brackit.xquery.atomic.QNm;
import org.brackit.xquery.compiler.AST;
import org.brackit.xquery.compiler.XQ;

/**
* @author Sebastian Baechle
*
*/
public abstract class AggFunChecker extends ScopeWalker {

protected static final QNm FN_COUNT = new QNm(FN_NSURI, FN_PREFIX, "count");
protected static final QNm FN_SUM = new QNm(FN_NSURI, FN_PREFIX, "sum");
protected static final QNm FN_AVG = new QNm(FN_NSURI, FN_PREFIX, "avg");
protected static final QNm FN_MIN = new QNm(FN_NSURI, FN_PREFIX, "min");
protected static final QNm FN_MAX = new QNm(FN_NSURI, FN_PREFIX, "max");
protected static final QNm[] aggFuns = new QNm[] { FN_COUNT, FN_SUM, FN_AVG,
FN_MIN, FN_MAX };
protected static final int[] aggFunMap = new int[] { XQ.CountAgg, XQ.SumAgg,
XQ.AvgAgg, XQ.MinAgg, XQ.MaxAgg };


protected QNm replaceRef(AST node, QNm name) {
node.getParent().replaceChild(node.getChildIndex(),
new AST(XQ.VariableRef, name));
return name;
}

protected int aggFunType(int type) {
switch (type) {
case XQ.CountAgg:
return 0;
case XQ.SumAgg:
return 1;
case XQ.AvgAgg:
return 2;
case XQ.MinAgg:
return 3;
case XQ.MaxAgg:
return 4;
case XQ.SequenceAgg:
default:
throw new RuntimeException("Unexpected aggregate function type: "
+ type);
}
}

}
Expand Up @@ -27,8 +27,6 @@
*/
package org.brackit.xquery.compiler.optimizer.walker.topdown;

import static org.brackit.xquery.module.Namespaces.FN_NSURI;
import static org.brackit.xquery.module.Namespaces.FN_PREFIX;

import java.util.Map;

Expand All @@ -51,38 +49,21 @@
* @author Sebastian Baechle
*
*/
public class GroupByAggregates extends ScopeWalker {

private static final QNm FN_COUNT = new QNm(FN_NSURI, FN_PREFIX, "count");
private static final QNm FN_SUM = new QNm(FN_NSURI, FN_PREFIX, "sum");
private static final QNm FN_AVG = new QNm(FN_NSURI, FN_PREFIX, "avg");
private static final QNm FN_MIN = new QNm(FN_NSURI, FN_PREFIX, "min");
private static final QNm FN_MAX = new QNm(FN_NSURI, FN_PREFIX, "max");

private static final QNm[] aggFuns = new QNm[] { FN_COUNT, FN_SUM, FN_AVG,
FN_MIN, FN_MAX };

private static final int[] aggFunMap = new int[] { XQ.CountAgg, XQ.SumAgg,
XQ.AvgAgg, XQ.MinAgg, XQ.MaxAgg };
public class GroupByAggregates extends AggFunChecker {

@Override
protected AST visit(AST node) {
if (node.getType() != XQ.GroupBy) {
return node;
}

boolean skipUnspecified = false;
AST dftAgg = node.getChild(node.getChildCount() - 2);
AST dftAggType = dftAgg.getChild(0);
if (dftAggType.getType() == XQ.SequenceAgg) {
// Switch to aggregate type "single" as new default.
// This reduces the grouping overhead for variables
// which are not accessed at all.
dftAgg.replaceChild(0, new AST(XQ.SingleAgg));
} else if (dftAggType.getType() == XQ.SingleAgg) {
// Consider only variables which already have a special
// aggregation spec
skipUnspecified = true;
} else {
// There's already a specialized aggregation type in place.
// It seems unlikely that further optimization is necessary
Expand All @@ -96,11 +77,7 @@ protected AST visit(AST node) {
for (Var var : findScope(node).localBindings()) {
AST aggSpec = findAggSpec(node, var);
if (aggSpec == null) {
if (skipUnspecified) {
continue;
} else {
aggSpec = addAggSpec(node, var);
}
aggSpec = addAggSpec(node, var);
}
VarRef refs = findVarRefs(var, node.getLastChild());
if (refs != null) {
Expand Down Expand Up @@ -242,31 +219,6 @@ private AST createBinding(QNm subsitute, int type) {
return agg;
}

private QNm replaceRef(AST node, QNm name) {
node.getParent().replaceChild(node.getChildIndex(),
new AST(XQ.VariableRef, name));
return name;
}

private int aggFunType(int type) {
switch (type) {
case XQ.CountAgg:
return 0;
case XQ.SumAgg:
return 1;
case XQ.AvgAgg:
return 2;
case XQ.MinAgg:
return 3;
case XQ.MaxAgg:
return 4;
case XQ.SequenceAgg:
default:
throw new RuntimeException("Unexpected aggregate function type: "
+ type);
}
}

public static void main(String[] args) throws QueryException {
DefaultOptimizer.UNNEST = false;
CompileChain cc = new CompileChain() {
Expand Down
Expand Up @@ -65,6 +65,9 @@ protected AST visit(AST join) {
AST newLeftInEnd = findEnd(newLeftIn);
AST ljoin = rightIn.copy();
ljoin.setProperty("leftJoin", Boolean.TRUE);
if (join.checkProperty("skipSort")) {
ljoin.setProperty("skipSort", Boolean.TRUE);
}
ljoin.addChild(rightIn.getChild(0).copyTree());
ljoin.addChild(rightIn.getChild(1).copyTree());
AST outStart = new AST(XQ.Start);
Expand Down
Expand Up @@ -52,7 +52,7 @@ protected AST visit(AST join) {
anc.replaceChild(parentJoin.getChildIndex(), join);
AST out = join.getLastChild();
join.replaceChild(3, parentJoin);
parentJoin.replaceChild(1, out);
parentJoin.getChild(1).replaceChild(0, out);

return anc;
}
Expand Down
Expand Up @@ -37,7 +37,7 @@
* @author Sebastian Baechle
*
*/
public class LetBindToLeftJoin extends ScopeWalker {
public class LetBindToLeftJoin extends AggFunChecker {

@Override
protected AST visit(AST node) {
Expand Down Expand Up @@ -91,13 +91,19 @@ private AST convertToLeftJoin(AST let) {
rlet.addChild(letVarBinding);
rlet.addChild(letReturn);
QNm letVar = (QNm) letVarBinding.getChild(0).getValue();
AST groupBy = createGroupBy(letVar);
AST groupBy = createGroupBy(letVar, let);
rlet.addChild(groupBy);

post.addChild(rlet);

// finally assemble left join
AST ljoin = createJoin(leftIn, rightIn, post, let.getLastChild().copyTree());

// we must not sort if result is directly aggregated
boolean skipSort = (groupBy.getChild(1).getChild(0).getType() != XQ.SequenceAgg);
if (skipSort) {
ljoin.setProperty("skipSort", Boolean.TRUE);
}

int replaceAt = insertJoinAfter.getChildCount() - 1;
insertJoinAfter.replaceChild(replaceAt, ljoin);
Expand All @@ -118,13 +124,38 @@ private AST createJoin(AST leftIn, AST rightIn, AST post, AST out) {
return ljoin;
}

private AST createGroupBy(QNm letVar) {
private AST createGroupBy(QNm letVar, AST letBind) {
int aggType = XQ.SequenceAgg;

Var var = findScope(letBind).localBindings().get(0);
VarRef refs = findVarRefs(var, letBind.getLastChild());
if (refs == null) {
// TODO Unused variable???? SingleAgg OK but currently causes errors
// in GroupByAggregates....
// aggType = XQ.SingleAgg;
} else if (refs.next != null) {
// TODO optimize me
} else {
AST p = refs.ref.getParent();
if (p.getType() == XQ.FunctionCall) {
QNm fun = (QNm) p.getValue();
for (int i = 0; i < aggFuns.length; i++) {
QNm aggFun = aggFuns[i];
if (fun.atomicCmp(aggFun) == 0) {
replaceRef(p, letVar);
aggType = aggFunMap[i];
break;
}
}
}
}

AST groupBy = new AST(XQ.GroupBy);
groupBy.setProperty("sequential", Boolean.TRUE);

AST aggSpec = new AST(XQ.AggregateSpec);
aggSpec.addChild(new AST(XQ.VariableRef, letVar));
aggSpec.addChild(createBinding(letVar, XQ.SequenceAgg));
aggSpec.addChild(createBinding(letVar, aggType));
groupBy.addChild(aggSpec);

AST dftAgg = new AST(XQ.DftAggregateSpec);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/brackit/xquery/expr/Accessor.java
Expand Up @@ -372,6 +372,7 @@ public abstract Stream<? extends Node<?>> performStep(Node<?> node)

public Stream<? extends Node<?>> performStep(Node<?> node, NodeType test)
throws QueryException {
return new KindFilter(test, performStep(node));
Stream<? extends Node<?>> s = node.performStep(axis, test);
return (s != null) ? s : new KindFilter(test, performStep(node));
}
}
8 changes: 8 additions & 0 deletions src/main/java/org/brackit/xquery/node/AbstractNode.java
Expand Up @@ -35,13 +35,15 @@
import org.brackit.xquery.node.stream.filter.Filter;
import org.brackit.xquery.node.stream.filter.FilteredStream;
import org.brackit.xquery.xdm.AbstractItem;
import org.brackit.xquery.xdm.Axis;
import org.brackit.xquery.xdm.DocumentException;
import org.brackit.xquery.xdm.Kind;
import org.brackit.xquery.xdm.Node;
import org.brackit.xquery.xdm.Stream;
import org.brackit.xquery.xdm.Type;
import org.brackit.xquery.xdm.type.ElementType;
import org.brackit.xquery.xdm.type.ItemType;
import org.brackit.xquery.xdm.type.NodeType;

/**
*
Expand Down Expand Up @@ -170,6 +172,12 @@ public ItemType itemType() throws DocumentException {
}
}

@Override
public Stream<? extends Node<?>> performStep(Axis axis, NodeType test)
throws DocumentException {
return null;
}

@Override
public Atomic atomize() throws QueryException {
return getValue();
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/org/brackit/xquery/operator/GroupBy.java
Expand Up @@ -98,9 +98,7 @@ public Tuple next(QueryContext ctx) throws QueryException {

// pass through
if ((check) && (dead(t))) {
grp.add(t);
Tuple emit = grp.emit();
grp.clear();
Tuple emit = grp.singleEmit(t);
return emit;
}

Expand Down Expand Up @@ -289,9 +287,7 @@ public Tuple next(QueryContext ctx) throws QueryException {
if ((check) && (dead(t))) {
if (grp.getSize() == 0) {
next = null;
grp.add(t);
Tuple emit = grp.emit();
grp.clear();
Tuple emit = grp.singleEmit(t);
return emit;
} else {
// keep next and output grouping map first
Expand Down
Expand Up @@ -39,4 +39,5 @@ public interface Aggregator {

public void add(Sequence seq) throws QueryException;

public void clear();
}
Expand Up @@ -59,4 +59,9 @@ public void add(Sequence seq) throws QueryException {
count = (IntNumeric) count.add(seq.size());
}
}

@Override
public void clear() {
count = Int32.ZERO;
}
}

0 comments on commit d34081d

Please sign in to comment.