forked from eXist-db/exist
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[refactor] Refactor the predicate position() optimisation into a Quer…
…yRewriter
- Loading branch information
1 parent
0436210
commit fed5617
Showing
2 changed files
with
78 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
exist-core/src/main/java/org/exist/xquery/PositionalPredicateRewriter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright (c) 2014, Evolved Binary Ltd | ||
*/ | ||
package org.exist.xquery; | ||
|
||
import com.evolvedbinary.j8fu.tuple.Tuple2; | ||
import org.exist.xquery.functions.fn.FunPosition; | ||
import org.exist.xquery.value.Type; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
import static com.evolvedbinary.j8fu.tuple.Tuple.Tuple; | ||
|
||
/** | ||
* Rewrite position() withing a predicate to a POSITIONAL version of the predicate where possible. | ||
* | ||
* @author <a href="mailto:[email protected]">Adam Retter</a> | ||
*/ | ||
public class PositionalPredicateRewriter extends QueryRewriter { | ||
|
||
public PositionalPredicateRewriter(final XQueryContext context) { | ||
super(context); | ||
} | ||
|
||
@Override | ||
public Pragma rewriteLocationStep(final LocationStep locationStep) throws XPathException { | ||
|
||
@Nullable final Predicate[] predicates = locationStep.getPredicates(); | ||
if (predicates != null) { | ||
for (final Predicate predicate : predicates) { | ||
@Nullable final Tuple2<Expression, LiteralValue> predicateOptimizableInnerExpr = canOptimizeToPositionalPredicate(predicate); | ||
if (predicateOptimizableInnerExpr != null) { | ||
predicate.replace(predicateOptimizableInnerExpr._1, predicateOptimizableInnerExpr._2); | ||
} | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
* Test whether we can optimise position() withing a predicate to a POSITIONAL version of a predicate. | ||
* | ||
* @param predicate the predicate to test | ||
* | ||
* @return the inner expr to be replaced and the literal value to replace it with if it can be optimised, null otherwise. | ||
*/ | ||
private @Nullable Tuple2<Expression, LiteralValue> canOptimizeToPositionalPredicate(final Predicate predicate) { | ||
if (predicate.getSubExpressionCount() == 1) { | ||
final org.exist.xquery.Expression predInnerExpr = predicate.getSubExpression(0); | ||
if (predInnerExpr instanceof final ValueComparison valueComparison && valueComparison.getRelation() == Constants.Comparison.EQ) { | ||
final org.exist.xquery.Expression left = valueComparison.getLeft(); | ||
final org.exist.xquery.Expression right = valueComparison.getRight(); | ||
|
||
if (left instanceof final InternalFunctionCall leftInternalFunctionCall && leftInternalFunctionCall.getFunction() instanceof FunPosition | ||
&& right instanceof final org.exist.xquery.LiteralValue rightLiteralValue && rightLiteralValue.returnsType() == Type.INTEGER) { | ||
|
||
// NOTE(AR) if the predicate is like [position() eq 1] or [position() = 1] then we could rewrite it to [1] | ||
return Tuple(predInnerExpr, rightLiteralValue); | ||
|
||
} else if (left instanceof final org.exist.xquery.LiteralValue leftLiteralValue && leftLiteralValue.returnsType() == Type.INTEGER | ||
&& right instanceof final InternalFunctionCall rightInternalFunctionCall && rightInternalFunctionCall.getFunction() instanceof FunPosition) { | ||
|
||
// NOTE(AR) if the predicate is like [1 eq position()] or [1 = position()] then we could rewrite it to [1] | ||
return Tuple(predInnerExpr, leftLiteralValue); | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
} |