Convert comparisons with current-datetime, current-date, and current-time to applicable index searches as though they were constants
Change-Id: Ied64276873afcfbdd31dac313009e47429d8f9b0
Reviewed-on: https://asterix-gerrit.ics.uci.edu/367
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Yingyi Bu <buyingyi@gmail.com>
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
index b736361..d274259 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
@@ -25,8 +25,6 @@
import java.util.List;
import java.util.Map;
-import org.apache.commons.lang3.mutable.Mutable;
-
import org.apache.asterix.common.config.DatasetConfig.IndexType;
import org.apache.asterix.dataflow.data.common.AqlExpressionTypeComputer;
import org.apache.asterix.metadata.api.IMetadataEntity;
@@ -44,6 +42,7 @@
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
import org.apache.asterix.optimizer.rules.am.OptimizableOperatorSubTree.DataSourceType;
+import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
@@ -110,14 +109,14 @@
}
}
- protected void pruneIndexCandidates(Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs)
- throws AlgebricksException {
+ protected void pruneIndexCandidates(Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs,
+ IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
Iterator<Map.Entry<IAccessMethod, AccessMethodAnalysisContext>> amIt = analyzedAMs.entrySet().iterator();
// Check applicability of indexes by access method type.
while (amIt.hasNext()) {
Map.Entry<IAccessMethod, AccessMethodAnalysisContext> entry = amIt.next();
AccessMethodAnalysisContext amCtx = entry.getValue();
- pruneIndexCandidates(entry.getKey(), amCtx);
+ pruneIndexCandidates(entry.getKey(), amCtx, context, typeEnvironment);
// Remove access methods for which there are definitely no
// applicable indexes.
if (amCtx.indexExprsAndVars.isEmpty()) {
@@ -174,11 +173,11 @@
* only require a match on a prefix of fields to be applicable. This methods
* removes all index candidates indexExprs that are definitely not
* applicable according to the expressions involved.
- *
+ *
* @throws AlgebricksException
*/
- public void pruneIndexCandidates(IAccessMethod accessMethod, AccessMethodAnalysisContext analysisCtx)
- throws AlgebricksException {
+ public void pruneIndexCandidates(IAccessMethod accessMethod, AccessMethodAnalysisContext analysisCtx,
+ IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
Iterator<Map.Entry<Index, List<Pair<Integer, Integer>>>> indexExprAndVarIt = analysisCtx.indexExprsAndVars
.entrySet().iterator();
// Used to keep track of matched expressions (added for prefix search)
@@ -222,11 +221,14 @@
for (int j = 0; j < optFuncExpr.getNumLogicalVars(); j++)
if (j != exprAndVarIdx.second)
indexedTypes.add(optFuncExpr.getFieldType(j));
+
//add constants in case of select
- if (indexedTypes.size() < 2 && optFuncExpr.getNumLogicalVars() == 1) {
- indexedTypes.add((IAType) AqlExpressionTypeComputer.INSTANCE.getType(new ConstantExpression(
- optFuncExpr.getConstantVal(0)), null, null));
+ if (indexedTypes.size() < 2 && optFuncExpr.getNumLogicalVars() == 1
+ && optFuncExpr.getNumConstantAtRuntimeExpr() > 0) {
+ indexedTypes.add((IAType) AqlExpressionTypeComputer.INSTANCE.getType(
+ optFuncExpr.getConstantAtRuntimeExpr(0), context.getMetadataProvider(), typeEnvironment));
}
+
//infer type of logicalExpr based on index keyType
indexedTypes.add((IAType) AqlExpressionTypeComputer.INSTANCE.getType(
optFuncExpr.getLogicalExpr(exprAndVarIdx.second), null, new IVariableTypeEnvironment() {
@@ -329,9 +331,12 @@
* Analyzes the given selection condition, filling analyzedAMs with
* applicable access method types. At this point we are not yet consulting
* the metadata whether an actual index exists or not.
+ *
+ * @throws AlgebricksException
*/
protected boolean analyzeCondition(ILogicalExpression cond, List<AbstractLogicalOperator> assignsAndUnnests,
- Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs) {
+ Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs, IOptimizationContext context,
+ IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) cond;
FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
// Don't consider optimizing a disjunctive condition with an index (too
@@ -339,14 +344,15 @@
if (funcIdent == AlgebricksBuiltinFunctions.OR) {
return false;
}
- boolean found = analyzeFunctionExpr(funcExpr, assignsAndUnnests, analyzedAMs);
+ boolean found = analyzeFunctionExpr(funcExpr, assignsAndUnnests, analyzedAMs, context, typeEnvironment);
for (Mutable<ILogicalExpression> arg : funcExpr.getArguments()) {
ILogicalExpression argExpr = arg.getValue();
if (argExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
continue;
}
AbstractFunctionCallExpression argFuncExpr = (AbstractFunctionCallExpression) argExpr;
- boolean matchFound = analyzeFunctionExpr(argFuncExpr, assignsAndUnnests, analyzedAMs);
+ boolean matchFound = analyzeFunctionExpr(argFuncExpr, assignsAndUnnests, analyzedAMs, context,
+ typeEnvironment);
found = found || matchFound;
}
return found;
@@ -356,9 +362,13 @@
* Finds applicable access methods for the given function expression based
* on the function identifier, and an analysis of the function's arguments.
* Updates the analyzedAMs accordingly.
+ *
+ * @throws AlgebricksException
*/
protected boolean analyzeFunctionExpr(AbstractFunctionCallExpression funcExpr,
- List<AbstractLogicalOperator> assignsAndUnnests, Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs) {
+ List<AbstractLogicalOperator> assignsAndUnnests,
+ Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs, IOptimizationContext context,
+ IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
if (funcIdent == AlgebricksBuiltinFunctions.AND) {
return false;
@@ -380,7 +390,8 @@
}
// Analyzes the funcExpr's arguments to see if the accessMethod is
// truly applicable.
- boolean matchFound = accessMethod.analyzeFuncExprArgs(funcExpr, assignsAndUnnests, analysisCtx);
+ boolean matchFound = accessMethod.analyzeFuncExprArgs(funcExpr, assignsAndUnnests, analysisCtx, context,
+ typeEnvironment);
if (matchFound) {
// If we've used the current new context placeholder, replace it
// with a new one.
@@ -398,7 +409,7 @@
* Finds secondary indexes whose keys include fieldName, and adds a mapping
* in analysisCtx.indexEsprs from that index to the a corresponding
* optimizable function expression.
- *
+ *
* @return true if a candidate index was added to foundIndexExprs, false
* otherwise
* @throws AlgebricksException
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java
index 7f713f8..831b3f7 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java
@@ -21,10 +21,9 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
-
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
+import java.util.Set;
import org.apache.asterix.algebra.operators.physical.ExternalDataLookupPOperator;
import org.apache.asterix.aql.util.FunctionUtils;
@@ -47,6 +46,8 @@
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
import org.apache.asterix.om.util.NonTaggedFormatUtil;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
@@ -57,7 +58,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.expressions.ConstantExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.IAlgebricksConstantValue;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
@@ -122,32 +123,47 @@
}
public static boolean analyzeFuncExprArgsForOneConstAndVar(AbstractFunctionCallExpression funcExpr,
- AccessMethodAnalysisContext analysisCtx) {
- IAlgebricksConstantValue constFilterVal = null;
+ AccessMethodAnalysisContext analysisCtx, IOptimizationContext context,
+ IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
+ ILogicalExpression constExpression = null;
+ IAType constantExpressionType = null;
LogicalVariable fieldVar = null;
ILogicalExpression arg1 = funcExpr.getArguments().get(0).getValue();
ILogicalExpression arg2 = funcExpr.getArguments().get(1).getValue();
- // One of the args must be a constant, and the other arg must be a variable.
- if (arg1.getExpressionTag() == LogicalExpressionTag.CONSTANT
+ // One of the args must be a runtime constant, and the other arg must be a variable.
+ if (arg1.getExpressionTag() == LogicalExpressionTag.VARIABLE
&& arg2.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
+ return false;
+ }
+ if (arg2.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
// The arguments of contains() function are asymmetrical, we can only use index if it is on the first argument
if (funcExpr.getFunctionIdentifier() == AsterixBuiltinFunctions.CONTAINS) {
return false;
}
- ConstantExpression constExpr = (ConstantExpression) arg1;
- constFilterVal = constExpr.getValue();
+ IAType expressionType = constantRuntimeResultType(arg1, context, typeEnvironment);
+ if (expressionType == null) {
+ //Not constant at runtime
+ return false;
+ }
+ constantExpressionType = expressionType;
+ constExpression = arg1;
VariableReferenceExpression varExpr = (VariableReferenceExpression) arg2;
fieldVar = varExpr.getVariableReference();
- } else if (arg1.getExpressionTag() == LogicalExpressionTag.VARIABLE
- && arg2.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
- ConstantExpression constExpr = (ConstantExpression) arg2;
- constFilterVal = constExpr.getValue();
+ } else if (arg1.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
+ IAType expressionType = constantRuntimeResultType(arg2, context, typeEnvironment);
+ if (expressionType == null) {
+ //Not constant at runtime
+ return false;
+ }
+ constantExpressionType = expressionType;
+ constExpression = arg2;
VariableReferenceExpression varExpr = (VariableReferenceExpression) arg1;
fieldVar = varExpr.getVariableReference();
} else {
return false;
}
- OptimizableFuncExpr newOptFuncExpr = new OptimizableFuncExpr(funcExpr, fieldVar, constFilterVal);
+ OptimizableFuncExpr newOptFuncExpr = new OptimizableFuncExpr(funcExpr, fieldVar, constExpression,
+ constantExpressionType);
for (IOptimizableFuncExpr optFuncExpr : analysisCtx.matchedFuncExprs) {
//avoid additional optFuncExpressions in case of a join
if (optFuncExpr.getFuncExpr().equals(funcExpr))
@@ -171,7 +187,7 @@
return false;
}
OptimizableFuncExpr newOptFuncExpr = new OptimizableFuncExpr(funcExpr, new LogicalVariable[] { fieldVar1,
- fieldVar2 }, null);
+ fieldVar2 }, new ILogicalExpression[0], new IAType[0]);
for (IOptimizableFuncExpr optFuncExpr : analysisCtx.matchedFuncExprs) {
//avoid additional optFuncExpressions in case of a join
if (optFuncExpr.getFuncExpr().equals(funcExpr))
@@ -308,7 +324,7 @@
* Returns the search key expression which feeds a secondary-index search. If we are optimizing a selection query then this method returns
* the a ConstantExpression from the first constant value in the optimizable function expression.
* If we are optimizing a join, then this method returns the VariableReferenceExpression that should feed the secondary index probe.
- *
+ *
* @throws AlgebricksException
*/
public static Pair<ILogicalExpression, Boolean> createSearchKeyExpr(IOptimizableFuncExpr optFuncExpr,
@@ -318,8 +334,19 @@
// We are optimizing a selection query. Search key is a constant.
// Type Checking and type promotion is done here
IAType fieldType = optFuncExpr.getFieldType(0);
- IAObject constantObj = ((AsterixConstantValue) optFuncExpr.getConstantVal(0)).getObject();
- ATypeTag constantValueTag = constantObj.getType().getTypeTag();
+
+ ILogicalExpression constantAtRuntimeExpression = null;
+ AsterixConstantValue constantValue = null;
+ ATypeTag constantValueTag = null;
+
+ constantAtRuntimeExpression = optFuncExpr.getConstantAtRuntimeExpr(0);
+
+ if (constantAtRuntimeExpression.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
+ constantValue = (AsterixConstantValue) ((ConstantExpression) constantAtRuntimeExpression).getValue();
+ }
+
+ constantValueTag = optFuncExpr.getConstantType(0).getTypeTag();
+
// type casting applied?
boolean typeCastingApplied = false;
// type casting happened from real (FLOAT, DOUBLE) value -> INT value?
@@ -327,9 +354,9 @@
AsterixConstantValue replacedConstantValue = null;
// if the constant type and target type does not match, we do a type conversion
- if (constantValueTag != fieldType.getTypeTag()) {
- replacedConstantValue = ATypeHierarchy.getAsterixConstantValueFromNumericTypeObject(constantObj,
- fieldType.getTypeTag());
+ if (constantValueTag != fieldType.getTypeTag() && constantValue != null) {
+ replacedConstantValue = ATypeHierarchy.getAsterixConstantValueFromNumericTypeObject(
+ constantValue.getObject(), fieldType.getTypeTag());
if (replacedConstantValue != null) {
typeCastingApplied = true;
}
@@ -358,8 +385,7 @@
return new Pair<ILogicalExpression, Boolean>(new ConstantExpression(replacedConstantValue),
realTypeConvertedToIntegerType);
} else {
- return new Pair<ILogicalExpression, Boolean>(new ConstantExpression(optFuncExpr.getConstantVal(0)),
- false);
+ return new Pair<ILogicalExpression, Boolean>(optFuncExpr.getConstantAtRuntimeExpr(0), false);
}
} else {
// We are optimizing a join query. Determine which variable feeds the secondary index.
@@ -610,4 +636,16 @@
secondaryIndex, primaryKeyVars, false, retainInput, retainNull));
return externalLookupOp;
}
+
+ //If the expression is constant at runtime, runturn the type
+ public static IAType constantRuntimeResultType(ILogicalExpression expr, IOptimizationContext context,
+ IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
+ Set<LogicalVariable> usedVariables = new HashSet<LogicalVariable>();
+ expr.getUsedVariables(usedVariables);
+ if (usedVariables.size() > 0) {
+ return null;
+ }
+ return (IAType) context.getExpressionTypeComputer().getType(expr, context.getMetadataProvider(),
+ typeEnvironment);
+ }
}
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java
index 7b76fa4..de28e4a 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java
@@ -28,9 +28,6 @@
import java.util.List;
import java.util.Set;
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-
import org.apache.asterix.aql.util.FunctionUtils;
import org.apache.asterix.common.annotations.SkipSecondaryIndexSearchExpressionAnnotation;
import org.apache.asterix.common.config.DatasetConfig.DatasetType;
@@ -39,6 +36,8 @@
import org.apache.asterix.metadata.entities.Index;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.optimizer.rules.util.EquivalenceClassUtils;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
@@ -47,6 +46,7 @@
import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
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.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.expressions.IndexedNLJoinExpressionAnnotation;
import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
@@ -96,8 +96,10 @@
@Override
public boolean analyzeFuncExprArgs(AbstractFunctionCallExpression funcExpr,
- List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx) {
- boolean matches = AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx);
+ List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx,
+ IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
+ boolean matches = AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx, context,
+ typeEnvironment);
if (!matches) {
matches = AccessMethodUtils.analyzeFuncExprArgsForTwoVars(funcExpr, analysisCtx);
}
@@ -234,6 +236,8 @@
LimitType[] highKeyLimits = new LimitType[numSecondaryKeys];
boolean[] lowKeyInclusive = new boolean[numSecondaryKeys];
boolean[] highKeyInclusive = new boolean[numSecondaryKeys];
+ ILogicalExpression[] constantAtRuntimeExpressions = new ILogicalExpression[numSecondaryKeys];
+ LogicalVariable[] constAtRuntimeExprVars = new LogicalVariable[numSecondaryKeys];
// TODO: For now we don't do any sophisticated analysis of the func exprs to come up with "the best" range predicate.
// If we can't figure out how to integrate a certain funcExpr into the current predicate, we just bail by setting this flag.
@@ -267,6 +271,12 @@
Pair<ILogicalExpression, Boolean> returnedSearchKeyExpr = AccessMethodUtils.createSearchKeyExpr(
optFuncExpr, indexSubTree, probeSubTree);
ILogicalExpression searchKeyExpr = returnedSearchKeyExpr.first;
+ if (searchKeyExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
+ constantAtRuntimeExpressions[keyPos] = searchKeyExpr;
+ constAtRuntimeExprVars[keyPos] = context.newVar();
+ searchKeyExpr = new VariableReferenceExpression(constAtRuntimeExprVars[keyPos]);
+
+ }
realTypeConvertedToIntegerType = returnedSearchKeyExpr.second;
LimitType limit = getLimitType(optFuncExpr, probeSubTree);
@@ -446,9 +456,9 @@
ArrayList<LogicalVariable> assignKeyVarList = new ArrayList<LogicalVariable>();
ArrayList<Mutable<ILogicalExpression>> assignKeyExprList = new ArrayList<Mutable<ILogicalExpression>>();
int numLowKeys = createKeyVarsAndExprs(numSecondaryKeys, lowKeyLimits, lowKeyExprs, assignKeyVarList,
- assignKeyExprList, keyVarList, context);
+ assignKeyExprList, keyVarList, context, constantAtRuntimeExpressions, constAtRuntimeExprVars);
int numHighKeys = createKeyVarsAndExprs(numSecondaryKeys, highKeyLimits, highKeyExprs, assignKeyVarList,
- assignKeyExprList, keyVarList, context);
+ assignKeyExprList, keyVarList, context, constantAtRuntimeExpressions, constAtRuntimeExprVars);
BTreeJobGenParams jobGenParams = new BTreeJobGenParams(chosenIndex.getIndexName(), IndexType.BTREE,
dataset.getDataverseName(), dataset.getDatasetName(), retainInput, retainNull, requiresBroadcast);
@@ -526,12 +536,14 @@
private int createKeyVarsAndExprs(int numKeys, LimitType[] keyLimits, ILogicalExpression[] searchKeyExprs,
ArrayList<LogicalVariable> assignKeyVarList, ArrayList<Mutable<ILogicalExpression>> assignKeyExprList,
- ArrayList<LogicalVariable> keyVarList, IOptimizationContext context) {
+ ArrayList<LogicalVariable> keyVarList, IOptimizationContext context, ILogicalExpression[] constExpressions,
+ LogicalVariable[] constExprVars) {
if (keyLimits[0] == null) {
return 0;
}
for (int i = 0; i < numKeys; i++) {
ILogicalExpression searchKeyExpr = searchKeyExprs[i];
+ ILogicalExpression constExpression = constExpressions[i];
LogicalVariable keyVar = null;
if (searchKeyExpr.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
keyVar = context.newVar();
@@ -539,6 +551,10 @@
assignKeyVarList.add(keyVar);
} else {
keyVar = ((VariableReferenceExpression) searchKeyExpr).getVariableReference();
+ if (constExpression != null) {
+ assignKeyExprList.add(new MutableObject<ILogicalExpression>(constExpression));
+ assignKeyVarList.add(constExprVars[i]);
+ }
}
keyVarList.add(keyVar);
}
@@ -630,7 +646,7 @@
private boolean probeIsOnLhs(IOptimizableFuncExpr optFuncExpr, OptimizableOperatorSubTree probeSubTree) {
if (probeSubTree == 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.getConstantVal(0);
+ return optFuncExpr.getFuncExpr().getArguments().get(0) == optFuncExpr.getConstantAtRuntimeExpr(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);
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java
index 50d39aa..432d933 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java
@@ -20,13 +20,13 @@
import java.util.List;
-import org.apache.commons.lang3.mutable.Mutable;
-
import org.apache.asterix.metadata.entities.Index;
+import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+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;
@@ -51,17 +51,19 @@
* optimizable by this access method based on its function identifier. If
* funcExpr has been found to be optimizable, this method adds an
* OptimizableFunction to analysisCtx.matchedFuncExprs for further analysis.
- *
+ *
* @return true if funcExpr is optimizable by this access method, false
* otherwise
+ * @throws AlgebricksException
*/
- public boolean analyzeFuncExprArgs(AbstractFunctionCallExpression funcExpr,
- List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx);
+ boolean analyzeFuncExprArgs(AbstractFunctionCallExpression funcExpr,
+ List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx,
+ IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException;
/**
* Indicates whether all index expressions must be matched in order for this
* index to be applicable.
- *
+ *
* @return boolean
*/
public boolean matchAllIndexExprs();
@@ -69,7 +71,7 @@
/**
* Indicates whether this index is applicable if only a prefix of the index
* expressions are matched.
- *
+ *
* @return boolean
*/
public boolean matchPrefixIndexExprs();
@@ -97,4 +99,5 @@
* @throws AlgebricksException
*/
public boolean exprIsOptimizable(Index index, IOptimizableFuncExpr optFuncExpr) throws AlgebricksException;
+
}
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java
index 85f8545..b4f8c9f 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java
@@ -24,7 +24,6 @@
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
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.expressions.IAlgebricksConstantValue;
/**
* Describes a function expression that is optimizable by an access method.
@@ -36,7 +35,7 @@
public int getNumLogicalVars();
- public int getNumConstantVals();
+ public int getNumConstantAtRuntimeExpr();
public LogicalVariable getLogicalVar(int index);
@@ -56,7 +55,7 @@
public OptimizableOperatorSubTree getOperatorSubTree(int index);
- public IAlgebricksConstantValue getConstantVal(int index);
+ public ILogicalExpression getConstantAtRuntimeExpr(int index);
public int findLogicalVar(LogicalVariable var);
@@ -71,4 +70,10 @@
public void setSourceVar(int index, LogicalVariable var);
public LogicalVariable getSourceVar(int index);
+
+ void setConstType(int index, IAType fieldType);
+
+ IAType getConstantType(int index);
+
+ void setConstantAtRuntimeExpr(int index, ILogicalExpression expr);
}
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
index 67b60df..4c150c0 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
@@ -34,6 +34,7 @@
import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
@@ -79,6 +80,7 @@
protected AbstractFunctionCallExpression joinCond = null;
protected final OptimizableOperatorSubTree leftSubTree = new OptimizableOperatorSubTree();
protected final OptimizableOperatorSubTree rightSubTree = new OptimizableOperatorSubTree();
+ protected IVariableTypeEnvironment typeEnvironment = null;
protected boolean isLeftOuterJoin = false;
protected boolean hasGroupBy = true;
@@ -105,10 +107,12 @@
boolean matchInLeftSubTree = false;
boolean matchInRightSubTree = false;
if (leftSubTree.hasDataSource()) {
- matchInLeftSubTree = analyzeCondition(joinCond, leftSubTree.assignsAndUnnests, analyzedAMs);
+ matchInLeftSubTree = analyzeCondition(joinCond, leftSubTree.assignsAndUnnests, analyzedAMs, context,
+ typeEnvironment);
}
if (rightSubTree.hasDataSource()) {
- matchInRightSubTree = analyzeCondition(joinCond, rightSubTree.assignsAndUnnests, analyzedAMs);
+ matchInRightSubTree = analyzeCondition(joinCond, rightSubTree.assignsAndUnnests, analyzedAMs, context,
+ typeEnvironment);
}
if (!matchInLeftSubTree && !matchInRightSubTree) {
return false;
@@ -133,7 +137,7 @@
if (checkRightSubTreeMetadata) {
fillSubTreeIndexExprs(rightSubTree, analyzedAMs, context);
}
- pruneIndexCandidates(analyzedAMs);
+ pruneIndexCandidates(analyzedAMs, context, typeEnvironment);
// Prioritize the order of index that will be applied. If the right subtree (inner branch) has indexes,
// those indexes will be used.
@@ -229,6 +233,7 @@
join = (LeftOuterJoinOperator) joinRef.getValue();
}
+ typeEnvironment = context.getOutputTypeEnvironment(join);
// Check that the select's condition is a function call.
ILogicalExpression condExpr = join.getCondition().getValue();
if (condExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java
index f337bbd..f374b9a 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java
@@ -22,9 +22,6 @@
import java.util.Arrays;
import java.util.List;
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-
import org.apache.asterix.common.config.DatasetConfig.DatasetType;
import org.apache.asterix.metadata.declared.AqlDataSource;
import org.apache.asterix.metadata.declared.AqlMetadataProvider;
@@ -39,6 +36,8 @@
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.ATypeTag;
import org.apache.asterix.om.types.IAType;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
@@ -50,6 +49,7 @@
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
import org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
import org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions.ComparisonKind;
@@ -64,6 +64,8 @@
public class IntroduceLSMComponentFilterRule implements IAlgebraicRewriteRule {
+ protected IVariableTypeEnvironment typeEnvironment = null;
+
@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
return false;
@@ -78,8 +80,9 @@
}
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
+ typeEnvironment = context.getOutputTypeEnvironment(op);
ILogicalExpression condExpr = ((SelectOperator) op).getCondition().getValue();
- AccessMethodAnalysisContext analysisCtx = analyzeCondition(condExpr);
+ AccessMethodAnalysisContext analysisCtx = analyzeCondition(condExpr, context, typeEnvironment);
if (analysisCtx.matchedFuncExprs.isEmpty()) {
return false;
}
@@ -128,7 +131,7 @@
for (IOptimizableFuncExpr optFuncExpr : optFuncExprs) {
ComparisonKind ck = AlgebricksBuiltinFunctions.getComparisonType(optFuncExpr.getFuncExpr()
.getFunctionIdentifier());
- ILogicalExpression searchKeyExpr = new ConstantExpression(optFuncExpr.getConstantVal(0));
+ ILogicalExpression searchKeyExpr = optFuncExpr.getConstantAtRuntimeExpr(0);
LogicalVariable var = context.newVar();
assignKeyExprList.add(new MutableObject<ILogicalExpression>(searchKeyExpr));
assignKeyVarList.add(var);
@@ -260,29 +263,31 @@
return true;
}
- private AccessMethodAnalysisContext analyzeCondition(ILogicalExpression cond) {
+ private AccessMethodAnalysisContext analyzeCondition(ILogicalExpression cond, IOptimizationContext context,
+ IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
AccessMethodAnalysisContext analysisCtx = new AccessMethodAnalysisContext();
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) cond;
FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
if (funcIdent != AlgebricksBuiltinFunctions.OR) {
- analyzeFunctionExpr(funcExpr, analysisCtx);
+ analyzeFunctionExpr(funcExpr, analysisCtx, context, typeEnvironment);
for (Mutable<ILogicalExpression> arg : funcExpr.getArguments()) {
ILogicalExpression argExpr = arg.getValue();
if (argExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
continue;
}
- analyzeFunctionExpr((AbstractFunctionCallExpression) argExpr, analysisCtx);
+ analyzeFunctionExpr((AbstractFunctionCallExpression) argExpr, analysisCtx, context, typeEnvironment);
}
}
return analysisCtx;
}
- private void analyzeFunctionExpr(AbstractFunctionCallExpression funcExpr, AccessMethodAnalysisContext analysisCtx) {
+ private void analyzeFunctionExpr(AbstractFunctionCallExpression funcExpr, AccessMethodAnalysisContext analysisCtx,
+ IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
if (funcIdent == AlgebricksBuiltinFunctions.LE || funcIdent == AlgebricksBuiltinFunctions.GE
|| funcIdent == AlgebricksBuiltinFunctions.LT || funcIdent == AlgebricksBuiltinFunctions.GT
|| funcIdent == AlgebricksBuiltinFunctions.EQ) {
- AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx);
+ AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx, context, typeEnvironment);
}
}
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
index 9084caf..7414c93 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
@@ -22,10 +22,9 @@
import java.util.List;
import java.util.Map;
-import org.apache.commons.lang3.mutable.Mutable;
-
import org.apache.asterix.metadata.declared.AqlMetadataProvider;
import org.apache.asterix.metadata.entities.Index;
+import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
@@ -34,6 +33,7 @@
import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+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.algebricks.core.algebra.operators.logical.SelectOperator;
@@ -70,6 +70,7 @@
protected Mutable<ILogicalOperator> selectRef = null;
protected SelectOperator select = null;
protected AbstractFunctionCallExpression selectCond = null;
+ protected IVariableTypeEnvironment typeEnvironment = null;
protected final OptimizableOperatorSubTree subTree = new OptimizableOperatorSubTree();
// Register access methods.
@@ -93,7 +94,7 @@
// Analyze select condition.
Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs = new HashMap<IAccessMethod, AccessMethodAnalysisContext>();
- if (!analyzeCondition(selectCond, subTree.assignsAndUnnests, analyzedAMs)) {
+ if (!analyzeCondition(selectCond, subTree.assignsAndUnnests, analyzedAMs, context, typeEnvironment)) {
return false;
}
@@ -103,7 +104,7 @@
}
fillSubTreeIndexExprs(subTree, analyzedAMs, context);
- pruneIndexCandidates(analyzedAMs);
+ pruneIndexCandidates(analyzedAMs, context, typeEnvironment);
// Choose index to be applied.
Pair<IAccessMethod, Index> chosenIndex = chooseIndex(analyzedAMs);
@@ -135,6 +136,8 @@
// Set and analyze select.
selectRef = opRef;
select = (SelectOperator) op1;
+
+ typeEnvironment = context.getOutputTypeEnvironment(op1);
// Check that the select's condition is a function call.
ILogicalExpression condExpr = select.getCondition().getValue();
if (condExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
index efe506f..ca70189 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
@@ -24,14 +24,12 @@
import java.util.List;
import java.util.Map;
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-
import org.apache.asterix.algebra.base.LogicalOperatorDeepCopyVisitor;
import org.apache.asterix.aql.util.FunctionUtils;
import org.apache.asterix.common.annotations.SkipSecondaryIndexSearchExpressionAnnotation;
import org.apache.asterix.common.config.DatasetConfig.IndexType;
import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.dataflow.data.common.AqlExpressionTypeComputer;
import org.apache.asterix.formats.nontagged.AqlBinaryTokenizerFactoryProvider;
import org.apache.asterix.metadata.entities.Dataset;
import org.apache.asterix.metadata.entities.Index;
@@ -47,6 +45,8 @@
import org.apache.asterix.om.types.ATypeTag;
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.types.hierachy.ATypeHierarchy;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Triple;
import org.apache.hyracks.algebricks.core.algebra.base.Counter;
@@ -58,7 +58,6 @@
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.expressions.ConstantExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.IAlgebricksConstantValue;
import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
@@ -125,10 +124,12 @@
@Override
public boolean analyzeFuncExprArgs(AbstractFunctionCallExpression funcExpr,
- List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx) {
+ List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx,
+ IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
if (funcExpr.getFunctionIdentifier() == AsterixBuiltinFunctions.CONTAINS) {
- boolean matches = AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx);
+ boolean matches = AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx, context,
+ typeEnvironment);
if (!matches) {
matches = AccessMethodUtils.analyzeFuncExprArgsForTwoVars(funcExpr, analysisCtx);
}
@@ -138,7 +139,8 @@
}
public boolean analyzeGetItemFuncExpr(AbstractFunctionCallExpression funcExpr,
- List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx) {
+ List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx)
+ throws AlgebricksException {
if (funcExpr.getFunctionIdentifier() != AsterixBuiltinFunctions.GET_ITEM) {
return false;
}
@@ -222,15 +224,13 @@
private boolean analyzeJoinSimilarityCheckFuncExprArgs(AbstractFunctionCallExpression funcExpr,
List<AbstractLogicalOperator> assignsAndUnnests, int matchedAssignOrUnnestIndex,
- AccessMethodAnalysisContext analysisCtx) {
+ AccessMethodAnalysisContext analysisCtx) throws AlgebricksException {
// There should be exactly three arguments.
// The last function argument is assumed to be the similarity threshold.
- IAlgebricksConstantValue constThreshVal = null;
ILogicalExpression arg3 = funcExpr.getArguments().get(2).getValue();
if (arg3.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
return false;
}
- constThreshVal = ((ConstantExpression) arg3).getValue();
ILogicalExpression arg1 = funcExpr.getArguments().get(0).getValue();
ILogicalExpression arg2 = funcExpr.getArguments().get(1).getValue();
// We expect arg1 and arg2 to be non-constants for a join.
@@ -249,7 +249,8 @@
return false;
}
OptimizableFuncExpr newOptFuncExpr = new OptimizableFuncExpr(funcExpr, new LogicalVariable[] { fieldVarExpr1,
- fieldVarExpr2 }, new IAlgebricksConstantValue[] { constThreshVal });
+ fieldVarExpr2 }, new ILogicalExpression[] { arg3 },
+ new IAType[] { (IAType) AqlExpressionTypeComputer.INSTANCE.getType(arg3, null, null) });
for (IOptimizableFuncExpr optFuncExpr : analysisCtx.matchedFuncExprs) {
//avoid additional optFuncExpressions in case of a join
if (optFuncExpr.getFuncExpr().equals(funcExpr)) {
@@ -262,15 +263,13 @@
private boolean analyzeSelectSimilarityCheckFuncExprArgs(AbstractFunctionCallExpression funcExpr,
List<AbstractLogicalOperator> assignsAndUnnests, int matchedAssignOrUnnestIndex,
- AccessMethodAnalysisContext analysisCtx) {
+ AccessMethodAnalysisContext analysisCtx) throws AlgebricksException {
// There should be exactly three arguments.
// The last function argument is assumed to be the similarity threshold.
- IAlgebricksConstantValue constThreshVal = null;
ILogicalExpression arg3 = funcExpr.getArguments().get(2).getValue();
if (arg3.getExpressionTag() != LogicalExpressionTag.CONSTANT) {
return false;
}
- constThreshVal = ((ConstantExpression) arg3).getValue();
ILogicalExpression arg1 = funcExpr.getArguments().get(0).getValue();
ILogicalExpression arg2 = funcExpr.getArguments().get(1).getValue();
// Determine whether one arg is constant, and the other is non-constant.
@@ -291,15 +290,16 @@
} else {
return false;
}
- ConstantExpression constExpr = (ConstantExpression) constArg;
- IAlgebricksConstantValue constFilterVal = constExpr.getValue();
LogicalVariable fieldVarExpr = getNonConstArgFieldExprPair(nonConstArg, funcExpr, assignsAndUnnests,
matchedAssignOrUnnestIndex);
if (fieldVarExpr == null) {
return false;
}
+
OptimizableFuncExpr newOptFuncExpr = new OptimizableFuncExpr(funcExpr, new LogicalVariable[] { fieldVarExpr },
- new IAlgebricksConstantValue[] { constFilterVal, constThreshVal });
+ new ILogicalExpression[] { constArg, arg3 }, new IAType[] {
+ (IAType) AqlExpressionTypeComputer.INSTANCE.getType(constArg, null, null),
+ (IAType) AqlExpressionTypeComputer.INSTANCE.getType(arg3, null, null) });
for (IOptimizableFuncExpr optFuncExpr : analysisCtx.matchedFuncExprs) {
//avoid additional optFuncExpressions in case of a join
if (optFuncExpr.getFuncExpr().equals(funcExpr))
@@ -731,8 +731,7 @@
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>(new ConstantExpression(optFuncExpr
- .getConstantVal(0))));
+ isFilterableArgs.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantAtRuntimeExpr(0)));
isFilterableArgs.add(new MutableObject<ILogicalExpression>(AccessMethodUtils
.createInt32Constant(chosenIndex.getGramLength())));
boolean usePrePost = optFuncExpr.containsPartialField() ? false : true;
@@ -749,8 +748,7 @@
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>(new ConstantExpression(optFuncExpr
- .getConstantVal(0))));
+ isFilterableArgs.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantAtRuntimeExpr(0)));
isFilterableExpr = new ScalarFunctionCallExpression(
FunctionUtils.getFunctionInfo(AsterixBuiltinFunctions.EDIT_DISTANCE_LIST_IS_FILTERABLE),
isFilterableArgs);
@@ -799,9 +797,7 @@
typeTag = type.getTypeTag();
} else {
// We are optimizing a selection query. Add the type of the search key constant.
- AsterixConstantValue constVal = (AsterixConstantValue) optFuncExpr.getConstantVal(0);
- IAObject obj = constVal.getObject();
- type = obj.getType();
+ type = optFuncExpr.getConstantType(0);
typeTag = type.getTypeTag();
if (typeTag != ATypeTag.ORDEREDLIST && typeTag != ATypeTag.STRING && typeTag != ATypeTag.UNORDEREDLIST) {
throw new AlgebricksException("Only ordered lists, string, and unordered lists types supported.");
@@ -818,7 +814,8 @@
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(optFuncExpr.getConstantVal(optFuncExpr.getNumConstantVals() - 1));
+ jobGenParams.setSimilarityThreshold(((ConstantExpression) optFuncExpr.getConstantAtRuntimeExpr(optFuncExpr
+ .getNumConstantAtRuntimeExpr() - 1)).getValue());
}
if (optFuncExpr.getFuncExpr().getFunctionIdentifier() == AsterixBuiltinFunctions.EDIT_DISTANCE_CHECK
|| optFuncExpr.getFuncExpr().getFunctionIdentifier() == AsterixBuiltinFunctions.EDIT_DISTANCE_CONTAINS) {
@@ -828,7 +825,8 @@
jobGenParams.setSearchModifierType(SearchModifierType.EDIT_DISTANCE);
}
// Add the similarity threshold which, by convention, is the last constant value.
- jobGenParams.setSimilarityThreshold(optFuncExpr.getConstantVal(optFuncExpr.getNumConstantVals() - 1));
+ jobGenParams.setSimilarityThreshold(((ConstantExpression) optFuncExpr.getConstantAtRuntimeExpr(optFuncExpr
+ .getNumConstantAtRuntimeExpr() - 1)).getValue());
}
}
@@ -839,7 +837,7 @@
// 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>(new ConstantExpression(optFuncExpr.getConstantVal(0))));
+ keyExprList.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantAtRuntimeExpr(0)));
return;
}
@@ -868,7 +866,7 @@
private boolean isEditDistanceFuncOptimizable(Index index, IOptimizableFuncExpr optFuncExpr)
throws AlgebricksException {
- if (optFuncExpr.getNumConstantVals() == 1) {
+ if (optFuncExpr.getNumConstantAtRuntimeExpr() == 1) {
return isEditDistanceFuncJoinOptimizable(index, optFuncExpr);
} else {
return isEditDistanceFuncSelectOptimizable(index, optFuncExpr);
@@ -901,7 +899,8 @@
// Check for panic in selection query.
// TODO: Panic also depends on prePost which is currently hardcoded to be true.
- AsterixConstantValue listOrStrConstVal = (AsterixConstantValue) optFuncExpr.getConstantVal(0);
+ AsterixConstantValue listOrStrConstVal = (AsterixConstantValue) ((ConstantExpression) optFuncExpr
+ .getConstantAtRuntimeExpr(0)).getValue();
IAObject listOrStrObj = listOrStrConstVal.getObject();
ATypeTag typeTag = listOrStrObj.getType().getTypeTag();
@@ -909,7 +908,8 @@
return false;
}
- AsterixConstantValue intConstVal = (AsterixConstantValue) optFuncExpr.getConstantVal(1);
+ AsterixConstantValue intConstVal = (AsterixConstantValue) ((ConstantExpression) optFuncExpr.getConstantAtRuntimeExpr(1))
+ .getValue();
IAObject intObj = intConstVal.getObject();
AInt32 edThresh = null;
@@ -1055,7 +1055,8 @@
}
private boolean isContainsFuncSelectOptimizable(Index index, IOptimizableFuncExpr optFuncExpr) {
- AsterixConstantValue strConstVal = (AsterixConstantValue) optFuncExpr.getConstantVal(0);
+ AsterixConstantValue strConstVal = (AsterixConstantValue) ((ConstantExpression) optFuncExpr.getConstantAtRuntimeExpr(0))
+ .getValue();
IAObject strObj = strConstVal.getObject();
ATypeTag typeTag = strObj.getType().getTypeTag();
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java
index f58cf2d..2ecd504 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java
@@ -26,7 +26,6 @@
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
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.expressions.IAlgebricksConstantValue;
/**
* General-purpose implementation of IOptimizableFuncExpr that supports any
@@ -40,16 +39,18 @@
protected final List<List<String>> fieldNames;
protected final IAType[] fieldTypes;
protected final OptimizableOperatorSubTree[] subTrees;
- protected final IAlgebricksConstantValue[] constantVals;
+ protected final ILogicalExpression[] constantAtRuntimeExpressions;
+ protected final IAType[] constantAtRuntimeExpressionTypes;
protected boolean partialField;
public OptimizableFuncExpr(AbstractFunctionCallExpression funcExpr, LogicalVariable[] logicalVars,
- IAlgebricksConstantValue[] constantVals) {
+ ILogicalExpression[] constantExpressions, IAType[] constantExpressionTypes) {
this.funcExpr = funcExpr;
this.logicalVars = logicalVars;
this.sourceVars = new LogicalVariable[logicalVars.length];
this.logicalExprs = new ILogicalExpression[logicalVars.length];
- this.constantVals = constantVals;
+ this.constantAtRuntimeExpressionTypes = constantExpressionTypes;
+ this.constantAtRuntimeExpressions = constantExpressions;
this.fieldNames = new ArrayList<List<String>>();
for (int i = 0; i < logicalVars.length; i++) {
fieldNames.add(new ArrayList<String>());
@@ -66,12 +67,13 @@
// Special, more convenient c'tor for simple binary functions.
public OptimizableFuncExpr(AbstractFunctionCallExpression funcExpr, LogicalVariable logicalVar,
- IAlgebricksConstantValue constantVal) {
+ ILogicalExpression constantExpression, IAType constantExpressionType) {
this.funcExpr = funcExpr;
this.logicalVars = new LogicalVariable[] { logicalVar };
this.sourceVars = new LogicalVariable[1];
this.logicalExprs = new ILogicalExpression[1];
- this.constantVals = new IAlgebricksConstantValue[] { constantVal };
+ this.constantAtRuntimeExpressions = new ILogicalExpression[] { constantExpression };
+ this.constantAtRuntimeExpressionTypes = new IAType[] { constantExpressionType };
this.fieldNames = new ArrayList<List<String>>();
for (int i = 0; i < logicalVars.length; i++) {
fieldNames.add(new ArrayList<String>());
@@ -96,8 +98,8 @@
}
@Override
- public int getNumConstantVals() {
- return constantVals.length;
+ public int getNumConstantAtRuntimeExpr() {
+ return constantAtRuntimeExpressions.length;
}
@Override
@@ -136,8 +138,23 @@
}
@Override
- public IAlgebricksConstantValue getConstantVal(int index) {
- return constantVals[index];
+ public ILogicalExpression getConstantAtRuntimeExpr(int index) {
+ return constantAtRuntimeExpressions[index];
+ }
+
+ @Override
+ public void setConstType(int index, IAType fieldType) {
+ constantAtRuntimeExpressionTypes[index] = fieldType;
+ }
+
+ @Override
+ public IAType getConstantType(int index) {
+ return constantAtRuntimeExpressionTypes[index];
+ }
+
+ @Override
+ public void setConstantAtRuntimeExpr(int index, ILogicalExpression expr) {
+ constantAtRuntimeExpressions[index] = expr;
}
@Override
diff --git a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java
index 24ba967..e9e55db 100644
--- a/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java
+++ b/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java
@@ -21,9 +21,6 @@
import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-
import org.apache.asterix.aql.util.FunctionUtils;
import org.apache.asterix.common.annotations.SkipSecondaryIndexSearchExpressionAnnotation;
import org.apache.asterix.common.config.DatasetConfig.DatasetType;
@@ -36,6 +33,8 @@
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.util.NonTaggedFormatUtil;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
@@ -44,6 +43,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.expressions.ConstantExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
@@ -74,8 +74,10 @@
@Override
public boolean analyzeFuncExprArgs(AbstractFunctionCallExpression funcExpr,
- List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx) {
- boolean matches = AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx);
+ List<AbstractLogicalOperator> assignsAndUnnests, AccessMethodAnalysisContext analysisCtx,
+ IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
+ boolean matches = AccessMethodUtils.analyzeFuncExprArgsForOneConstAndVar(funcExpr, analysisCtx, context,
+ typeEnvironment);
if (!matches) {
matches = AccessMethodUtils.analyzeFuncExprArgsForTwoVars(funcExpr, analysisCtx);
}
diff --git a/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-01.aql b/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-01.aql
new file mode 100644
index 0000000..7179d54
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-01.aql
@@ -0,0 +1,43 @@
+/*
+ * 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 : This test is intended to verify that the primary BTree index is used
+ * : for an invocation of current-datetime()
+ * Expected Result : Success
+ * Date : 27th Aug 2015
+ * Author : Steven Jacobs
+ */
+
+drop dataverse emergencyTest if exists;
+create dataverse emergencyTest;
+use dataverse emergencyTest;
+create type CHPReport as {
+ "id":int,
+ "timestamp":datetime,
+ "title":string,
+ "message":string
+}
+create dataset CHPReports(CHPReport)
+primary key timestamp;
+
+for $emergency in dataset CHPReports
+where $emergency.timestamp >= current-datetime() - day-time-duration("PT10H")
+and $emergency.title = "ghost"
+return $emergency.message;
+
diff --git a/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-02.aql b/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-02.aql
new file mode 100644
index 0000000..8a5fe07
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-02.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 : This test is intended to verify that the primary BTree index is used
+ * : for an invocation of current-datetime()
+ * Expected Result : Success
+ * Date : 27th Aug 2015
+ * Author : Steven Jacobs
+ */
+
+drop dataverse emergencyTest if exists;
+create dataverse emergencyTest;
+use dataverse emergencyTest;
+create type CHPReport as {
+ "id":int,
+ "timestamp":datetime,
+ "title":string,
+ "message":string
+}
+create dataset CHPReports(CHPReport)
+primary key timestamp;
+
+for $emergency in dataset CHPReports
+let $time := current-datetime() - day-time-duration("PT10H")
+where $emergency.timestamp >= $time
+return $emergency;
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-03.aql b/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-03.aql
new file mode 100644
index 0000000..f3b49ad
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-03.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 : This test is intended to verify that the primary BTree index is used
+ * : for an invocation of current-datetime()
+ * Expected Result : Success
+ * Date : 27th Aug 2015
+ * Author : Steven Jacobs
+ */
+
+drop dataverse emergencyTest if exists;
+create dataverse emergencyTest;
+use dataverse emergencyTest;
+create type CHPReport as {
+ "id":int,
+ "timestamp":datetime,
+ "title":string,
+ "message":string
+}
+create dataset CHPReports(CHPReport)
+primary key timestamp;
+
+for $emergency in dataset CHPReports
+where $emergency.timestamp >= current-datetime()
+return $emergency;
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-04.aql b/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-04.aql
new file mode 100644
index 0000000..59014bc
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-04.aql
@@ -0,0 +1,40 @@
+/*
+ * 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 : This test makes sure that the plan is still okay when not converted to index search
+ * Expected Result : Success
+ * Date : 27th Aug 2015
+ * Author : Steven Jacobs
+ */
+
+drop dataverse emergencyTest if exists;
+create dataverse emergencyTest;
+use dataverse emergencyTest;
+create type CHPReport as {
+ "id":int,
+ "timestamp":datetime,
+ "title":string,
+ "message":string
+}
+create dataset CHPReports(CHPReport)
+primary key id;
+
+for $emergency in dataset CHPReports
+where $emergency.timestamp >= current-datetime()
+return $emergency;
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-01.plan b/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-01.plan
new file mode 100644
index 0000000..9b5e82c
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-01.plan
@@ -0,0 +1,11 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-02.plan b/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-02.plan
new file mode 100644
index 0000000..a9e223a
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-02.plan
@@ -0,0 +1,8 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-03.plan b/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-03.plan
new file mode 100644
index 0000000..a9e223a
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-03.plan
@@ -0,0 +1,8 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-04.plan b/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-04.plan
new file mode 100644
index 0000000..ef7eae2
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-04.plan
@@ -0,0 +1,8 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |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