You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by sj...@apache.org on 2015/10/21 19:38:56 UTC

incubator-asterixdb git commit: Convert comparisons with current-datetime, current-date, and current-time to applicable index searches as though they were constants

Repository: incubator-asterixdb
Updated Branches:
  refs/heads/master a48f56b0c -> 5b79000c3


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 <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Yingyi Bu <bu...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/commit/5b79000c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/tree/5b79000c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/diff/5b79000c

Branch: refs/heads/master
Commit: 5b79000c3654ce1ef628aa20bd9be73e91346be0
Parents: a48f56b
Author: Steven Jacobs <sj...@ucr.edu>
Authored: Mon Oct 19 15:39:32 2015 -0700
Committer: Steven Jacobs <sj...@ucr.edu>
Committed: Wed Oct 21 10:35:53 2015 -0700

----------------------------------------------------------------------
 .../am/AbstractIntroduceAccessMethodRule.java   | 45 ++++++----
 .../optimizer/rules/am/AccessMethodUtils.java   | 86 ++++++++++++++------
 .../optimizer/rules/am/BTreeAccessMethod.java   | 34 ++++++--
 .../optimizer/rules/am/IAccessMethod.java       | 17 ++--
 .../rules/am/IOptimizableFuncExpr.java          | 11 ++-
 .../rules/am/IntroduceJoinAccessMethodRule.java | 11 ++-
 .../am/IntroduceLSMComponentFilterRule.java     | 25 +++---
 .../am/IntroduceSelectAccessMethodRule.java     | 11 ++-
 .../rules/am/InvertedIndexAccessMethod.java     | 63 +++++++-------
 .../optimizer/rules/am/OptimizableFuncExpr.java | 37 ++++++---
 .../optimizer/rules/am/RTreeAccessMethod.java   | 12 +--
 .../queries/btree-index/btree-datetime-01.aql   | 43 ++++++++++
 .../queries/btree-index/btree-datetime-02.aql   | 42 ++++++++++
 .../queries/btree-index/btree-datetime-03.aql   | 41 ++++++++++
 .../queries/btree-index/btree-datetime-04.aql   | 40 +++++++++
 .../results/btree-index/btree-datetime-01.plan  | 11 +++
 .../results/btree-index/btree-datetime-02.plan  |  8 ++
 .../results/btree-index/btree-datetime-03.plan  |  8 ++
 .../results/btree-index/btree-datetime-04.plan  |  8 ++
 19 files changed, 430 insertions(+), 123 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
----------------------------------------------------------------------
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.Iterator;
 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.BuiltinType;
 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 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
         }
     }
 
-    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 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
      * 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 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
                     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 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
      * 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 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
         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 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
      * 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 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
             }
             // 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 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
      * 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

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java
----------------------------------------------------------------------
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 @@ package org.apache.asterix.optimizer.rules.am;
 
 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.ATypeTag;
 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.LogicalOperatorTag;
 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 class AccessMethodUtils {
     }
 
     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 @@ public class AccessMethodUtils {
             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 @@ public class AccessMethodUtils {
      * 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 @@ public class AccessMethodUtils {
             // 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 @@ public class AccessMethodUtils {
             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 @@ public class AccessMethodUtils {
                 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 @@ public class AccessMethodUtils {
                 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);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/BTreeAccessMethod.java
----------------------------------------------------------------------
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.Iterator;
 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.Dataset;
 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.IOptimizationContext;
 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 @@ public class BTreeAccessMethod implements IAccessMethod {
 
     @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 @@ public class BTreeAccessMethod implements IAccessMethod {
         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 @@ public class BTreeAccessMethod implements IAccessMethod {
             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 @@ public class BTreeAccessMethod implements IAccessMethod {
         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 @@ public class BTreeAccessMethod implements IAccessMethod {
 
     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 @@ public class BTreeAccessMethod implements IAccessMethod {
                 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 @@ public class BTreeAccessMethod implements IAccessMethod {
     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);

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IAccessMethod.java
----------------------------------------------------------------------
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 @@ package org.apache.asterix.optimizer.rules.am;
 
 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 @@ public interface IAccessMethod {
      * 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 @@ public interface IAccessMethod {
     /**
      * 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 @@ public interface IAccessMethod {
      * @throws AlgebricksException
      */
     public boolean exprIsOptimizable(Index index, IOptimizableFuncExpr optFuncExpr) throws AlgebricksException;
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IOptimizableFuncExpr.java
----------------------------------------------------------------------
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.asterix.om.types.IAType;
 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 interface IOptimizableFuncExpr {
 
     public int getNumLogicalVars();
 
-    public int getNumConstantVals();
+    public int getNumConstantAtRuntimeExpr();
 
     public LogicalVariable getLogicalVar(int index);
 
@@ -56,7 +55,7 @@ public interface IOptimizableFuncExpr {
 
     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 interface IOptimizableFuncExpr {
     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);
 }

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
----------------------------------------------------------------------
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.IOptimizationContext;
 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 @@ public class IntroduceJoinAccessMethodRule extends AbstractIntroduceAccessMethod
     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 @@ public class IntroduceJoinAccessMethodRule extends AbstractIntroduceAccessMethod
         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 @@ public class IntroduceJoinAccessMethodRule extends AbstractIntroduceAccessMethod
         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 @@ public class IntroduceJoinAccessMethodRule extends AbstractIntroduceAccessMethod
             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) {

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceLSMComponentFilterRule.java
----------------------------------------------------------------------
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.ArrayList;
 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.functions.AsterixBuiltinFunctions;
 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.base.LogicalVariable;
 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 @@ import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 
 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 @@ public class IntroduceLSMComponentFilterRule implements IAlgebraicRewriteRule {
         }
 
         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 @@ public class IntroduceLSMComponentFilterRule implements IAlgebraicRewriteRule {
         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 @@ public class IntroduceLSMComponentFilterRule implements IAlgebraicRewriteRule {
         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);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
----------------------------------------------------------------------
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.HashMap;
 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.IOptimizationContext;
 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 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth
     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 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth
 
         // 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 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth
         }
 
         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 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth
         // 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) {

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
----------------------------------------------------------------------
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.HashSet;
 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.ARecordType;
 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.LogicalOperatorTag;
 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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
 
     @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 class InvertedIndexAccessMethod implements IAccessMethod {
     }
 
     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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
 
     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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
             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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
 
     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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
         } 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 @@ 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>(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 @@ 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>(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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
             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 @@ 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(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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
                 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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
         // 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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
 
     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 @@ 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) optFuncExpr.getConstantVal(0);
+        AsterixConstantValue listOrStrConstVal = (AsterixConstantValue) ((ConstantExpression) optFuncExpr
+                .getConstantAtRuntimeExpr(0)).getValue();
         IAObject listOrStrObj = listOrStrConstVal.getObject();
         ATypeTag typeTag = listOrStrObj.getType().getTypeTag();
 
@@ -909,7 +908,8 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
             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 @@ public class InvertedIndexAccessMethod implements IAccessMethod {
     }
 
     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();
 

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/OptimizableFuncExpr.java
----------------------------------------------------------------------
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.asterix.om.types.IAType;
 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 @@ public class OptimizableFuncExpr implements IOptimizableFuncExpr {
     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 @@ public class OptimizableFuncExpr implements IOptimizableFuncExpr {
 
     // 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 @@ public class OptimizableFuncExpr implements IOptimizableFuncExpr {
     }
 
     @Override
-    public int getNumConstantVals() {
-        return constantVals.length;
+    public int getNumConstantAtRuntimeExpr() {
+        return constantAtRuntimeExpressions.length;
     }
 
     @Override
@@ -136,8 +138,23 @@ public class OptimizableFuncExpr implements IOptimizableFuncExpr {
     }
 
     @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

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/RTreeAccessMethod.java
----------------------------------------------------------------------
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 @@ package org.apache.asterix.optimizer.rules.am;
 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.functions.AsterixBuiltinFunctions;
 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.IOptimizationContext;
 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 @@ public class RTreeAccessMethod implements IAccessMethod {
 
     @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);
         }

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-01.aql
----------------------------------------------------------------------
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;
+

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-02.aql
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-03.aql
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-app/src/test/resources/optimizerts/queries/btree-index/btree-datetime-04.aql
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-01.plan
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-02.plan
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-03.plan
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/5b79000c/asterix-app/src/test/resources/optimizerts/results/btree-index/btree-datetime-04.plan
----------------------------------------------------------------------
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