ASTERIXDB-1608, ASTERIXDB-1617 Match user query for nonpure function calls This fix makes it so that nonpure functions are called in the same place and with the same number of executions as specified by the user in the query. This also means that indexes cannot be used for queries that compare with a nonpure call that is made on a per-record basis. Added optimizer tests Change-Id: I2dec322b30835625430c06acd7626d902bada137 Reviewed-on: https://asterix-gerrit.ics.uci.edu/1057 Tested-by: Jenkins <[email protected]> Reviewed-by: Till Westmann <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/6b8a42f3 Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/6b8a42f3 Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/6b8a42f3 Branch: refs/heads/master Commit: 6b8a42f3df9cebb9bd5d56e5986215bc0d98e45c Parents: 2da225b Author: Steven Glenn Jacobs <[email protected]> Authored: Mon Nov 28 15:40:31 2016 -0800 Committer: Till Westmann <[email protected]> Committed: Tue Nov 29 10:05:44 2016 -0800 ---------------------------------------------------------------------- .../operators/physical/CommitPOperator.java | 2 +- .../optimizer/rules/PushFieldAccessRule.java | 6 +- .../am/AbstractIntroduceAccessMethodRule.java | 10 +- .../optimizer/rules/am/AccessMethodUtils.java | 43 ++++-- .../optimizer/rules/am/BTreeAccessMethod.java | 47 ++++++- .../optimizer/rules/am/IAccessMethod.java | 21 ++- .../rules/am/IOptimizableFuncExpr.java | 8 +- .../am/IntroduceLSMComponentFilterRule.java | 2 +- .../am/IntroduceSelectAccessMethodRule.java | 130 +++++++++++++++---- .../rules/am/InvertedIndexAccessMethod.java | 44 ++++--- .../optimizer/rules/am/OptimizableFuncExpr.java | 33 +++-- .../rules/am/OptimizableOperatorSubTree.java | 45 ++++--- .../optimizer/rules/am/RTreeAccessMethod.java | 10 +- .../nonpure/global-datetime-no-index.aql | 41 ++++++ .../global-datetime-use-index-return-time.aql | 45 +++++++ .../nonpure/global-datetime-use-index.aql | 42 ++++++ .../queries/nonpure/keep-datetime-local.aql | 74 +++++++++++ .../nonpure/local-datetime-ignore-index.aql | 42 ++++++ .../queries/nonpure/local-datetime-no-index.aql | 42 ++++++ ...in-nonpure-location-in-join-cannot-index.aql | 48 +++++++ .../queries/nonpure/query-ASTERIXDB-1608.aql | 33 +++++ .../results/btree-index/btree-datetime-02.plan | 9 +- .../nonpure/global-datetime-no-index.plan | 10 ++ .../global-datetime-use-index-return-time.plan | 12 ++ .../nonpure/global-datetime-use-index.plan | 10 ++ .../results/nonpure/keep-datetime-local.plan | 36 +++++ .../nonpure/local-datetime-ignore-index.plan | 9 ++ .../nonpure/local-datetime-no-index.plan | 10 ++ ...n-nonpure-location-in-join-cannot-index.plan | 25 ++++ .../results/nonpure/query-ASTERIXDB-1608.plan | 13 ++ .../global-datetime-use-index.1.ddl.aql | 30 +++++ .../global-datetime-use-index.2.update.aql | 26 ++++ .../global-datetime-use-index.3.query.aql | 26 ++++ .../local-datetime-ignore-index.1.ddl.aql | 30 +++++ .../local-datetime-ignore-index.2.update.aql | 26 ++++ .../local-datetime-ignore-index.3.query.aql | 26 ++++ .../global-datetime-use-index.1.adm | 2 + .../local-datetime-ignore-index.1.adm | 2 + .../src/test/resources/runtimets/testsuite.xml | 16 ++- .../core/algebra/base/PhysicalOperatorTag.java | 2 +- .../algebra/util/OperatorPropertiesUtil.java | 27 +++- .../rewriter/rules/ConsolidateAssignsRule.java | 7 +- .../rules/EnforceStructuralPropertiesRule.java | 4 +- .../rules/ExtractCommonExpressionsRule.java | 29 +++-- .../rewriter/rules/InlineVariablesRule.java | 22 +--- .../PushMapOperatorDownThroughProductRule.java | 5 + .../rewriter/rules/SetExecutionModeRule.java | 6 +- 47 files changed, 1020 insertions(+), 168 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/CommitPOperator.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/CommitPOperator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/CommitPOperator.java index 28c883a..1c01c40 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/CommitPOperator.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/algebra/operators/physical/CommitPOperator.java @@ -62,7 +62,7 @@ public class CommitPOperator extends AbstractPhysicalOperator { @Override public PhysicalOperatorTag getOperatorTag() { - return PhysicalOperatorTag.EXTENSION_OPERATOR; + return PhysicalOperatorTag.DELEGATE_OPERATOR; } @Override http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushFieldAccessRule.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushFieldAccessRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushFieldAccessRule.java index e68ad02..3fe5e30 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushFieldAccessRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushFieldAccessRule.java @@ -62,11 +62,12 @@ import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceSc import org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities; -import org.apache.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil; import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule; public class PushFieldAccessRule implements IAlgebraicRewriteRule { + private static final String IS_MOVABLE = "isMovable"; + @Override public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) { return false; @@ -184,7 +185,8 @@ public class PushFieldAccessRule implements IAlgebraicRewriteRule { && !(op2.getOperatorTag() == LogicalOperatorTag.SELECT && isAccessToIndexedField(access, context))) { return false; } - if (!OperatorPropertiesUtil.isMovable(op2)) { + Object annotation = op2.getAnnotations().get(IS_MOVABLE); + if (annotation != null && !((Boolean) annotation)) { return false; } if (tryingToPushThroughSelectionWithSameDataSource(access, op2)) { http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java index 3c79009..c44cebc 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java @@ -243,11 +243,13 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew if (j != exprAndVarIdx.second) { matchedTypes.add(optFuncExpr.getFieldType(j)); } + } if (matchedTypes.size() < 2 && optFuncExpr.getNumLogicalVars() == 1) { - matchedTypes.add((IAType) ExpressionTypeComputer.INSTANCE.getType( - optFuncExpr.getConstantAtRuntimeExpr(0), context.getMetadataProvider(), + matchedTypes + .add((IAType) ExpressionTypeComputer.INSTANCE.getType(optFuncExpr.getConstantExpr(0), + context.getMetadataProvider(), typeEnvironment)); } @@ -583,9 +585,7 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew subTree.getRecordType(), optVarIndex, optFuncExpr.getFuncExpr().getArguments().get(optVarIndex).getValue(), datasetRecordVar, subTree.getMetaRecordType(), datasetMetaVar); - if (fieldName == null) { - continue; - } + IAType fieldType = (IAType) context.getOutputTypeEnvironment(assignOp).getVarType(var); // Set the fieldName in the corresponding matched // function expression. http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java index 2d46a0b..cee77ed 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java @@ -74,6 +74,7 @@ import org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperato import org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator.IOrder; import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestMapOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities; import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl; import org.apache.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil; @@ -308,11 +309,18 @@ public class AccessMethodUtils { // Type Checking and type promotion is done here IAType fieldType = optFuncExpr.getFieldType(0); + if (optFuncExpr.getNumConstantExpr() == 0) { + //We are looking at a selection case, but using two variables + //This means that the second variable comes from a nonPure function call + //TODO: Right now we miss on type promotion for nonpure functions + return new Pair<>(new VariableReferenceExpression(optFuncExpr.getLogicalVar(1)), false); + } + ILogicalExpression constantAtRuntimeExpression = null; AsterixConstantValue constantValue = null; ATypeTag constantValueTag = null; - constantAtRuntimeExpression = optFuncExpr.getConstantAtRuntimeExpr(0); + constantAtRuntimeExpression = optFuncExpr.getConstantExpr(0); if (constantAtRuntimeExpression.getExpressionTag() == LogicalExpressionTag.CONSTANT) { constantValue = (AsterixConstantValue) ((ConstantExpression) constantAtRuntimeExpression).getValue(); @@ -355,19 +363,16 @@ public class AccessMethodUtils { } if (typeCastingApplied) { - return new Pair<ILogicalExpression, Boolean>(new ConstantExpression(replacedConstantValue), - realTypeConvertedToIntegerType); + return new Pair<>(new ConstantExpression(replacedConstantValue), realTypeConvertedToIntegerType); } else { - return new Pair<ILogicalExpression, Boolean>(optFuncExpr.getConstantAtRuntimeExpr(0), false); + return new Pair<>(optFuncExpr.getConstantExpr(0), false); } } else { // We are optimizing a join query. Determine which variable feeds the secondary index. if (optFuncExpr.getOperatorSubTree(0) == null || optFuncExpr.getOperatorSubTree(0) == probeSubTree) { - return new Pair<ILogicalExpression, Boolean>( - new VariableReferenceExpression(optFuncExpr.getLogicalVar(0)), false); + return new Pair<>(new VariableReferenceExpression(optFuncExpr.getLogicalVar(0)), false); } else { - return new Pair<ILogicalExpression, Boolean>( - new VariableReferenceExpression(optFuncExpr.getLogicalVar(1)), false); + return new Pair<>(new VariableReferenceExpression(optFuncExpr.getLogicalVar(1)), false); } } } @@ -645,7 +650,7 @@ public class AccessMethodUtils { return unnestOp; } - //If the expression is constant at runtime, runturn the type + //If the expression is constant at runtime, return the type public static IAType constantRuntimeResultType(ILogicalExpression expr, IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException { Set<LogicalVariable> usedVariables = new HashSet<LogicalVariable>(); @@ -656,4 +661,24 @@ public class AccessMethodUtils { return (IAType) context.getExpressionTypeComputer().getType(expr, context.getMetadataProvider(), typeEnvironment); } + + //Get Variables used by afterSelectRefs that were created before the datasource + //If there are any, we should retain inputs + public static boolean retainInputs(List<LogicalVariable> dataSourceVariables, ILogicalOperator sourceOp, + List<Mutable<ILogicalOperator>> afterSelectRefs) throws AlgebricksException { + List<LogicalVariable> usedVars = new ArrayList<>(); + List<LogicalVariable> producedVars = new ArrayList<>(); + List<LogicalVariable> liveVars = new ArrayList<>(); + VariableUtilities.getLiveVariables(sourceOp, liveVars); + for (Mutable<ILogicalOperator> opMutable : afterSelectRefs) { + ILogicalOperator op = opMutable.getValue(); + VariableUtilities.getUsedVariables(op, usedVars); + VariableUtilities.getProducedVariables(op, producedVars); + } + usedVars.removeAll(producedVars); + usedVars.removeAll(dataSourceVariables); + usedVars.retainAll(liveVars); + return usedVars.isEmpty() ? false : true; + } + } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java index eb7d3a4..3035c76 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java @@ -120,13 +120,20 @@ public class BTreeAccessMethod implements IAccessMethod { } @Override - public boolean applySelectPlanTransformation(Mutable<ILogicalOperator> selectRef, - OptimizableOperatorSubTree subTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx, - IOptimizationContext context) throws AlgebricksException { + public boolean applySelectPlanTransformation(List<Mutable<ILogicalOperator>> afterSelectRefs, + Mutable<ILogicalOperator> selectRef, OptimizableOperatorSubTree subTree, Index chosenIndex, + AccessMethodAnalysisContext analysisCtx, IOptimizationContext context) throws AlgebricksException { SelectOperator select = (SelectOperator) selectRef.getValue(); Mutable<ILogicalExpression> conditionRef = select.getCondition(); + ILogicalOperator primaryIndexUnnestOp = createSecondaryToPrimaryPlan(conditionRef, subTree, null, chosenIndex, - analysisCtx, false, false, false, context); + analysisCtx, + AccessMethodUtils.retainInputs(subTree.getDataSourceVariables(), subTree.getDataSourceRef().getValue(), + afterSelectRefs), + false, subTree.getDataSourceRef().getValue().getInputs().get(0).getValue() + .getExecutionMode() == ExecutionMode.UNPARTITIONED, + context); + if (primaryIndexUnnestOp == null) { return false; } @@ -484,6 +491,18 @@ public class BTreeAccessMethod implements IAccessMethod { OperatorManipulationUtil.deepCopy(dataSourceOp.getInputs().get(0).getValue()))); assignConstantSearchKeys.setExecutionMode(dataSourceOp.getExecutionMode()); inputOp = assignConstantSearchKeys; + } else if (probeSubTree == null) { + //nonpure case + //Make sure that the nonpure function is unpartitioned + ILogicalOperator checkOp = dataSourceOp.getInputs().get(0).getValue(); + while (checkOp.getExecutionMode() != ExecutionMode.UNPARTITIONED) { + if (checkOp.getInputs().size() == 1) { + checkOp = checkOp.getInputs().get(0).getValue(); + } else { + return null; + } + } + inputOp = dataSourceOp.getInputs().get(0).getValue(); } else { // All index search keys are variables. inputOp = probeSubTree.getRoot(); @@ -694,8 +713,11 @@ public class BTreeAccessMethod implements IAccessMethod { private boolean probeIsOnLhs(IOptimizableFuncExpr optFuncExpr, OptimizableOperatorSubTree probeSubTree) { if (probeSubTree == null) { + if (optFuncExpr.getConstantExpressions().length == 0) { + return optFuncExpr.getLogicalExpr(0) == null; + } // We are optimizing a selection query. Search key is a constant. Return true if constant is on lhs. - return optFuncExpr.getFuncExpr().getArguments().get(0) == optFuncExpr.getConstantAtRuntimeExpr(0); + return optFuncExpr.getFuncExpr().getArguments().get(0) == optFuncExpr.getConstantExpr(0); } else { // We are optimizing a join query. Determine whether the feeding variable is on the lhs. return (optFuncExpr.getOperatorSubTree(0) == null || optFuncExpr.getOperatorSubTree(0) == probeSubTree); @@ -711,10 +733,21 @@ public class BTreeAccessMethod implements IAccessMethod { } @Override - public boolean exprIsOptimizable(Index index, IOptimizableFuncExpr optFuncExpr) { + public boolean exprIsOptimizable(Index index, IOptimizableFuncExpr optFuncExpr) throws AlgebricksException { // If we are optimizing a join, check for the indexed nested-loop join hint. if (optFuncExpr.getNumLogicalVars() == 2) { - if (!optFuncExpr.getFuncExpr().getAnnotations().containsKey(IndexedNLJoinExpressionAnnotation.INSTANCE)) { + if (optFuncExpr.getOperatorSubTree(0) == optFuncExpr.getOperatorSubTree(1)) { + if ((optFuncExpr.getSourceVar(0) == null && optFuncExpr.getFieldType(0) != null) + || (optFuncExpr.getSourceVar(1) == null && optFuncExpr.getFieldType(1) != null)) { + //We are in the select case (trees are the same, and one field comes from non-scan) + //We can do the index search + } else { + //One of the vars was from an assign rather than a scan + //And we were unable to determine its type + return false; + } + } else if (!optFuncExpr.getFuncExpr().getAnnotations() + .containsKey(IndexedNLJoinExpressionAnnotation.INSTANCE)) { return false; } } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java index 5691d57..d249b96 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java @@ -30,7 +30,6 @@ import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCa import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment; import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier; import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator; -import org.apache.hyracks.data.std.api.IDataOutputProvider; /** * Interface that an access method should implement to work with the rewrite @@ -38,7 +37,7 @@ import org.apache.hyracks.data.std.api.IDataOutputProvider; * methods for analyzing a select/join condition, and for rewriting the plan * with a given index. */ -public interface IAccessMethod extends Comparable<IAccessMethod>{ +public interface IAccessMethod extends Comparable<IAccessMethod> { /** * @return A list of function identifiers that are optimizable by this @@ -80,19 +79,17 @@ public interface IAccessMethod extends Comparable<IAccessMethod>{ /** * Applies the plan transformation to use chosenIndex to optimize a selection query. + * + * @param afterSelectRefs */ - public boolean applySelectPlanTransformation(Mutable<ILogicalOperator> selectRef, - OptimizableOperatorSubTree subTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx, - IOptimizationContext context) throws AlgebricksException; + public boolean applySelectPlanTransformation(List<Mutable<ILogicalOperator>> afterSelectRefs, + Mutable<ILogicalOperator> selectRef, OptimizableOperatorSubTree subTree, Index chosenIndex, + AccessMethodAnalysisContext analysisCtx, IOptimizationContext context) throws AlgebricksException; public ILogicalOperator createSecondaryToPrimaryPlan(Mutable<ILogicalExpression> conditionRef, - OptimizableOperatorSubTree indexSubTree, - OptimizableOperatorSubTree probeSubTree, - Index chosenIndex, - AccessMethodAnalysisContext analysisCtx, - boolean retainInput, boolean retainNull, boolean requiresBroadcast, - IOptimizationContext context) - throws AlgebricksException; + OptimizableOperatorSubTree indexSubTree, OptimizableOperatorSubTree probeSubTree, Index chosenIndex, + AccessMethodAnalysisContext analysisCtx, boolean retainInput, boolean retainNull, boolean requiresBroadcast, + IOptimizationContext context) throws AlgebricksException; /** * Applies the plan transformation to use chosenIndex to optimize a join query. http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java index b4f8c9f..05dc4a6 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java @@ -35,7 +35,7 @@ public interface IOptimizableFuncExpr { public int getNumLogicalVars(); - public int getNumConstantAtRuntimeExpr(); + public int getNumConstantExpr(); public LogicalVariable getLogicalVar(int index); @@ -55,7 +55,7 @@ public interface IOptimizableFuncExpr { public OptimizableOperatorSubTree getOperatorSubTree(int index); - public ILogicalExpression getConstantAtRuntimeExpr(int index); + public ILogicalExpression getConstantExpr(int index); public int findLogicalVar(LogicalVariable var); @@ -75,5 +75,7 @@ public interface IOptimizableFuncExpr { IAType getConstantType(int index); - void setConstantAtRuntimeExpr(int index, ILogicalExpression expr); + void setConstantExpr(int index, ILogicalExpression expr); + + ILogicalExpression[] getConstantExpressions(); } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java index 02fb2a5..53f7a72 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java @@ -131,7 +131,7 @@ public class IntroduceLSMComponentFilterRule implements IAlgebraicRewriteRule { for (IOptimizableFuncExpr optFuncExpr : optFuncExprs) { ComparisonKind ck = AlgebricksBuiltinFunctions .getComparisonType(optFuncExpr.getFuncExpr().getFunctionIdentifier()); - ILogicalExpression searchKeyExpr = optFuncExpr.getConstantAtRuntimeExpr(0); + ILogicalExpression searchKeyExpr = optFuncExpr.getConstantExpr(0); LogicalVariable var = context.newVar(); assignKeyExprList.add(new MutableObject<ILogicalExpression>(searchKeyExpr)); assignKeyVarList.add(var); http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java index 434b961..1d332b6 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Optional; import java.util.TreeMap; +import org.apache.asterix.algebra.operators.CommitOperator; import org.apache.asterix.metadata.declared.MetadataProvider; import org.apache.asterix.metadata.entities.Index; import org.apache.commons.lang3.mutable.Mutable; @@ -42,6 +43,8 @@ import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvir import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression; import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier; import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator.ExecutionMode; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.IntersectOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator; @@ -79,10 +82,11 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth // Operators representing the patterns to be matched: // These ops are set in matchesPattern() protected Mutable<ILogicalOperator> selectRef = null; - protected SelectOperator select = null; + protected SelectOperator selectOp = null; protected AbstractFunctionCallExpression selectCond = null; protected IVariableTypeEnvironment typeEnvironment = null; protected final OptimizableOperatorSubTree subTree = new OptimizableOperatorSubTree(); + protected List<Mutable<ILogicalOperator>> afterSelectRefs = null; // Register access methods. protected static Map<FunctionIdentifier, List<IAccessMethod>> accessMethods = new HashMap<FunctionIdentifier, List<IAccessMethod>>(); @@ -93,46 +97,111 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth registerAccessMethod(InvertedIndexAccessMethod.INSTANCE, accessMethods); } + /** + * Recursively check the given plan from the root operator to transform a plan + * with SELECT operator into an index-utilized plan. + */ @Override public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException { clear(); setMetadataDeclarations(context); - // Match operator pattern and initialize operator members. - if (!matchesOperatorPattern(opRef, context)) { + AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue(); + if (context.checkIfInDontApplySet(this, op)) { return false; } - // Analyze select condition. - Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs = new TreeMap<IAccessMethod, AccessMethodAnalysisContext>(); - if (!analyzeCondition(selectCond, subTree.getAssignsAndUnnests(), analyzedAMs, context, typeEnvironment)) { + //We start at the top of the plan + if (op.getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT + && op.getOperatorTag() != LogicalOperatorTag.SINK + && op.getOperatorTag() != LogicalOperatorTag.DELEGATE_OPERATOR) { return false; } - - // Set dataset and type metadata. - if (!subTree.setDatasetAndTypeMetadata((MetadataProvider) context.getMetadataProvider())) { + if (op.getOperatorTag() == LogicalOperatorTag.DELEGATE_OPERATOR + && !(((DelegateOperator) op).getDelegate() instanceof CommitOperator)) { return false; } - fillSubTreeIndexExprs(subTree, analyzedAMs, context); - pruneIndexCandidates(analyzedAMs, context, typeEnvironment); + afterSelectRefs = new ArrayList<>(); - // Choose index to be applied. - List<Pair<IAccessMethod, Index>> chosenIndexes = chooseAllIndex(analyzedAMs); - if (chosenIndexes == null || chosenIndexes.size() == 0) { - context.addToDontApplySet(this, select); + // Recursively check the given plan whether the desired pattern exists in it. + // If so, try to optimize the plan. + boolean planTransformed = checkAndApplyTheSelectTransformationRule(opRef, context); + + if (selectOp != null) { + // We found an optimization here. Don't need to optimize this operator again. + context.addToDontApplySet(this, selectOp); + } + + if (!planTransformed) { + // We found an optimization here. Don't need to optimize this operator again. return false; + } else { + OperatorPropertiesUtil.typeOpRec(opRef, context); + } - // Apply plan transformation using chosen index. - boolean res = intersectAllSecondaryIndexes(chosenIndexes, analyzedAMs, context); + return planTransformed; + } - if (res) { - OperatorPropertiesUtil.typeOpRec(opRef, context); + protected boolean checkAndApplyTheSelectTransformationRule(Mutable<ILogicalOperator> opRef, + IOptimizationContext context) throws AlgebricksException { + AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue(); + + // Match operator pattern and initialize operator members. + if (matchesOperatorPattern(opRef, context)) { + // Analyze select condition. + Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs = new TreeMap<>(); + if (!analyzeCondition(selectCond, subTree.getAssignsAndUnnests(), analyzedAMs, context, typeEnvironment)) { + return false; + } + + // Set dataset and type metadata. + if (!subTree.setDatasetAndTypeMetadata((MetadataProvider) context.getMetadataProvider())) { + return false; + } + + fillSubTreeIndexExprs(subTree, analyzedAMs, context); + pruneIndexCandidates(analyzedAMs, context, typeEnvironment); + + // Choose index to be applied. + List<Pair<IAccessMethod, Index>> chosenIndexes = chooseAllIndex(analyzedAMs); + if (chosenIndexes == null || chosenIndexes.isEmpty()) { + context.addToDontApplySet(this, selectOp); + return false; + } + + // Apply plan transformation using chosen index. + boolean res = intersectAllSecondaryIndexes(chosenIndexes, analyzedAMs, context); + + context.addToDontApplySet(this, selectOp); + if (res) { + OperatorPropertiesUtil.typeOpRec(opRef, context); + return res; + } + selectRef = null; + selectOp = null; + afterSelectRefs.add(opRef); + + } else { + // This is not a SELECT operator. Remember operators + afterSelectRefs.add(opRef); + + } + // Recursively check the plan and try to optimize it. + boolean selectFoundAndOptimizationApplied = false; + for (Mutable<ILogicalOperator> inputOpRef : op.getInputs()) { + boolean foundHere = checkAndApplyTheSelectTransformationRule(inputOpRef, context); + if (foundHere) { + selectFoundAndOptimizationApplied = true; + } } - context.addToDontApplySet(this, select); - return res; + + // Clean the path after SELECT operator by removing the current operator in the list. + afterSelectRefs.remove(opRef); + return selectFoundAndOptimizationApplied; + } private boolean intersectAllSecondaryIndexes(List<Pair<IAccessMethod, Index>> chosenIndexes, @@ -149,18 +218,22 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth } if (chosenIndex != null) { AccessMethodAnalysisContext analysisCtx = analyzedAMs.get(chosenIndex.first); - return chosenIndex.first.applySelectPlanTransformation(selectRef, subTree, chosenIndex.second, analysisCtx, - context); + return chosenIndex.first.applySelectPlanTransformation(afterSelectRefs, selectRef, subTree, + chosenIndex.second, analysisCtx, context); } // Intersect all secondary indexes, and postpone the primary index search. - Mutable<ILogicalExpression> conditionRef = select.getCondition(); + Mutable<ILogicalExpression> conditionRef = selectOp.getCondition(); List<ILogicalOperator> subRoots = new ArrayList<>(); for (Pair<IAccessMethod, Index> pair : chosenIndexes) { AccessMethodAnalysisContext analysisCtx = analyzedAMs.get(pair.first); subRoots.add(pair.first.createSecondaryToPrimaryPlan(conditionRef, subTree, null, pair.second, analysisCtx, - false, false, false, context)); + AccessMethodUtils.retainInputs(subTree.getDataSourceVariables(), + subTree.getDataSourceRef().getValue(), afterSelectRefs), + false, subTree.getDataSourceRef().getValue().getInputs().get(0).getValue() + .getExecutionMode() == ExecutionMode.UNPARTITIONED, + context)); } ILogicalOperator primaryUnnest = connectAll2ndarySearchPlanWithIntersect(subRoots, context); @@ -217,11 +290,11 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth } // Set and analyze select. selectRef = opRef; - select = (SelectOperator) op1; + selectOp = (SelectOperator) op1; typeEnvironment = context.getOutputTypeEnvironment(op1); // Check that the select's condition is a function call. - ILogicalExpression condExpr = select.getCondition().getValue(); + ILogicalExpression condExpr = selectOp.getCondition().getValue(); if (condExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) { return false; } @@ -236,8 +309,9 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth } private void clear() { + afterSelectRefs = null; selectRef = null; - select = null; + selectOp = null; selectCond = null; } } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java index e43af61..066757d 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java @@ -144,7 +144,7 @@ public class InvertedIndexAccessMethod implements IAccessMethod { public boolean analyzeGetItemFuncExpr(AbstractFunctionCallExpression funcExpr, List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx) - throws AlgebricksException { + throws AlgebricksException { if (funcExpr.getFunctionIdentifier() != AsterixBuiltinFunctions.GET_ITEM) { return false; } @@ -436,11 +436,15 @@ public class InvertedIndexAccessMethod implements IAccessMethod { } @Override - public boolean applySelectPlanTransformation(Mutable<ILogicalOperator> selectRef, - OptimizableOperatorSubTree subTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx, - IOptimizationContext context) throws AlgebricksException { + public boolean applySelectPlanTransformation(List<Mutable<ILogicalOperator>> afterSelectRefs, + Mutable<ILogicalOperator> selectRef, OptimizableOperatorSubTree subTree, Index chosenIndex, + AccessMethodAnalysisContext analysisCtx, IOptimizationContext context) throws AlgebricksException { ILogicalOperator indexPlanRootOp = createSecondaryToPrimaryPlan(null, subTree, null, chosenIndex, analysisCtx, - false, false, false, context); + AccessMethodUtils.retainInputs(subTree.getDataSourceVariables(), subTree.getDataSourceRef().getValue(), + afterSelectRefs), + false, subTree.getDataSourceRef().getValue().getInputs().get(0).getValue() + .getExecutionMode() == ExecutionMode.UNPARTITIONED, + context); // Replace the datasource scan with the new plan rooted at primaryIndexUnnestMap. subTree.getDataSourceRef().setValue(indexPlanRootOp); return true; @@ -737,7 +741,7 @@ public class InvertedIndexAccessMethod implements IAccessMethod { isFilterableArgs .add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(inputSearchVar))); // Since we are optimizing a join, the similarity threshold should be the only constant in the optimizable function expression. - isFilterableArgs.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantAtRuntimeExpr(0))); + isFilterableArgs.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantExpr(0))); isFilterableArgs.add(new MutableObject<ILogicalExpression>( AccessMethodUtils.createInt32Constant(chosenIndex.getGramLength()))); boolean usePrePost = optFuncExpr.containsPartialField() ? false : true; @@ -754,7 +758,7 @@ public class InvertedIndexAccessMethod implements IAccessMethod { isFilterableArgs .add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(inputSearchVar))); // Since we are optimizing a join, the similarity threshold should be the only constant in the optimizable function expression. - isFilterableArgs.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantAtRuntimeExpr(0))); + isFilterableArgs.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantExpr(0))); isFilterableExpr = new ScalarFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.EDIT_DISTANCE_LIST_IS_FILTERABLE), isFilterableArgs); @@ -828,8 +832,9 @@ public class InvertedIndexAccessMethod implements IAccessMethod { if (optFuncExpr.getFuncExpr().getFunctionIdentifier() == AsterixBuiltinFunctions.SIMILARITY_JACCARD_CHECK) { jobGenParams.setSearchModifierType(SearchModifierType.JACCARD); // Add the similarity threshold which, by convention, is the last constant value. - jobGenParams.setSimilarityThreshold(((ConstantExpression) optFuncExpr - .getConstantAtRuntimeExpr(optFuncExpr.getNumConstantAtRuntimeExpr() - 1)).getValue()); + jobGenParams.setSimilarityThreshold( + ((ConstantExpression) optFuncExpr.getConstantExpr(optFuncExpr.getNumConstantExpr() - 1)) + .getValue()); } if (optFuncExpr.getFuncExpr().getFunctionIdentifier() == AsterixBuiltinFunctions.EDIT_DISTANCE_CHECK || optFuncExpr.getFuncExpr() @@ -840,19 +845,20 @@ public class InvertedIndexAccessMethod implements IAccessMethod { jobGenParams.setSearchModifierType(SearchModifierType.EDIT_DISTANCE); } // Add the similarity threshold which, by convention, is the last constant value. - jobGenParams.setSimilarityThreshold(((ConstantExpression) optFuncExpr - .getConstantAtRuntimeExpr(optFuncExpr.getNumConstantAtRuntimeExpr() - 1)).getValue()); + jobGenParams.setSimilarityThreshold( + ((ConstantExpression) optFuncExpr.getConstantExpr(optFuncExpr.getNumConstantExpr() - 1)) + .getValue()); } } private void addKeyVarsAndExprs(IOptimizableFuncExpr optFuncExpr, ArrayList<LogicalVariable> keyVarList, ArrayList<Mutable<ILogicalExpression>> keyExprList, IOptimizationContext context) - throws AlgebricksException { + throws AlgebricksException { // For now we are assuming a single secondary index key. // Add a variable and its expr to the lists which will be passed into an assign op. LogicalVariable keyVar = context.newVar(); keyVarList.add(keyVar); - keyExprList.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantAtRuntimeExpr(0))); + keyExprList.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantExpr(0))); return; } @@ -882,7 +888,7 @@ public class InvertedIndexAccessMethod implements IAccessMethod { private boolean isEditDistanceFuncOptimizable(Index index, IOptimizableFuncExpr optFuncExpr) throws AlgebricksException { - if (optFuncExpr.getNumConstantAtRuntimeExpr() == 1) { + if (optFuncExpr.getNumConstantExpr() == 1) { return isEditDistanceFuncJoinOptimizable(index, optFuncExpr); } else { return isEditDistanceFuncSelectOptimizable(index, optFuncExpr); @@ -917,7 +923,7 @@ public class InvertedIndexAccessMethod implements IAccessMethod { // Check for panic in selection query. // TODO: Panic also depends on prePost which is currently hardcoded to be true. AsterixConstantValue listOrStrConstVal = (AsterixConstantValue) ((ConstantExpression) optFuncExpr - .getConstantAtRuntimeExpr(0)).getValue(); + .getConstantExpr(0)).getValue(); IAObject listOrStrObj = listOrStrConstVal.getObject(); ATypeTag typeTag = listOrStrObj.getType().getTypeTag(); @@ -925,8 +931,8 @@ public class InvertedIndexAccessMethod implements IAccessMethod { return false; } - AsterixConstantValue intConstVal = (AsterixConstantValue) ((ConstantExpression) optFuncExpr - .getConstantAtRuntimeExpr(1)).getValue(); + AsterixConstantValue intConstVal = (AsterixConstantValue) ((ConstantExpression) optFuncExpr.getConstantExpr(1)) + .getValue(); IAObject intObj = intConstVal.getObject(); AInt32 edThresh = null; @@ -1084,8 +1090,8 @@ public class InvertedIndexAccessMethod implements IAccessMethod { } private boolean isContainsFuncSelectOptimizable(Index index, IOptimizableFuncExpr optFuncExpr) { - AsterixConstantValue strConstVal = (AsterixConstantValue) ((ConstantExpression) optFuncExpr - .getConstantAtRuntimeExpr(0)).getValue(); + AsterixConstantValue strConstVal = (AsterixConstantValue) ((ConstantExpression) optFuncExpr.getConstantExpr(0)) + .getValue(); IAObject strObj = strConstVal.getObject(); ATypeTag typeTag = strObj.getType().getTypeTag(); http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java index 2ecd504..d792e3d 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java @@ -39,8 +39,8 @@ public class OptimizableFuncExpr implements IOptimizableFuncExpr { protected final List<List<String>> fieldNames; protected final IAType[] fieldTypes; protected final OptimizableOperatorSubTree[] subTrees; - protected final ILogicalExpression[] constantAtRuntimeExpressions; - protected final IAType[] constantAtRuntimeExpressionTypes; + protected final ILogicalExpression[] constantExpressions; + protected final IAType[] constantExpressionTypes; protected boolean partialField; public OptimizableFuncExpr(AbstractFunctionCallExpression funcExpr, LogicalVariable[] logicalVars, @@ -49,8 +49,8 @@ public class OptimizableFuncExpr implements IOptimizableFuncExpr { this.logicalVars = logicalVars; this.sourceVars = new LogicalVariable[logicalVars.length]; this.logicalExprs = new ILogicalExpression[logicalVars.length]; - this.constantAtRuntimeExpressionTypes = constantExpressionTypes; - this.constantAtRuntimeExpressions = constantExpressions; + this.constantExpressionTypes = constantExpressionTypes; + this.constantExpressions = constantExpressions; this.fieldNames = new ArrayList<List<String>>(); for (int i = 0; i < logicalVars.length; i++) { fieldNames.add(new ArrayList<String>()); @@ -72,8 +72,8 @@ public class OptimizableFuncExpr implements IOptimizableFuncExpr { this.logicalVars = new LogicalVariable[] { logicalVar }; this.sourceVars = new LogicalVariable[1]; this.logicalExprs = new ILogicalExpression[1]; - this.constantAtRuntimeExpressions = new ILogicalExpression[] { constantExpression }; - this.constantAtRuntimeExpressionTypes = new IAType[] { constantExpressionType }; + this.constantExpressions = new ILogicalExpression[] { constantExpression }; + this.constantExpressionTypes = new IAType[] { constantExpressionType }; this.fieldNames = new ArrayList<List<String>>(); for (int i = 0; i < logicalVars.length; i++) { fieldNames.add(new ArrayList<String>()); @@ -98,8 +98,8 @@ public class OptimizableFuncExpr implements IOptimizableFuncExpr { } @Override - public int getNumConstantAtRuntimeExpr() { - return constantAtRuntimeExpressions.length; + public int getNumConstantExpr() { + return constantExpressions.length; } @Override @@ -138,23 +138,28 @@ public class OptimizableFuncExpr implements IOptimizableFuncExpr { } @Override - public ILogicalExpression getConstantAtRuntimeExpr(int index) { - return constantAtRuntimeExpressions[index]; + public ILogicalExpression getConstantExpr(int index) { + return constantExpressions[index]; + } + + @Override + public ILogicalExpression[] getConstantExpressions() { + return constantExpressions; } @Override public void setConstType(int index, IAType fieldType) { - constantAtRuntimeExpressionTypes[index] = fieldType; + constantExpressionTypes[index] = fieldType; } @Override public IAType getConstantType(int index) { - return constantAtRuntimeExpressionTypes[index]; + return constantExpressionTypes[index]; } @Override - public void setConstantAtRuntimeExpr(int index, ILogicalExpression expr) { - constantAtRuntimeExpressions[index] = expr; + public void setConstantExpr(int index, ILogicalExpression expr) { + constantExpressions[index] = expr; } @Override http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableOperatorSubTree.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableOperatorSubTree.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableOperatorSubTree.java index 75ee46b..1869d60 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableOperatorSubTree.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableOperatorSubTree.java @@ -42,6 +42,7 @@ import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable; import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression; import org.apache.hyracks.algebricks.core.algebra.metadata.IDataSource; import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator; +import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator.ExecutionMode; import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractScanOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestOperator; import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator; @@ -85,36 +86,50 @@ public class OptimizableOperatorSubTree { reset(); rootRef = subTreeOpRef; root = subTreeOpRef.getValue(); + boolean passedSource = false; + boolean result = false; + Mutable<ILogicalOperator> searchOpRef = subTreeOpRef; // Examine the op's children to match the expected patterns. - AbstractLogicalOperator subTreeOp = (AbstractLogicalOperator) subTreeOpRef.getValue(); + AbstractLogicalOperator subTreeOp = (AbstractLogicalOperator) searchOpRef.getValue(); do { // Skip select operator. if (subTreeOp.getOperatorTag() == LogicalOperatorTag.SELECT) { - subTreeOpRef = subTreeOp.getInputs().get(0); - subTreeOp = (AbstractLogicalOperator) subTreeOpRef.getValue(); + searchOpRef = subTreeOp.getInputs().get(0); + subTreeOp = (AbstractLogicalOperator) searchOpRef.getValue(); } // Check primary-index pattern. if (subTreeOp.getOperatorTag() != LogicalOperatorTag.ASSIGN && subTreeOp.getOperatorTag() != LogicalOperatorTag.UNNEST) { // Pattern may still match if we are looking for primary index matches as well. - return initializeDataSource(subTreeOpRef); + result = initializeDataSource(searchOpRef); + passedSource = true; + if (!subTreeOp.getInputs().isEmpty()) { + searchOpRef = subTreeOp.getInputs().get(0); + subTreeOp = (AbstractLogicalOperator) searchOpRef.getValue(); + } } // Match (assign | unnest)+. - while ((subTreeOp.getOperatorTag() == LogicalOperatorTag.ASSIGN - || subTreeOp.getOperatorTag() == LogicalOperatorTag.UNNEST)) { - if (!OperatorPropertiesUtil.isMovable(subTreeOp)) { + while (subTreeOp.getOperatorTag() == LogicalOperatorTag.ASSIGN + || subTreeOp.getOperatorTag() == LogicalOperatorTag.UNNEST) { + if (!passedSource && !OperatorPropertiesUtil.isMovable(subTreeOp)) { return false; - } else { - getAssignsAndUnnestsRefs().add(subTreeOpRef); - getAssignsAndUnnests().add(subTreeOp); } - subTreeOpRef = subTreeOp.getInputs().get(0); - subTreeOp = (AbstractLogicalOperator) subTreeOpRef.getValue(); + if (subTreeOp.getExecutionMode() != ExecutionMode.UNPARTITIONED) { + //The unpartitioned ops should stay below the search + assignsAndUnnestsRefs.add(searchOpRef); + } + assignsAndUnnests.add(subTreeOp); + + searchOpRef = subTreeOp.getInputs().get(0); + subTreeOp = (AbstractLogicalOperator) searchOpRef.getValue(); + } + if (passedSource) { + return result; } } while (subTreeOp.getOperatorTag() == LogicalOperatorTag.SELECT); // Match data source (datasource scan or primary index search). - return initializeDataSource(subTreeOpRef); + return initializeDataSource(searchOpRef); } private boolean initializeDataSource(Mutable<ILogicalOperator> subTreeOpRef) { @@ -395,8 +410,8 @@ public class OptimizableOperatorSubTree { case DATASOURCE_SCAN: case EXTERNAL_SCAN: case PRIMARY_INDEX_LOOKUP: - AbstractScanOperator scanOp = - (AbstractScanOperator) getIxJoinOuterAdditionalDataSourceRefs().get(idx).getValue(); + AbstractScanOperator scanOp = (AbstractScanOperator) getIxJoinOuterAdditionalDataSourceRefs() + .get(idx).getValue(); return scanOp.getVariables(); case COLLECTION_SCAN: return new ArrayList<>(); http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java index c3c162e..eeaaa8d 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java @@ -95,12 +95,14 @@ public class RTreeAccessMethod implements IAccessMethod { } @Override - public boolean applySelectPlanTransformation(Mutable<ILogicalOperator> selectRef, - OptimizableOperatorSubTree subTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx, - IOptimizationContext context) throws AlgebricksException { + public boolean applySelectPlanTransformation(List<Mutable<ILogicalOperator>> afterSelectRefs, + Mutable<ILogicalOperator> selectRef, OptimizableOperatorSubTree subTree, Index chosenIndex, + AccessMethodAnalysisContext analysisCtx, IOptimizationContext context) throws AlgebricksException { // TODO: We can probably do something smarter here based on selectivity or MBR area. ILogicalOperator primaryIndexUnnestOp = createSecondaryToPrimaryPlan(subTree, null, chosenIndex, analysisCtx, - false, false, false, context); + AccessMethodUtils.retainInputs(subTree.getDataSourceVariables(), subTree.getDataSourceRef().getValue(), + afterSelectRefs), + false, false, context); if (primaryIndexUnnestOp == null) { return false; } http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-no-index.aql ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-no-index.aql b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-no-index.aql new file mode 100644 index 0000000..bd3f019 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-no-index.aql @@ -0,0 +1,41 @@ +/* + * 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. + */ + + /* + * Description : Time should be unpartitioned and Broadcast to nodes + * Expected Result : Success + * Date : 20th Oct 2016 + */ + +drop dataverse channels if exists; +create dataverse channels; +use dataverse channels; + +create type userLocation as { + userId: int, + stamp: datetime +} + +create dataset Users(userLocation) +primary key userId; + +let $time := current-datetime() +for $result in dataset Users +where $result.stamp = $time +return $time \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-use-index-return-time.aql ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-use-index-return-time.aql b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-use-index-return-time.aql new file mode 100644 index 0000000..34c4e30 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-use-index-return-time.aql @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/* + * Description : Time should be unpartitioned + * : but used by index and returned + * Expected Result : Success + * Date : 20th Oct 2016 + */ + +drop dataverse channels if exists; +create dataverse channels; +use dataverse channels; + +create type userLocation as { + userId: int, + stamp: datetime +} + +create dataset Users(userLocation) +primary key stamp; + +let $time := current-datetime() +for $result in dataset Users +where $result.stamp = $time +return { + "date":$time, + "result":$result +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-use-index.aql ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-use-index.aql b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-use-index.aql new file mode 100644 index 0000000..010ad6f --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/global-datetime-use-index.aql @@ -0,0 +1,42 @@ +/* + * 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. + */ + + /* + * Description : Time should be unpartitioned + * : but used by index + * Expected Result : Success + * Date : 20th Oct 2016 + */ + +drop dataverse channels if exists; +create dataverse channels; +use dataverse channels; + +create type userLocation as { + userId: int, + stamp: datetime +} + +create dataset Users(userLocation) +primary key stamp; + +let $time := current-datetime() +for $result in dataset Users +where $result.stamp = $time +return $result \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/keep-datetime-local.aql ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/keep-datetime-local.aql b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/keep-datetime-local.aql new file mode 100644 index 0000000..bb0ffc1 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/keep-datetime-local.aql @@ -0,0 +1,74 @@ +/* + * 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. + */ + +/* + * Description : Time should remain partitoned + * : and be returned + * Expected Result : Success + * Date : 20th Oct 2016 + */ + +drop dataverse test if exists; +create dataverse test; +use dataverse test; + +create type TwitterUserType as closed { + screen-name: string, + lang: string, + friends-count: int32, + statuses-count: int32, + name: string, + followers-count: int32 +} + +create type TweetMessageType as closed { + tweetid: int64, + user: TwitterUserType, + sender-location: point, + send-time: datetime, + referred-topics: {{ string }}, + message-text: string, + countA: int32, + countB: int32 +} + +create dataset TweetMessages(TweetMessageType) +primary key tweetid; + +create index twmSndLocIx on TweetMessages(sender-location) type rtree; +create index msgCountAIx on TweetMessages(countA) type btree; +create index msgCountBIx on TweetMessages(countB) type btree; +create index msgTextIx on TweetMessages(message-text) type keyword; + +write output to asterix_nc1:"rttest/btree-index-join_leftouterjoin-probe-pidx-with-join-btree-sidx_01.adm"; + +for $t1 in dataset('TweetMessages') +let $time := current-datetime() +where $t1.tweetid < int64("10") +order by $t1.tweetid +return { +"time": $time, +"tweetid1": $t1.tweetid, +"count1":$t1.countA, +"t2info": for $t2 in dataset('TweetMessages') + where $t1.countA /* +indexnl */= $t2.countB + order by $t2.tweetid + return {"tweetid2": $t2.tweetid, + "count2":$t2.countB} +}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/local-datetime-ignore-index.aql ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/local-datetime-ignore-index.aql b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/local-datetime-ignore-index.aql new file mode 100644 index 0000000..1077257 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/local-datetime-ignore-index.aql @@ -0,0 +1,42 @@ +/* + * 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. + */ + + /* + * Description : Time should remain partitoned + * : and therefore unusable by index + * Expected Result : Success + * Date : 20th Oct 2016 + */ + +drop dataverse channels if exists; +create dataverse channels; +use dataverse channels; + +create type userLocation as { + userId: int, + stamp: datetime +} + +create dataset Users(userLocation) +primary key stamp; + +for $result in dataset Users +let $time := current-datetime() +where $result.stamp = $time +return $result \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/local-datetime-no-index.aql ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/local-datetime-no-index.aql b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/local-datetime-no-index.aql new file mode 100644 index 0000000..5083aaa --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/local-datetime-no-index.aql @@ -0,0 +1,42 @@ +/* + * 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. + */ + +/* + * Description : Time should remain partitoned + * : and be returned + * Expected Result : Success + * Date : 20th Oct 2016 + */ + +drop dataverse channels if exists; +create dataverse channels; +use dataverse channels; + +create type userLocation as { + userId: int, + stamp: datetime +} + +create dataset Users(userLocation) +primary key userId; + +for $result in dataset Users +let $time := current-datetime() +where $result.stamp = $time +return $time \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/maintain-nonpure-location-in-join-cannot-index.aql ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/maintain-nonpure-location-in-join-cannot-index.aql b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/maintain-nonpure-location-in-join-cannot-index.aql new file mode 100644 index 0000000..4a7b695 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/maintain-nonpure-location-in-join-cannot-index.aql @@ -0,0 +1,48 @@ +/* + * 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. + */ + + /* + * Description : Time should remain partitoned + * Expected Result : Success + * Date : 20th Oct 2016 + */ + +drop dataverse channels if exists; +create dataverse channels; +use dataverse channels; + +create type userLocation as { + id: int, + stamp: time +} + +create dataset Users1(userLocation) +primary key stamp; + +create dataset Users2(userLocation) +primary key stamp; + +for $x in dataset Users1 +let $time := current-time() +for $y in dataset Users2 +where $y.stamp > $time-time("123045678+0800") +return { + "x_id": $x.id, + "y_id": $y.id +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/query-ASTERIXDB-1608.aql ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/query-ASTERIXDB-1608.aql b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/query-ASTERIXDB-1608.aql new file mode 100644 index 0000000..04620bd --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/nonpure/query-ASTERIXDB-1608.aql @@ -0,0 +1,33 @@ +/* + * 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. + */ + +/* + * Description : Check fix for ASTERIXDB-1608 + * Expected Result : Success + * Date : 20th Oct 2016 + */ + + +drop dataverse test if exists; +create dataverse test; + +for $x in range(1, 3) +for $y in range(1, 3) +return +{"id": create-uuid(), "x": $x} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-02.plan ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-02.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-02.plan index a9e223a..a461461 100644 --- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-02.plan +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-02.plan @@ -1,8 +1,9 @@ -- DISTRIBUTE_RESULT |PARTITIONED| -- ONE_TO_ONE_EXCHANGE |PARTITIONED| -- STREAM_PROJECT |PARTITIONED| - -- ONE_TO_ONE_EXCHANGE |PARTITIONED| - -- BTREE_SEARCH |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- ASSIGN |PARTITIONED| -- ONE_TO_ONE_EXCHANGE |PARTITIONED| - -- ASSIGN |PARTITIONED| - -- EMPTY_TUPLE_SOURCE |PARTITIONED| \ No newline at end of file + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-no-index.plan ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-no-index.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-no-index.plan new file mode 100644 index 0000000..82d3768 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-no-index.plan @@ -0,0 +1,10 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- ASSIGN |UNPARTITIONED| + -- EMPTY_TUPLE_SOURCE |UNPARTITIONED| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-use-index-return-time.plan ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-use-index-return-time.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-use-index-return-time.plan new file mode 100644 index 0000000..c6fd83e --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-use-index-return-time.plan @@ -0,0 +1,12 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- BTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STABLE_SORT [$$0(ASC)] |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$0] |PARTITIONED| + -- ASSIGN |UNPARTITIONED| + -- EMPTY_TUPLE_SOURCE |UNPARTITIONED| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-use-index.plan ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-use-index.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-use-index.plan new file mode 100644 index 0000000..972e56a --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/global-datetime-use-index.plan @@ -0,0 +1,10 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- BTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STABLE_SORT [$$0(ASC)] |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$0] |PARTITIONED| + -- ASSIGN |UNPARTITIONED| + -- EMPTY_TUPLE_SOURCE |UNPARTITIONED| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/keep-datetime-local.plan ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/keep-datetime-local.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/keep-datetime-local.plan new file mode 100644 index 0000000..5246d83 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/keep-datetime-local.plan @@ -0,0 +1,36 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- SORT_MERGE_EXCHANGE [$$22(ASC) ] |PARTITIONED| + -- STABLE_SORT [$$22(ASC)] |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- PRE_CLUSTERED_GROUP_BY[$$30] |PARTITIONED| + { + -- AGGREGATE |LOCAL| + -- STREAM_SELECT |LOCAL| + -- NESTED_TUPLE_SOURCE |LOCAL| + } + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STABLE_SORT [$$30(ASC), $$23(ASC)] |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$30] |PARTITIONED| + -- HYBRID_HASH_JOIN [$$25][$$24] |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$25] |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$24] |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/local-datetime-ignore-index.plan ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/local-datetime-ignore-index.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/local-datetime-ignore-index.plan new file mode 100644 index 0000000..a461461 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/local-datetime-ignore-index.plan @@ -0,0 +1,9 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/local-datetime-no-index.plan ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/local-datetime-no-index.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/local-datetime-no-index.plan new file mode 100644 index 0000000..2d604a9 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/local-datetime-no-index.plan @@ -0,0 +1,10 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/maintain-nonpure-location-in-join-cannot-index.plan ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/maintain-nonpure-location-in-join-cannot-index.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/maintain-nonpure-location-in-join-cannot-index.plan new file mode 100644 index 0000000..fe2675b --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/maintain-nonpure-location-in-join-cannot-index.plan @@ -0,0 +1,25 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- NESTED_LOOP |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| \ No newline at end of file http://git-wip-us.apache.org/repos/asf/asterixdb/blob/6b8a42f3/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/query-ASTERIXDB-1608.plan ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/query-ASTERIXDB-1608.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/query-ASTERIXDB-1608.plan new file mode 100644 index 0000000..1864e29 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/nonpure/query-ASTERIXDB-1608.plan @@ -0,0 +1,13 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- NESTED_LOOP |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |UNPARTITIONED| + -- UNNEST |UNPARTITIONED| + -- EMPTY_TUPLE_SOURCE |UNPARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |UNPARTITIONED| + -- UNNEST |UNPARTITIONED| + -- EMPTY_TUPLE_SOURCE |UNPARTITIONED| \ No newline at end of file
