Unnesting rule and code additions to support XMark Query 8.
Project: http://git-wip-us.apache.org/repos/asf/vxquery/repo Commit: http://git-wip-us.apache.org/repos/asf/vxquery/commit/7fc0d93b Tree: http://git-wip-us.apache.org/repos/asf/vxquery/tree/7fc0d93b Diff: http://git-wip-us.apache.org/repos/asf/vxquery/diff/7fc0d93b Branch: refs/heads/master Commit: 7fc0d93b4f83fa9ead1f053bf041e1b871ee9f33 Parents: 3e40e5a Author: Preston Carman <[email protected]> Authored: Thu Aug 13 14:48:17 2015 -0700 Committer: Preston Carman <[email protected]> Committed: Thu Aug 13 14:48:17 2015 -0700 ---------------------------------------------------------------------- .../java/org/apache/vxquery/cli/VXQuery.java | 54 +- .../compiler/rewriter/RewriteRuleset.java | 50 +- .../rewriter/rules/ConsolidateUnnestsRule.java | 79 +- .../rules/ConvertAssignToUnnestRule.java | 31 +- .../ConvertFromAlgebricksExpressionsRule.java | 33 +- .../ConvertToAlgebricksExpressionsRule.java | 16 +- .../rules/InlineNestedVariablesRule.java | 97 -- .../ExtractFunctionsFromJoinConditionRule.java | 141 ++ .../InlineNestedVariablesRule.java | 97 ++ ...oveFreeVariableOperatorOutOfSubplanRule.java | 178 +++ ...GeneralComparisonScalarEvaluatorFactory.java | 12 +- .../IfThenElseScalarEvaluatorFactory.java | 37 +- .../vxquery/serializer/XMLSerializer.java | 9 +- .../xmlquery/query/XMLQueryCompiler.java | 10 +- .../xmlquery/translator/XMLQueryTranslator.java | 42 +- vxquery-xtest/pom.xml | 1 + vxquery-xtest/results/xqts.txt | 1480 +++++++++--------- .../org/apache/vxquery/xtest/XTestOptions.java | 38 +- .../vxquery/xtest/AbstractXQueryTest.java | 6 +- .../org/apache/vxquery/xtest/VXQueryTest.java | 4 +- .../apache/vxquery/xtest/VXQueryXMarkTest.java | 55 + .../org/apache/vxquery/xtest/XMarkTest.java | 5 +- .../java/org/apache/vxquery/xtest/XQTSTest.java | 2 +- .../Queries/XQuery/XMark/Modified/q08.xq | 2 +- 24 files changed, 1465 insertions(+), 1014 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-cli/src/main/java/org/apache/vxquery/cli/VXQuery.java ---------------------------------------------------------------------- diff --git a/vxquery-cli/src/main/java/org/apache/vxquery/cli/VXQuery.java b/vxquery-cli/src/main/java/org/apache/vxquery/cli/VXQuery.java index 5b99978..cf21c76 100644 --- a/vxquery-cli/src/main/java/org/apache/vxquery/cli/VXQuery.java +++ b/vxquery-cli/src/main/java/org/apache/vxquery/cli/VXQuery.java @@ -77,7 +77,7 @@ public class VXQuery { /** * Constructor to use command line options passed. - * + * * @param opts * Command line options object */ @@ -87,7 +87,7 @@ public class VXQuery { /** * Main method to get command line options and execute query process. - * + * * @param args * @throws Exception */ @@ -134,7 +134,7 @@ public class VXQuery { /** * Creates a new Hyracks connection with: the client IP address and port provided, if IP address is provided in command line. Otherwise create a new virtual * cluster with Hyracks nodes. Queries passed are run either way. After running queries, if a virtual cluster has been created, it is shut down. - * + * * @throws Exception */ private void execute() throws Exception { @@ -160,7 +160,7 @@ public class VXQuery { /** * Reads the contents of the files passed in the list of arguments to a string. If -showquery argument is passed, output the query as string. Run the query * for the string. - * + * * @throws IOException * @throws SystemException * @throws Exception @@ -226,7 +226,7 @@ public class VXQuery { /** * Get cluster node configuration. - * + * * @return Configuration of node controllers as array of Strings. * @throws Exception */ @@ -243,7 +243,7 @@ public class VXQuery { /** * Creates a Hyracks dataset, if not already existing with the job frame size, and 1 reader. Allocates a new buffer of size specified in the frame of Hyracks * node. Creates new dataset reader with the current job ID and result set ID. Outputs the string in buffer for each frame. - * + * * @param spec * JobSpecification object, containing frame size. Current specified job. * @param writer @@ -274,7 +274,7 @@ public class VXQuery { /** * Create a unique result set id to get the correct query back from the cluster. - * + * * @return Result Set id generated with current system time. */ protected ResultSetId createResultSetId() { @@ -284,7 +284,7 @@ public class VXQuery { /** * Start local virtual cluster with cluster controller node and node controller nodes. IP address provided for node controller is localhost. Unassigned ports * 39000 and 39001 are used for client and cluster port respectively. Creates a new Hyracks connection with the IP address and client ports. - * + * * @throws Exception */ public void startLocalHyracks() throws Exception { @@ -317,7 +317,7 @@ public class VXQuery { /** * Shuts down the virtual cluster, along with all nodes and node execution, network and queue managers. - * + * * @throws Exception */ public void stopLocalHyracks() throws Exception { @@ -329,7 +329,7 @@ public class VXQuery { /** * Reads the contents of file given in query into a String. The file is always closed. For XML files UTF-8 encoding is used. - * + * * @param query * The query with filename to be processed * @return UTF-8 formatted query string @@ -341,7 +341,7 @@ public class VXQuery { /** * Save and print out the timing message. - * + * * @param message */ private static void timingMessage(String message) { @@ -353,55 +353,55 @@ public class VXQuery { * Helper class with fields and methods to handle all command line options */ private static class CmdLineOptions { - @Option(name = "-available-processors", usage = "Number of available processors. (default java's available processors)") + @Option(name = "-available-processors", usage = "Number of available processors. (default: java's available processors)") private int availableProcessors = -1; - @Option(name = "-client-net-ip-address", usage = "IP Address of the ClusterController") + @Option(name = "-client-net-ip-address", usage = "IP Address of the ClusterController.") private String clientNetIpAddress = null; - @Option(name = "-client-net-port", usage = "Port of the ClusterController (default 1098)") + @Option(name = "-client-net-port", usage = "Port of the ClusterController. (default: 1098)") private int clientNetPort = 1098; - @Option(name = "-local-node-controllers", usage = "Number of local node controllers (default 1)") + @Option(name = "-local-node-controllers", usage = "Number of local node controllers. (default: 1)") private int localNodeControllers = 1; - @Option(name = "-frame-size", usage = "Frame size in bytes. (default 65,536)") + @Option(name = "-frame-size", usage = "Frame size in bytes. (default: 65,536)") private int frameSize = 65536; - @Option(name = "-join-hash-size", usage = "Join hash size in bytes. (default 67,108,864)") + @Option(name = "-join-hash-size", usage = "Join hash size in bytes. (default: 67,108,864)") private long joinHashSize = -1; - @Option(name = "-maximum-data-size", usage = "Maximum possible data size in bytes. (default 150,323,855,000)") + @Option(name = "-maximum-data-size", usage = "Maximum possible data size in bytes. (default: 150,323,855,000)") private long maximumDataSize = -1; @Option(name = "-buffer-size", usage = "Disk read buffer size in bytes.") private int bufferSize = -1; - @Option(name = "-O", usage = "Optimization Level. Default: Full Optimization") + @Option(name = "-O", usage = "Optimization Level. (default: Full Optimization)") private int optimizationLevel = Integer.MAX_VALUE; - @Option(name = "-showquery", usage = "Show query string") + @Option(name = "-showquery", usage = "Show query string.") private boolean showQuery; - @Option(name = "-showast", usage = "Show abstract syntax tree") + @Option(name = "-showast", usage = "Show abstract syntax tree.") private boolean showAST; - @Option(name = "-showtet", usage = "Show translated expression tree") + @Option(name = "-showtet", usage = "Show translated expression tree.") private boolean showTET; - @Option(name = "-showoet", usage = "Show optimized expression tree") + @Option(name = "-showoet", usage = "Show optimized expression tree.") private boolean showOET; - @Option(name = "-showrp", usage = "Show Runtime plan") + @Option(name = "-showrp", usage = "Show Runtime plan.") private boolean showRP; - @Option(name = "-compileonly", usage = "Compile the query and stop") + @Option(name = "-compileonly", usage = "Compile the query and stop.") private boolean compileOnly; - @Option(name = "-repeatexec", usage = "Number of times to repeat execution") + @Option(name = "-repeatexec", usage = "Number of times to repeat execution.") private int repeatExec = 1; - @Option(name = "-timing", usage = "Produce timing information") + @Option(name = "-timing", usage = "Produce timing information.") private boolean timing; @Option(name = "-timing-ignore-queries", usage = "Ignore the first X number of quereies.") http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/RewriteRuleset.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/RewriteRuleset.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/RewriteRuleset.java index 7b55856..c3d0358 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/RewriteRuleset.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/RewriteRuleset.java @@ -22,13 +22,11 @@ import java.util.List; import org.apache.vxquery.compiler.rewriter.rules.ConsolidateDescandantChild; import org.apache.vxquery.compiler.rewriter.rules.ConsolidateAssignAggregateRule; import org.apache.vxquery.compiler.rewriter.rules.ConvertAssignToUnnestRule; -import org.apache.vxquery.compiler.rewriter.rules.ReplaceSourceMapInDocExpression; import org.apache.vxquery.compiler.rewriter.rules.ConvertFromAlgebricksExpressionsRule; import org.apache.vxquery.compiler.rewriter.rules.ConvertToAlgebricksExpressionsRule; import org.apache.vxquery.compiler.rewriter.rules.EliminateSubplanForSingleItemsRule; import org.apache.vxquery.compiler.rewriter.rules.EliminateUnnestAggregateSequencesRule; import org.apache.vxquery.compiler.rewriter.rules.EliminateUnnestAggregateSubplanRule; -import org.apache.vxquery.compiler.rewriter.rules.InlineNestedVariablesRule; import org.apache.vxquery.compiler.rewriter.rules.IntroduceCollectionRule; import org.apache.vxquery.compiler.rewriter.rules.IntroduceTwoStepAggregateRule; import org.apache.vxquery.compiler.rewriter.rules.PushChildIntoDataScanRule; @@ -40,17 +38,24 @@ import org.apache.vxquery.compiler.rewriter.rules.RemoveRedundantPromoteExpressi import org.apache.vxquery.compiler.rewriter.rules.RemoveRedundantTreatExpressionsRule; import org.apache.vxquery.compiler.rewriter.rules.RemoveUnusedSortDistinctNodesRule; import org.apache.vxquery.compiler.rewriter.rules.RemoveUnusedUnnestIterateRule; +import org.apache.vxquery.compiler.rewriter.rules.ReplaceSourceMapInDocExpression; import org.apache.vxquery.compiler.rewriter.rules.SetCollectionDataSourceRule; import org.apache.vxquery.compiler.rewriter.rules.SetVariableIdContextRule; +import org.apache.vxquery.compiler.rewriter.rules.algebricksalternatives.ExtractFunctionsFromJoinConditionRule; +import org.apache.vxquery.compiler.rewriter.rules.algebricksalternatives.InlineNestedVariablesRule; +import org.apache.vxquery.compiler.rewriter.rules.algebricksalternatives.MoveFreeVariableOperatorOutOfSubplanRule; import edu.uci.ics.hyracks.algebricks.core.rewriter.base.HeuristicOptimizer; import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.BreakSelectIntoConjunctsRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.ComplexJoinInferenceRule; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.ComplexUnnestToProductRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.ConsolidateAssignsRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.ConsolidateSelectsRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.CopyLimitDownRule; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.EliminateGroupByEmptyKeyRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.EliminateSubplanRule; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.EliminateSubplanWithInputCardinalityOneRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.EnforceStructuralPropertiesRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.ExtractCommonOperatorsRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.ExtractGbyExpressionsRule; @@ -58,17 +63,21 @@ import edu.uci.ics.hyracks.algebricks.rewriter.rules.FactorRedundantGroupAndDeco import edu.uci.ics.hyracks.algebricks.rewriter.rules.InferTypesRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.InlineAssignIntoAggregateRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.InlineVariablesRule; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.InsertOuterJoinRule; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.IntroJoinInsideSubplanRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.IntroduceAggregateCombinerRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.IntroduceGroupByCombinerRule; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.IntroduceGroupByForSubplanRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.IntroduceProjectsRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.IsolateHyracksOperatorsRule; -import edu.uci.ics.hyracks.algebricks.rewriter.rules.MoveFreeVariableOperatorOutOfSubplanRule; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.NestedSubplanToJoinRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.PullSelectOutOfEqJoin; import edu.uci.ics.hyracks.algebricks.rewriter.rules.PushMapOperatorDownThroughProductRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.PushProjectDownRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.PushProjectIntoDataSourceScanRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.PushSelectDownRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.PushSelectIntoJoinRule; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.PushSubplanIntoGroupByRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.PushSubplanWithAggregateDownThroughProductRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.ReinferAllTypesRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.RemoveRedundantVariablesRule; @@ -76,6 +85,7 @@ import edu.uci.ics.hyracks.algebricks.rewriter.rules.RemoveUnusedAssignAndAggreg import edu.uci.ics.hyracks.algebricks.rewriter.rules.SetAlgebricksPhysicalOperatorsRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.SetExecutionModeRule; import edu.uci.ics.hyracks.algebricks.rewriter.rules.SimpleUnnestToProductRule; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.SubplanOutOfGroupRule; public class RewriteRuleset { /** @@ -98,7 +108,7 @@ public class RewriteRuleset { // TODO Fix the group by operator before putting back in the rule set. // normalization.add(new ConvertAssignSortDistinctNodesToOperatorsRule()); - // Find unnest followed by aggregate in a subplan. + // Find unnest followed by aggregate in a subplan. normalization.add(new EliminateUnnestAggregateSubplanRule()); normalization.add(new RemoveRedundantVariablesRule()); normalization.add(new RemoveUnusedAssignAndAggregateRule()); @@ -199,6 +209,38 @@ public class RewriteRuleset { return typeInfer; } + /** + * Unnest more complex structures. + */ + public final static List<IAlgebraicRewriteRule> buildUnnestingRuleCollection() { + List<IAlgebraicRewriteRule> xquery = new LinkedList<IAlgebraicRewriteRule>(); + + xquery.add(new PushSelectDownRule()); + xquery.add(new SimpleUnnestToProductRule()); + xquery.add(new ComplexUnnestToProductRule()); + xquery.add(new ComplexJoinInferenceRule()); + xquery.add(new PushSelectIntoJoinRule()); + xquery.add(new IntroJoinInsideSubplanRule()); + xquery.add(new PushMapOperatorDownThroughProductRule()); + xquery.add(new PushSubplanWithAggregateDownThroughProductRule()); + xquery.add(new IntroduceGroupByForSubplanRule()); + xquery.add(new SubplanOutOfGroupRule()); + xquery.add(new InsertOuterJoinRule()); + xquery.add(new ExtractFunctionsFromJoinConditionRule()); + + xquery.add(new RemoveRedundantVariablesRule()); + xquery.add(new RemoveUnusedAssignAndAggregateRule()); + + xquery.add(new FactorRedundantGroupAndDecorVarsRule()); + xquery.add(new EliminateSubplanRule()); + xquery.add(new EliminateGroupByEmptyKeyRule()); + xquery.add(new PushSubplanIntoGroupByRule()); + xquery.add(new NestedSubplanToJoinRule()); + xquery.add(new EliminateSubplanWithInputCardinalityOneRule()); + + return xquery; + } + public final static List<IAlgebraicRewriteRule> buildNormalizationRuleCollection() { List<IAlgebraicRewriteRule> normalization = new LinkedList<IAlgebraicRewriteRule>(); normalization.add(new EliminateSubplanRule()); http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConsolidateUnnestsRule.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConsolidateUnnestsRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConsolidateUnnestsRule.java index 6a2bb08..f1b2196 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConsolidateUnnestsRule.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConsolidateUnnestsRule.java @@ -37,26 +37,26 @@ import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.UnnestOpera * operator (2). XQuery unnest operator (1) must have a scalar implementation * of the unnest function. If so the two unnest expressions can be merged * together. - * + * * <pre> - * Before + * Before * * plan__parent * UNNEST( $v2 : uf2( $v1 ) ) * UNNEST( $v1 : uf1( $v0 ) ) * plan__child - * + * * Where $v1 is not used in plan__parent and uf1 is not a descendant expression. - * + * * After * * plan__parent * UNNEST( $v2 : uf2( sf1( $v0 ) ) ) * plan__child - * + * * uf1 becomes sf1 since it changes from unnesting to scalar expression. * </pre> - * + * * @author prestonc */ public class ConsolidateUnnestsRule extends AbstractUsedVariablesProcessingRule { @@ -75,41 +75,42 @@ public class ConsolidateUnnestsRule extends AbstractUsedVariablesProcessingRule } UnnestOperator unnest2 = (UnnestOperator) op2; - if (!usedVariables.contains(unnest2.getVariable())) { - // Check to see if the unnest2 expression has a scalar implementation. - ILogicalExpression logicalExpression2 = (ILogicalExpression) unnest2.getExpressionRef().getValue(); - if (logicalExpression2.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) { - return false; - } - AbstractFunctionCallExpression functionCall2 = (AbstractFunctionCallExpression) logicalExpression2; - Function functionInfo2 = (Function) functionCall2.getFunctionInfo(); - if (!functionInfo2.hasScalarEvaluatorFactory()) { - return false; - } - // Exception for specific path expressions. - if (functionCall2.getFunctionIdentifier().equals(BuiltinOperators.DESCENDANT.getFunctionIdentifier()) - || functionCall2.getFunctionIdentifier().equals( - BuiltinOperators.DESCENDANT_OR_SELF.getFunctionIdentifier())) { - return false; - } - - // Find unnest2 variable in unnest1 - Mutable<ILogicalExpression> unnest1Arg = ExpressionToolbox.findVariableExpression( - unnest1.getExpressionRef(), unnest2.getVariable()); - if (unnest1Arg == null) { - return false; - } + if (usedVariables.contains(unnest2.getVariable())) { + return false; + } - // Replace unnest2 expression in unnest1 - ScalarFunctionCallExpression child = new ScalarFunctionCallExpression(functionInfo2, - functionCall2.getArguments()); - unnest1Arg.setValue(child); + // Check to see if the unnest2 expression has a scalar implementation. + ILogicalExpression logicalExpression2 = (ILogicalExpression) unnest2.getExpressionRef().getValue(); + if (logicalExpression2.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) { + return false; + } + AbstractFunctionCallExpression functionCall2 = (AbstractFunctionCallExpression) logicalExpression2; + Function functionInfo2 = (Function) functionCall2.getFunctionInfo(); + if (!functionInfo2.hasScalarEvaluatorFactory()) { + return false; + } + // Exception for specific path expressions. + if (functionCall2.getFunctionIdentifier().equals(BuiltinOperators.DESCENDANT.getFunctionIdentifier()) + || functionCall2.getFunctionIdentifier().equals( + BuiltinOperators.DESCENDANT_OR_SELF.getFunctionIdentifier())) { + return false; + } - // Move input for unnest2 into unnest1 - unnest1.getInputs().clear(); - unnest1.getInputs().addAll(unnest2.getInputs()); - return true; + // Find unnest2 variable in unnest1 + Mutable<ILogicalExpression> unnest1Arg = ExpressionToolbox.findVariableExpression(unnest1.getExpressionRef(), + unnest2.getVariable()); + if (unnest1Arg == null) { + return false; } - return false; + + // Replace unnest2 expression in unnest1 + ScalarFunctionCallExpression child = new ScalarFunctionCallExpression(functionInfo2, + functionCall2.getArguments()); + unnest1Arg.setValue(child); + + // Move input for unnest2 into unnest1 + unnest1.getInputs().clear(); + unnest1.getInputs().addAll(unnest2.getInputs()); + return true; } } http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertAssignToUnnestRule.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertAssignToUnnestRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertAssignToUnnestRule.java index 72f6d03..28e54e4 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertAssignToUnnestRule.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertAssignToUnnestRule.java @@ -31,12 +31,11 @@ import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.UnnestingFunction import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator; -import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule; /** * The rule searches for unnest(iterate) operator followed by an assign(child) * operator and merges the assign into the unnest operator. - * + * * <pre> * Before * @@ -44,22 +43,23 @@ import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule; * UNNEST( $v2 : iterate( $v1 ) ) * ASSIGN( $v1 : sf1( $v0 ) ) * plan__child - * + * * where plan__parent does not use $v1 and $v0 is defined in plan__child. * sf1 is a scalar function that has a unnesting implementation. - * + * * After * * plan__parent * UNNEST( $v2 : uf1( $v0 ) ) * plan__child * </pre> - * + * * @author prestonc */ -public class ConvertAssignToUnnestRule implements IAlgebraicRewriteRule { +public class ConvertAssignToUnnestRule extends AbstractUsedVariablesProcessingRule { @Override - public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException { + protected boolean processOperator(Mutable<ILogicalOperator> opRef, IOptimizationContext context) + throws AlgebricksException { AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue(); if (op.getOperatorTag() != LogicalOperatorTag.UNNEST) { return false; @@ -82,6 +82,10 @@ public class ConvertAssignToUnnestRule implements IAlgebraicRewriteRule { } AssignOperator assign = (AssignOperator) op2; + if (usedVariables.contains(assign.getVariables())) { + return false; + } + // Check to see if the expression has an unnesting implementation. ILogicalExpression logicalExpression2 = (ILogicalExpression) assign.getExpressions().get(0).getValue(); if (logicalExpression2.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) { @@ -92,21 +96,16 @@ public class ConvertAssignToUnnestRule implements IAlgebraicRewriteRule { if (!functionInfo2.hasUnnestingEvaluatorFactory()) { return false; } - - // TODO add checks for variables used that have now been removed. // Update the unnest parameters. unnest.getInputs().clear(); unnest.getInputs().addAll(assign.getInputs()); - - UnnestingFunctionCallExpression child = new UnnestingFunctionCallExpression(functionInfo2, functionCall2.getArguments()); + + UnnestingFunctionCallExpression child = new UnnestingFunctionCallExpression(functionInfo2, + functionCall2.getArguments()); unnest.getExpressionRef().setValue(child); - + return true; } - @Override - public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) { - return false; - } } http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java index f77b93b..b363c85 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java @@ -45,26 +45,26 @@ import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule; * The rule searches for where the Algebricks builtin function are temporarly in the plan in place of XQuery function. * The combination the Algebricks builtin function are replace with boolean XQuery function and the XQuery equivalent * function. - * + * * <pre> * Before * * plan__parent * %OPERATOR( $v1 : algebricks_function( \@input_expression ) ) * plan__child - * + * * where the function annotation contains a hint on which xquery expression is represented by the algebricks function. - * - * After + * + * After * * plan__parent * %OPERATOR( $v1 :xquery_expression( \@input_expression ) ) ) * plan__child - * - * note the xquery_expression may include the boolean function to ensure only a true or false result. * + * note the xquery_expression may include the boolean function to ensure only a true or false result. + * * </pre> - * + * * @author prestonc, shivanim */ public class ConvertFromAlgebricksExpressionsRule implements IAlgebraicRewriteRule { @@ -77,20 +77,14 @@ public class ConvertFromAlgebricksExpressionsRule implements IAlgebraicRewriteRu @SuppressWarnings({ "unchecked", "rawtypes" }) public ConvertFromAlgebricksExpressionsRule() { ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.AND, new Pair(BuiltinOperators.AND, null)); - ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.EQ, new Pair(BuiltinOperators.VALUE_EQ, - BuiltinOperators.GENERAL_EQ)); - ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.GE, new Pair(BuiltinOperators.VALUE_GE, - BuiltinOperators.GENERAL_GE)); - ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.GT, new Pair(BuiltinOperators.VALUE_GT, - BuiltinOperators.GENERAL_GT)); + ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.EQ, new Pair(BuiltinOperators.VALUE_EQ, null)); + ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.GE, new Pair(BuiltinOperators.VALUE_GE, null)); + ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.GT, new Pair(BuiltinOperators.VALUE_GT, null)); ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.IS_NULL, new Pair(null, BuiltinFunctions.FN_EMPTY_1)); - ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.LE, new Pair(BuiltinOperators.VALUE_LE, - BuiltinOperators.GENERAL_LE)); - ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.LT, new Pair(BuiltinOperators.VALUE_LT, - BuiltinOperators.GENERAL_LT)); + ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.LE, new Pair(BuiltinOperators.VALUE_LE, null)); + ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.LT, new Pair(BuiltinOperators.VALUE_LT, null)); ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.NOT, new Pair(null, BuiltinFunctions.FN_NOT_1)); - ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.NEQ, new Pair(BuiltinOperators.VALUE_NE, - BuiltinOperators.GENERAL_NE)); + ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.NEQ, new Pair(BuiltinOperators.VALUE_NE, null)); ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.OR, new Pair(BuiltinOperators.OR, null)); } @@ -109,6 +103,7 @@ public class ConvertFromAlgebricksExpressionsRule implements IAlgebraicRewriteRu modified = true; } } + context.computeAndSetTypeEnvironmentForOperator(opRef.getValue()); return modified; } http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java index f1747fc..394c622 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java @@ -42,7 +42,7 @@ import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule; * The rule searches for where the XQuery function are used in place of Algebricks builtin function. * The combination of the boolean XQuery function and the XQuery equivalent function are replaced with * the Algebricks builtin function . - * + * * <pre> * Before * @@ -50,18 +50,18 @@ import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule; * %OPERATOR( $v1 : xquery_expression( \@input_expression ) ) * plan__child * - * where xquery_expression has a known equivalent in Algebricks, + * where xquery_expression has a known equivalent in Algebricks, * such as conditional expressions and a check for null. * The expression may include the boolean function to ensure only * a true or false result. - * - * After + * + * After * * plan__parent * %OPERATOR( $v1 : algebricks_function( \@input_expression ) ) * plan__child * </pre> - * + * * @author prestonc, shivanim */ public class ConvertToAlgebricksExpressionsRule implements IAlgebraicRewriteRule { @@ -81,12 +81,6 @@ public class ConvertToAlgebricksExpressionsRule implements IAlgebraicRewriteRule ALGEBRICKS_MAP.put(BuiltinFunctions.FN_EMPTY_1.getFunctionIdentifier(), AlgebricksBuiltinFunctions.IS_NULL); ALGEBRICKS_MAP.put(BuiltinFunctions.FN_NOT_1.getFunctionIdentifier(), AlgebricksBuiltinFunctions.NOT); - ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_EQ.getFunctionIdentifier(), AlgebricksBuiltinFunctions.EQ); - ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_GE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.GE); - ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_GT.getFunctionIdentifier(), AlgebricksBuiltinFunctions.GT); - ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_LE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.LE); - ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_LT.getFunctionIdentifier(), AlgebricksBuiltinFunctions.LT); - ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_NE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.NEQ); } @Override http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/InlineNestedVariablesRule.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/InlineNestedVariablesRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/InlineNestedVariablesRule.java deleted file mode 100644 index c0c082f..0000000 --- a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/InlineNestedVariablesRule.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.vxquery.compiler.rewriter.rules; - -import java.util.List; - -import org.apache.commons.lang3.mutable.Mutable; - -import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException; -import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression; -import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator; -import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalPlan; -import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext; -import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag; -import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag; -import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable; -import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression; -import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator; -import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans; -import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator; -import edu.uci.ics.hyracks.algebricks.rewriter.rules.InlineVariablesRule; - -/** - * Modifies the InlineVariablesRule to also process nested plans. - */ -public class InlineNestedVariablesRule extends InlineVariablesRule { - - protected boolean inlineVariables(Mutable<ILogicalOperator> opRef, IOptimizationContext context) - throws AlgebricksException { - AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue(); - - // Update mapping from variables to expressions during top-down traversal. - if (op.getOperatorTag() == LogicalOperatorTag.ASSIGN) { - AssignOperator assignOp = (AssignOperator) op; - List<LogicalVariable> vars = assignOp.getVariables(); - List<Mutable<ILogicalExpression>> exprs = assignOp.getExpressions(); - for (int i = 0; i < vars.size(); i++) { - ILogicalExpression expr = exprs.get(i).getValue(); - // Ignore functions that are either in the doNotInline set or are non-functional - if (expr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) { - AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr; - if (doNotInlineFuncs.contains(funcExpr.getFunctionIdentifier()) || !funcExpr.isFunctional()) { - continue; - } - } - varAssignRhs.put(vars.get(i), exprs.get(i).getValue()); - } - } - - boolean modified = false; - // Descend into nested plans inlining along the way. - if (op.hasNestedPlans()) { - AbstractOperatorWithNestedPlans nestedOp = (AbstractOperatorWithNestedPlans) op; - for (ILogicalPlan nestedPlan : nestedOp.getNestedPlans()) { - for (Mutable<ILogicalOperator> nestedOpRef : nestedPlan.getRoots()) { - if (inlineVariables(nestedOpRef, context)) { - modified = true; - } - } - } - } - - // Descend into children inlining along on the way. - for (Mutable<ILogicalOperator> inputOpRef : op.getInputs()) { - if (inlineVariables(inputOpRef, context)) { - modified = true; - } - } - - if (performBottomUpAction(op)) { - modified = true; - } - - if (modified) { - context.computeAndSetTypeEnvironmentForOperator(op); - context.addToDontApplySet(this, op); - // Re-enable rules that we may have already tried. They could be applicable now after inlining. - context.removeFromAlreadyCompared(opRef.getValue()); - } - - return modified; - } -} http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/ExtractFunctionsFromJoinConditionRule.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/ExtractFunctionsFromJoinConditionRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/ExtractFunctionsFromJoinConditionRule.java new file mode 100644 index 0000000..9847c7f --- /dev/null +++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/ExtractFunctionsFromJoinConditionRule.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.vxquery.compiler.rewriter.rules.algebricksalternatives; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.mutable.Mutable; +import org.apache.commons.lang3.mutable.MutableObject; + +import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable; +import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression; +import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression; +import edu.uci.ics.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions; +import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities; +import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule; + +/** + * Factors out function expressions from each comparison function or similarity function in join condition by assigning them to a variables, and replacing the function expressions with references to those variables. + * Examples: + * Plan with function expressions in comparison or similarity condition of join expression. Generates one assign operator per extracted function expression. + * Example + * Before plan: + * join ( eq( funcX($$1), funcX($$2) ) ) + * After plan: + * join (eq($$3,$$4)) + * assign [$$4] <- [funcY($$2)] + * assign [$$3] <- [funcX($$1)] + */ +public class ExtractFunctionsFromJoinConditionRule implements IAlgebraicRewriteRule { + + @Override + public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException { + return false; + } + + @Override + public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) + throws AlgebricksException { + AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue(); + + if (op.getOperatorTag() != LogicalOperatorTag.INNERJOIN + && op.getOperatorTag() != LogicalOperatorTag.LEFTOUTERJOIN) { + return false; + } + AbstractBinaryJoinOperator joinOp = (AbstractBinaryJoinOperator) op; + ILogicalExpression expr = joinOp.getCondition().getValue(); + + return assignFunctionExpressions(joinOp, expr, context); + + } + + private boolean assignFunctionExpressions(AbstractLogicalOperator joinOp, ILogicalExpression expr, + IOptimizationContext context) throws AlgebricksException { + if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) { + return false; + } + AbstractFunctionCallExpression fexp = (AbstractFunctionCallExpression) expr; + FunctionIdentifier fi = fexp.getFunctionIdentifier(); + + boolean modified = false; + if (fi.equals(AlgebricksBuiltinFunctions.AND) || fi.equals(AlgebricksBuiltinFunctions.OR)) { + for (Mutable<ILogicalExpression> a : fexp.getArguments()) { + if (assignFunctionExpressions(joinOp, a.getValue(), context)) { + modified = true; + } + } + return modified; + } else if (AlgebricksBuiltinFunctions.isComparisonFunction(fi)) { + for (Mutable<ILogicalExpression> exprRef : fexp.getArguments()) { + if (exprRef.getValue().getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) { + LogicalVariable newVar = context.newVar(); + AssignOperator newAssign = new AssignOperator(newVar, new MutableObject<ILogicalExpression>(exprRef + .getValue().cloneExpression())); + newAssign.setExecutionMode(joinOp.getExecutionMode()); + + // Place assign below joinOp. + List<LogicalVariable> used = new ArrayList<LogicalVariable>(); + VariableUtilities.getUsedVariables(newAssign, used); + + Mutable<ILogicalOperator> leftBranchRef = joinOp.getInputs().get(0); + ILogicalOperator leftBranch = leftBranchRef.getValue(); + List<LogicalVariable> leftBranchVariables = new ArrayList<LogicalVariable>(); + VariableUtilities.getLiveVariables(leftBranch, leftBranchVariables); + if (leftBranchVariables.containsAll(used)) { + // place assign on left branch + newAssign.getInputs().add(new MutableObject<ILogicalOperator>(leftBranch)); + leftBranchRef.setValue(newAssign); + modified = true; + } else { + Mutable<ILogicalOperator> rightBranchRef = joinOp.getInputs().get(1); + ILogicalOperator rightBranch = rightBranchRef.getValue(); + List<LogicalVariable> rightBranchVariables = new ArrayList<LogicalVariable>(); + VariableUtilities.getLiveVariables(rightBranch, rightBranchVariables); + if (rightBranchVariables.containsAll(used)) { + // place assign on right branch + newAssign.getInputs().add(new MutableObject<ILogicalOperator>(rightBranch)); + rightBranchRef.setValue(newAssign); + modified = true; + } + } + + if (modified) { + // Replace original expr with variable reference. + exprRef.setValue(new VariableReferenceExpression(newVar)); + context.computeAndSetTypeEnvironmentForOperator(newAssign); + context.computeAndSetTypeEnvironmentForOperator(joinOp); + } + } + } + return modified; + } else { + return false; + } + } + +} http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/InlineNestedVariablesRule.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/InlineNestedVariablesRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/InlineNestedVariablesRule.java new file mode 100644 index 0000000..ca0bc1c --- /dev/null +++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/InlineNestedVariablesRule.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.vxquery.compiler.rewriter.rules.algebricksalternatives; + +import java.util.List; + +import org.apache.commons.lang3.mutable.Mutable; + +import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalPlan; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable; +import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.InlineVariablesRule; + +/** + * Modifies the InlineVariablesRule to also process nested plans. + */ +public class InlineNestedVariablesRule extends InlineVariablesRule { + + protected boolean inlineVariables(Mutable<ILogicalOperator> opRef, IOptimizationContext context) + throws AlgebricksException { + AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue(); + + // Update mapping from variables to expressions during top-down traversal. + if (op.getOperatorTag() == LogicalOperatorTag.ASSIGN) { + AssignOperator assignOp = (AssignOperator) op; + List<LogicalVariable> vars = assignOp.getVariables(); + List<Mutable<ILogicalExpression>> exprs = assignOp.getExpressions(); + for (int i = 0; i < vars.size(); i++) { + ILogicalExpression expr = exprs.get(i).getValue(); + // Ignore functions that are either in the doNotInline set or are non-functional + if (expr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) { + AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr; + if (doNotInlineFuncs.contains(funcExpr.getFunctionIdentifier()) || !funcExpr.isFunctional()) { + continue; + } + } + varAssignRhs.put(vars.get(i), exprs.get(i).getValue()); + } + } + + boolean modified = false; + // Descend into nested plans inlining along the way. + if (op.hasNestedPlans()) { + AbstractOperatorWithNestedPlans nestedOp = (AbstractOperatorWithNestedPlans) op; + for (ILogicalPlan nestedPlan : nestedOp.getNestedPlans()) { + for (Mutable<ILogicalOperator> nestedOpRef : nestedPlan.getRoots()) { + if (inlineVariables(nestedOpRef, context)) { + modified = true; + } + } + } + } + + // Descend into children inlining along on the way. + for (Mutable<ILogicalOperator> inputOpRef : op.getInputs()) { + if (inlineVariables(inputOpRef, context)) { + modified = true; + } + } + + if (performBottomUpAction(op)) { + modified = true; + } + + if (modified) { + context.computeAndSetTypeEnvironmentForOperator(op); + context.addToDontApplySet(this, op); + // Re-enable rules that we may have already tried. They could be applicable now after inlining. + context.removeFromAlreadyCompared(opRef.getValue()); + } + + return modified; + } +} http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/MoveFreeVariableOperatorOutOfSubplanRule.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/MoveFreeVariableOperatorOutOfSubplanRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/MoveFreeVariableOperatorOutOfSubplanRule.java new file mode 100644 index 0000000..94b809d --- /dev/null +++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/algebricksalternatives/MoveFreeVariableOperatorOutOfSubplanRule.java @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.vxquery.compiler.rewriter.rules.algebricksalternatives; + +import java.util.HashSet; +import java.util.ListIterator; +import java.util.Set; + +import org.apache.commons.lang3.mutable.Mutable; + +import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalPlan; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator; +import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities; +import edu.uci.ics.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil; +import edu.uci.ics.hyracks.algebricks.rewriter.rules.AbstractDecorrelationRule; + +/** + * The rule searches for operators that can be moved outside the subplan. + * + * <pre> + * Before + * + * %PARENT_PLAN + * SUBPLAN{ + * %NESTED_OPERATORS_B+ + * ASSIGN || %SUBPLAN + * %NESTED_OPERATORS_A* + * NESTEDTUPLESOURCE + * } + * %CHILD_PLAN + * + * where + * %SUBPLAN has one nested plan with a root AGGREGATE operator. + * + * After + * + * %PARENT_PLAN + * SUBPLAN{ + * %NESTED_OPERATORS_B+ + * %NESTED_OPERATORS_A* + * NESTEDTUPLESOURCE + * } + * ASSIGN || %SUBPLAN + * %CHILD_PLAN + * </pre> + */ +public class MoveFreeVariableOperatorOutOfSubplanRule extends AbstractDecorrelationRule { + + @Override + public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) + throws AlgebricksException { + AbstractLogicalOperator op0 = (AbstractLogicalOperator) opRef.getValue(); + if (op0.getOperatorTag() != LogicalOperatorTag.SUBPLAN) { + return false; + } + SubplanOperator subplan = (SubplanOperator) op0; + + Mutable<ILogicalOperator> leftRef = subplan.getInputs().get(0); + if (((AbstractLogicalOperator) leftRef.getValue()).getOperatorTag() == LogicalOperatorTag.EMPTYTUPLESOURCE) { + return false; + } + + ListIterator<ILogicalPlan> plansIter = subplan.getNestedPlans().listIterator(); + ILogicalPlan p = null; + while (plansIter.hasNext()) { + p = plansIter.next(); + } + if (p == null) { + return false; + } + if (p.getRoots().size() != 1) { + return false; + } + Mutable<ILogicalOperator> opRef1 = p.getRoots().get(0); + + //The root operator will not be movable. Start with the second op + AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef1.getValue(); + if (op1.getInputs().size() != 1) { + return false; + } + Mutable<ILogicalOperator> op2Ref = op1.getInputs().get(0); + + //Get all variables that come from outside of the loop + Set<LogicalVariable> free = new HashSet<LogicalVariable>(); + OperatorPropertiesUtil.getFreeVariablesInSelfOrDesc(op1, free); + + while (op2Ref != null) { + //Get the operator that we want to look at + AbstractLogicalOperator op2 = (AbstractLogicalOperator) op2Ref.getValue(); + + //Make sure we are looking at subplan with a scan/join + if (op2.getInputs().size() != 1 || !descOrSelfIsScanOrJoin(op2)) { + return false; + } + boolean notApplicable = false; + + //Get its used variables + Set<LogicalVariable> used = new HashSet<LogicalVariable>(); + + //not movable if the operator is not an assign or subplan + //Might be helpful in the future for other operations in the future + if (op2.getOperatorTag() == LogicalOperatorTag.ASSIGN) { + VariableUtilities.getUsedVariables(op2, used); + } else if (op2.getOperatorTag() == LogicalOperatorTag.SUBPLAN) { + // Nested plan must have an aggregate root. + ListIterator<ILogicalPlan> subplansIter = ((SubplanOperator) op2).getNestedPlans().listIterator(); + ILogicalPlan plan = null; + while (subplansIter.hasNext()) { + plan = subplansIter.next(); + } + if (plan == null) { + return false; + } + if (plan.getRoots().size() != 1) { + return false; + } + ILogicalOperator op3 = plan.getRoots().get(0).getValue(); + if (op3.getOperatorTag() != LogicalOperatorTag.AGGREGATE) { + return false; + } + // Used variables do not include ones created in the subplan. + VariableUtilities.getUsedVariables(op2, used); + Set<LogicalVariable> subplanProducedAndDown = new HashSet<LogicalVariable>(); + VariableUtilities.getProducedVariablesInDescendantsAndSelf(op3, subplanProducedAndDown); + used.removeAll(subplanProducedAndDown); + } else { + notApplicable = true; + } + + //Make sure that all of its used variables come from outside + for (LogicalVariable var : used) { + if (!free.contains(var)) { + notApplicable = true; + } + } + + if (notApplicable) { + op2Ref = op2.getInputs().get(0); + } else { + //Make the input of op2 be the input of op1 + op2Ref.setValue(op2.getInputs().get(0).getValue()); + + //Make the outside of the subplan the input of op2 + Mutable<ILogicalOperator> outsideRef = op2.getInputs().get(0); + outsideRef.setValue(op0.getInputs().get(0).getValue()); + + //Make op2 the input of the subplan + Mutable<ILogicalOperator> op2OutsideRef = op0.getInputs().get(0); + op2OutsideRef.setValue(op2); + + return true; + } + + } + return false; + } + +} http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/comparison/general/AbstractGeneralComparisonScalarEvaluatorFactory.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/comparison/general/AbstractGeneralComparisonScalarEvaluatorFactory.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/comparison/general/AbstractGeneralComparisonScalarEvaluatorFactory.java index 446b445..99c4faa 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/comparison/general/AbstractGeneralComparisonScalarEvaluatorFactory.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/comparison/general/AbstractGeneralComparisonScalarEvaluatorFactory.java @@ -146,7 +146,7 @@ public abstract class AbstractGeneralComparisonScalarEvaluatorFactory extends /** * Check the second argument for a sequence and loop if required. - * + * * @param aOp * @param tvpArg1 * @param tvpArg2 @@ -181,7 +181,7 @@ public abstract class AbstractGeneralComparisonScalarEvaluatorFactory extends /** * Transform the values into values supported for general comparison. - * + * * @param aOp * @param tvpArg1 * @param tvpArg2 @@ -219,8 +219,16 @@ public abstract class AbstractGeneralComparisonScalarEvaluatorFactory extends // Set up value comparison tagged value pointables. if (tid1 == ValueTag.XS_UNTYPED_ATOMIC_TAG && tid2 == ValueTag.XS_UNTYPED_ATOMIC_TAG) { // Only need to change tag since the storage is the same for untyped atomic and string. + dOutInner1.write(tvpTransform1.getByteArray(), tvpTransform1.getStartOffset(), + tvpTransform1.getLength()); + tvpCompare1.set(abvsInner1.getByteArray(), abvsInner1.getStartOffset(), abvsInner1.getLength()); tvpCompare1.getByteArray()[0] = ValueTag.XS_STRING_TAG; + tagTransformed1 = true; + dOutInner2.write(tvpTransform2.getByteArray(), tvpTransform2.getStartOffset(), + tvpTransform2.getLength()); + tvpCompare2.set(abvsInner2.getByteArray(), abvsInner2.getStartOffset(), abvsInner2.getLength()); tvpCompare2.getByteArray()[0] = ValueTag.XS_STRING_TAG; + tagTransformed2 = true; } else if (tid1 == ValueTag.XS_UNTYPED_ATOMIC_TAG) { tid1 = tid2; getCastToOperator(tid2); http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/conditional/IfThenElseScalarEvaluatorFactory.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/conditional/IfThenElseScalarEvaluatorFactory.java b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/conditional/IfThenElseScalarEvaluatorFactory.java index b0584f8..7cd97e3 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/conditional/IfThenElseScalarEvaluatorFactory.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/conditional/IfThenElseScalarEvaluatorFactory.java @@ -20,7 +20,6 @@ import org.apache.vxquery.datamodel.accessors.TaggedValuePointable; import org.apache.vxquery.datamodel.values.ValueTag; import org.apache.vxquery.exceptions.ErrorCode; import org.apache.vxquery.exceptions.SystemException; -import org.apache.vxquery.runtime.functions.base.AbstractTaggedValueArgumentScalarEvaluator; import org.apache.vxquery.runtime.functions.base.AbstractTaggedValueArgumentScalarEvaluatorFactory; import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException; @@ -29,32 +28,42 @@ import edu.uci.ics.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory; import edu.uci.ics.hyracks.api.context.IHyracksTaskContext; import edu.uci.ics.hyracks.data.std.api.IPointable; import edu.uci.ics.hyracks.data.std.primitive.BooleanPointable; +import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference; public class IfThenElseScalarEvaluatorFactory extends AbstractTaggedValueArgumentScalarEvaluatorFactory { private static final long serialVersionUID = 1L; + private static final int CONDITION = 0; + private static final int TRUE_CONDITION = 1; + private static final int FALSE_CONDITION = 2; public IfThenElseScalarEvaluatorFactory(IScalarEvaluatorFactory[] args) { super(args); } @Override - protected IScalarEvaluator createEvaluator(IHyracksTaskContext ctx, IScalarEvaluator[] args) + protected IScalarEvaluator createEvaluator(IHyracksTaskContext ctx, final IScalarEvaluator[] args) throws AlgebricksException { - return new AbstractTaggedValueArgumentScalarEvaluator(args) { - private final BooleanPointable bp = (BooleanPointable) BooleanPointable.FACTORY.createPointable(); + final TaggedValuePointable conditionTvp = (TaggedValuePointable) TaggedValuePointable.FACTORY.createPointable(); + final BooleanPointable bp = (BooleanPointable) BooleanPointable.FACTORY.createPointable(); + return new IScalarEvaluator() { @Override - protected void evaluate(TaggedValuePointable[] args, IPointable result) throws SystemException { - TaggedValuePointable tvp1 = args[0]; - if (tvp1.getTag() != ValueTag.XS_BOOLEAN_TAG) { - throw new SystemException(ErrorCode.FORG0006); - } - tvp1.getValue(bp); + public void evaluate(IFrameTupleReference tuple, IPointable result) throws AlgebricksException { + args[CONDITION].evaluate(tuple, conditionTvp); + + try { + if (conditionTvp.getTag() != ValueTag.XS_BOOLEAN_TAG) { + throw new SystemException(ErrorCode.FORG0006); + } + conditionTvp.getValue(bp); - if (bp.getBoolean()) { - result.set(args[1]); - } else { - result.set(args[2]); + if (bp.getBoolean()) { + args[TRUE_CONDITION].evaluate(tuple, result); + } else { + args[FALSE_CONDITION].evaluate(tuple, result); + } + } catch (SystemException e) { + throw new AlgebricksException(e); } } }; http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/serializer/XMLSerializer.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/serializer/XMLSerializer.java b/vxquery-core/src/main/java/org/apache/vxquery/serializer/XMLSerializer.java index 189ae24..8a5845d 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/serializer/XMLSerializer.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/serializer/XMLSerializer.java @@ -366,7 +366,7 @@ public class XMLSerializer implements IPrinter { enp.getAttributeSequence(ntp, seqp); if (seqp.getByteArray() != null && seqp.getEntryCount() > 0) { ps.append(' '); - printSequence(ps, seqp); + printSequence(ps, seqp, " "); } enp.getChildrenSequence(ntp, seqp); @@ -422,12 +422,19 @@ public class XMLSerializer implements IPrinter { } private void printSequence(PrintStream ps, SequencePointable seqp) { + printSequence(ps, seqp, null); + } + + private void printSequence(PrintStream ps, SequencePointable seqp, String between) { VoidPointable vp = pp.takeOne(VoidPointable.class); try { int len = seqp.getEntryCount(); for (int i = 0; i < len; ++i) { seqp.getEntry(i, vp); print(vp.getByteArray(), vp.getStartOffset(), vp.getLength(), ps); + if (i < len - 1 && between != null) { + ps.append(between); + } } } finally { pp.giveBack(vp); http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/query/XMLQueryCompiler.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/query/XMLQueryCompiler.java b/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/query/XMLQueryCompiler.java index 38272dd..d9c5d01 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/query/XMLQueryCompiler.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/query/XMLQueryCompiler.java @@ -164,7 +164,13 @@ public class XMLQueryCompiler { builder.setNullableTypeComputer(new INullableTypeComputer() { @Override public Object makeNullableType(Object type) throws AlgebricksException { - throw new NotImplementedException("NullableTypeComputer is not implented (makeNullableType)"); + SequenceType st = (SequenceType) type; + if (st.getQuantifier().allowsEmptySequence()) { + return type; + } else if (st.getQuantifier() == Quantifier.QUANT_ONE) { + return SequenceType.create(st.getItemType(), Quantifier.QUANT_QUESTION); + } + return type; } @Override @@ -239,6 +245,8 @@ public class XMLQueryCompiler { RewriteRuleset.buildNestedDataSourceRuleCollection())); defaultLogicalRewrites.add(new Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>(seqOnceCtrl, RewriteRuleset.buildTypeInferenceRuleCollection())); + defaultLogicalRewrites.add(new Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>(seqCtrlNoDfs, + RewriteRuleset.buildUnnestingRuleCollection())); defaultLogicalRewrites.add(new Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>(seqCtrlFullDfs, RewriteRuleset.buildNormalizationRuleCollection())); defaultLogicalRewrites.add(new Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>(seqCtrlNoDfs, http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/translator/XMLQueryTranslator.java ---------------------------------------------------------------------- diff --git a/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/translator/XMLQueryTranslator.java b/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/translator/XMLQueryTranslator.java index 2507d6c..9faefda 100644 --- a/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/translator/XMLQueryTranslator.java +++ b/vxquery-core/src/main/java/org/apache/vxquery/xmlquery/translator/XMLQueryTranslator.java @@ -160,7 +160,9 @@ import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator; import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalPlan; import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag; +import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag; import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable; +import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ConstantExpression; import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression; @@ -1501,26 +1503,40 @@ public class XMLQueryTranslator { ctxExpr = vre(createAssignment(ctxExpr, tCtx)); ctxExpr = sfce(asc ? BuiltinOperators.SORT_DISTINCT_NODES_ASC_OR_ATOMICS : BuiltinOperators.SORT_DISTINCT_NODES_DESC_OR_ATOMICS, ctxExpr); + iterateOver(ctxExpr, tCtx); + int i = 0; + ILogicalExpression selectCondition = null; for (ASTNode pn : predicates) { - tCtx = tCtx.pushContext(); - tCtx.pushVariableScope(); - iterateOver(ctxExpr, tCtx); + // Handles integer, boolean expression, path expression exists + // TODO Support inner focus between predicates. LogicalVariable pLVar = translateExpression(pn, tCtx); ILogicalExpression tTest = instanceOf(vre(pLVar), SequenceType.create(BuiltinTypeRegistry.XSEXT_NUMERIC, Quantifier.QUANT_ONE)); ILogicalExpression posTest = sfce(BuiltinOperators.VALUE_EQ, vre(pLVar), vre(tCtx.varScope .lookupVariable(XMLQueryCompilerConstants.POS_VAR_NAME).getLogicalVariable())); - ILogicalExpression boolTest = sfce(BuiltinFunctions.FN_BOOLEAN_1, vre(pLVar)); - - SelectOperator select = new SelectOperator(mutable(sfce(BuiltinOperators.IF_THEN_ELSE, tTest, - posTest, boolTest)), false, null); - select.getInputs().add(mutable(tCtx.op)); - tCtx.op = select; - ctxExpr = vre(tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.DOT_VAR_NAME) - .getLogicalVariable()); - tCtx.popVariableScope(); - tCtx = tCtx.popContext(); + ILogicalExpression boolTestTmp = vre(pLVar); + if (tCtx.op.getOperatorTag() == LogicalOperatorTag.ASSIGN) { + ILogicalExpression expression = ((AssignOperator) tCtx.op).getExpressions().get(0) + .getValue(); + if (expression.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL + && ((AbstractFunctionCallExpression) expression).getFunctionIdentifier().equals( + BuiltinOperators.CHILD.getFunctionIdentifier())) { + boolTestTmp = sfce(BuiltinFunctions.FN_COUNT_1, boolTestTmp); + } + } + ILogicalExpression boolTest = sfce(BuiltinFunctions.FN_BOOLEAN_1, boolTestTmp); + ILogicalExpression condition = sfce(BuiltinOperators.IF_THEN_ELSE, tTest, posTest, boolTest); + if (i++ == 0) { + selectCondition = condition; + } else { + selectCondition = sfce(BuiltinOperators.AND, selectCondition, condition); + } } + SelectOperator select = new SelectOperator(mutable(selectCondition), false, null); + select.getInputs().add(mutable(tCtx.op)); + tCtx.op = select; + ctxExpr = vre(tCtx.varScope.lookupVariable(XMLQueryCompilerConstants.DOT_VAR_NAME) + .getLogicalVariable()); } if (popScope) { tCtx.popVariableScope(); http://git-wip-us.apache.org/repos/asf/vxquery/blob/7fc0d93b/vxquery-xtest/pom.xml ---------------------------------------------------------------------- diff --git a/vxquery-xtest/pom.xml b/vxquery-xtest/pom.xml index 6fb2798..9e83fd7 100644 --- a/vxquery-xtest/pom.xml +++ b/vxquery-xtest/pom.xml @@ -119,6 +119,7 @@ <!-- <argLine>-agentpath:"${yourkit.home}/bin/mac/libyjpagent.jnilib=sampling"</argLine> --> <excludes> <exclude>**/AbstractXQueryTest.java</exclude> + <exclude>**/VXQueryXMarkTest.java</exclude> <exclude>**/XMarkTest.java</exclude> <exclude>**/XQTSTest.java</exclude> </excludes>
