Reintegrated asterix_fix_issue_154. Fixes some fuzzy join tests, and adds a hint for indexed nl joins. Abandoning complete fix for issue 154 for now.

git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_stabilization@590 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/jobgen/AqlLogicalExpressionJobGen.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/jobgen/AqlLogicalExpressionJobGen.java
index 9717d6a..f515516 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/jobgen/AqlLogicalExpressionJobGen.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/jobgen/AqlLogicalExpressionJobGen.java
@@ -4,28 +4,22 @@
 
 import org.apache.commons.lang3.mutable.Mutable;
 
+import edu.uci.ics.asterix.common.functions.FunctionDescriptorTag;
 import edu.uci.ics.asterix.formats.base.IDataFormat;
 import edu.uci.ics.asterix.metadata.declared.AqlCompiledMetadataDeclarations;
 import edu.uci.ics.asterix.metadata.declared.AqlMetadataProvider;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
-import edu.uci.ics.asterix.runtime.base.IAggregateFunctionDynamicDescriptor;
-import edu.uci.ics.asterix.runtime.base.IRunningAggregateFunctionDynamicDescriptor;
-import edu.uci.ics.asterix.runtime.base.IScalarFunctionDynamicDescriptor;
-import edu.uci.ics.asterix.runtime.base.ISerializableAggregateFunctionDynamicDescriptor;
-import edu.uci.ics.asterix.runtime.base.IUnnestingFunctionDynamicDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.comparisons.ComparisonEvalFactory;
 import edu.uci.ics.asterix.runtime.formats.FormatUtils;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression.FunctionKind;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ILogicalExpressionJobGen;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.StatefulFunctionCallExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
@@ -53,79 +47,25 @@
             IVariableTypeEnvironment env, IOperatorSchema[] inputSchemas, JobGenContext context)
             throws AlgebricksException {
         ICopyEvaluatorFactory[] args = codegenArguments(expr, env, inputSchemas, context);
-        IFunctionDescriptor fd;
-        AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
-        AqlCompiledMetadataDeclarations compiledDecls = mp.getMetadataDeclarations();
-        try {
-            fd = compiledDecls.getFormat().resolveFunction(expr, env);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
-        }
+        IFunctionDescriptor fd = getFunctionDescriptor(expr, env, context);
         switch (fd.getFunctionDescriptorTag()) {
-            case SCALAR: {
-                throw new AlgebricksException(
-                        "Trying to create an aggregate from a scalar evaluator function descriptor. (fi="
-                                + expr.getFunctionIdentifier() + ")");
-            }
-            case AGGREGATE: {
-                IAggregateFunctionDynamicDescriptor afdd = (IAggregateFunctionDynamicDescriptor) fd;
-                return afdd.createAggregateFunctionFactory(args);
-            }
-            case SERIALAGGREGATE: {
-                // temporal hack
+            case SERIALAGGREGATE:
                 return null;
-            }
-            case RUNNINGAGGREGATE: {
-                throw new AlgebricksException(
-                        "Trying to create an aggregate from a running aggregate function descriptor.");
-            }
-            case UNNEST: {
-                throw new AlgebricksException(
-                        "Trying to create an aggregate from an unnesting aggregate function descriptor.");
-            }
-
-            default: {
-                throw new IllegalStateException(fd.getFunctionDescriptorTag().toString());
-            }
+            case AGGREGATE:
+                return fd.createAggregateFunctionFactory(args);
+            default:
+                throw new IllegalStateException("Invalid function descriptor " + fd.getFunctionDescriptorTag()
+                        + " expected " + FunctionDescriptorTag.SERIALAGGREGATE + " or "
+                        + FunctionDescriptorTag.AGGREGATE);
         }
-
     }
 
     @Override
-    public ICopyRunningAggregateFunctionFactory createRunningAggregateFunctionFactory(StatefulFunctionCallExpression expr,
-            IVariableTypeEnvironment env, IOperatorSchema[] inputSchemas, JobGenContext context)
-            throws AlgebricksException {
+    public ICopyRunningAggregateFunctionFactory createRunningAggregateFunctionFactory(
+            StatefulFunctionCallExpression expr, IVariableTypeEnvironment env, IOperatorSchema[] inputSchemas,
+            JobGenContext context) throws AlgebricksException {
         ICopyEvaluatorFactory[] args = codegenArguments(expr, env, inputSchemas, context);
-        IFunctionDescriptor fd;
-        AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
-        AqlCompiledMetadataDeclarations compiledDecls = mp.getMetadataDeclarations();
-        try {
-            fd = compiledDecls.getFormat().resolveFunction(expr, env);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
-        }
-        switch (fd.getFunctionDescriptorTag()) {
-            case SCALAR: {
-                throw new AlgebricksException(
-                        "Trying to create a running aggregate from a scalar evaluator function descriptor. (fi="
-                                + expr.getFunctionIdentifier() + ")");
-            }
-            case AGGREGATE: {
-                throw new AlgebricksException(
-                        "Trying to create a running aggregate from an aggregate function descriptor.");
-            }
-            case UNNEST: {
-                throw new AlgebricksException(
-                        "Trying to create a running aggregate from an unnesting function descriptor.");
-            }
-            case RUNNINGAGGREGATE: {
-                IRunningAggregateFunctionDynamicDescriptor rafdd = (IRunningAggregateFunctionDynamicDescriptor) fd;
-                return rafdd.createRunningAggregateFunctionFactory(args);
-            }
-            default: {
-                throw new IllegalStateException();
-            }
-        }
+        return getFunctionDescriptor(expr, env, context).createRunningAggregateFunctionFactory(args);
     }
 
     @Override
@@ -133,52 +73,33 @@
             IVariableTypeEnvironment env, IOperatorSchema[] inputSchemas, JobGenContext context)
             throws AlgebricksException {
         ICopyEvaluatorFactory[] args = codegenArguments(expr, env, inputSchemas, context);
-        IFunctionDescriptor fd;
-        AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
-        AqlCompiledMetadataDeclarations compiledDecls = mp.getMetadataDeclarations();
-        try {
-            fd = compiledDecls.getFormat().resolveFunction(expr, env);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
-        }
-        switch (fd.getFunctionDescriptorTag()) {
-            case UNNEST: {
-                IUnnestingFunctionDynamicDescriptor ufdd = (IUnnestingFunctionDynamicDescriptor) fd;
-                return ufdd.createUnnestingFunctionFactory(args);
-            }
-            default: {
-                throw new AlgebricksException("Trying to create an unnesting function descriptor from a "
-                        + fd.getFunctionDescriptorTag() + ". (fid=" + expr.getFunctionIdentifier() + ")");
-            }
-        }
+        return getFunctionDescriptor(expr, env, context).createUnnestingFunctionFactory(args);
     }
 
     @Override
     public ICopyEvaluatorFactory createEvaluatorFactory(ILogicalExpression expr, IVariableTypeEnvironment env,
             IOperatorSchema[] inputSchemas, JobGenContext context) throws AlgebricksException {
+        ICopyEvaluatorFactory copyEvaluatorFactory = null;
         switch (expr.getExpressionTag()) {
             case VARIABLE: {
                 VariableReferenceExpression v = (VariableReferenceExpression) expr;
-                return createVariableEvaluatorFactory(v, inputSchemas, context);
+                copyEvaluatorFactory = createVariableEvaluatorFactory(v, inputSchemas, context);
+                return copyEvaluatorFactory;
             }
             case CONSTANT: {
                 ConstantExpression c = (ConstantExpression) expr;
-                return createConstantEvaluatorFactory(c, inputSchemas, context);
+                copyEvaluatorFactory = createConstantEvaluatorFactory(c, inputSchemas, context);
+                return copyEvaluatorFactory;
             }
             case FUNCTION_CALL: {
-                AbstractFunctionCallExpression fun = (AbstractFunctionCallExpression) expr;
-                if (fun.getKind() == FunctionKind.SCALAR) {
-                    ScalarFunctionCallExpression scalar = (ScalarFunctionCallExpression) fun;
-                    return createScalarFunctionEvaluatorFactory(scalar, env, inputSchemas, context);
-                } else {
-                    throw new AlgebricksException("Cannot create evaluator for function " + fun + " of kind "
-                            + fun.getKind());
-                }
+                copyEvaluatorFactory = createScalarFunctionEvaluatorFactory((AbstractFunctionCallExpression) expr, env,
+                        inputSchemas, context);
+                return copyEvaluatorFactory;
             }
-            default: {
+            default:
                 throw new IllegalStateException();
-            }
         }
+
     }
 
     private ICopyEvaluatorFactory createVariableEvaluatorFactory(VariableReferenceExpression expr,
@@ -203,31 +124,15 @@
             return new ComparisonEvalFactory(args[0], args[1], ck);
         }
 
-        IFunctionDescriptor fd;
-
+        IFunctionDescriptor fd = null;
         AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
         IDataFormat format = mp == null ? FormatUtils.getDefaultFormat() : mp.getMetadataDeclarations().getFormat();
-        try {
-            fd = format.resolveFunction(expr, env);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
-        }
-
-        switch (fd.getFunctionDescriptorTag()) {
-            case SCALAR: {
-                IScalarFunctionDynamicDescriptor sfdd = (IScalarFunctionDynamicDescriptor) fd;
-                return sfdd.createEvaluatorFactory(args);
-            }
-            default: {
-                throw new AlgebricksException("Trying to create a scalar function descriptor from a "
-                        + fd.getFunctionDescriptorTag() + ". (fid=" + fi + ")");
-            }
-        }
-
+        fd = format.resolveFunction(expr, env);
+        return fd.createEvaluatorFactory(args);
     }
 
-    private ICopyEvaluatorFactory createConstantEvaluatorFactory(ConstantExpression expr, IOperatorSchema[] inputSchemas,
-            JobGenContext context) throws AlgebricksException {
+    private ICopyEvaluatorFactory createConstantEvaluatorFactory(ConstantExpression expr,
+            IOperatorSchema[] inputSchemas, JobGenContext context) throws AlgebricksException {
         AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
         IDataFormat format = mp == null ? FormatUtils.getDefaultFormat() : mp.getMetadataDeclarations().getFormat();
         return format.getConstantEvalFactory(expr.getValue());
@@ -250,27 +155,15 @@
             AggregateFunctionCallExpression expr, IVariableTypeEnvironment env, IOperatorSchema[] inputSchemas,
             JobGenContext context) throws AlgebricksException {
         ICopyEvaluatorFactory[] args = codegenArguments(expr, env, inputSchemas, context);
-        IFunctionDescriptor fd;
-        AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
-        AqlCompiledMetadataDeclarations compiledDecls = mp.getMetadataDeclarations();
-        try {
-            fd = compiledDecls.getFormat().resolveFunction(expr, env);
-        } catch (AlgebricksException e) {
-            throw new AlgebricksException(e);
-        }
+        IFunctionDescriptor fd = getFunctionDescriptor(expr, env, context);
+
         switch (fd.getFunctionDescriptorTag()) {
-            case SCALAR: {
-                throw new AlgebricksException(
-                        "Trying to create an aggregate from a scalar evaluator function descriptor. (fi="
-                                + expr.getFunctionIdentifier() + ")");
-            }
             case AGGREGATE: {
                 if (AsterixBuiltinFunctions.isAggregateFunctionSerializable(fd.getIdentifier())) {
                     AggregateFunctionCallExpression serialAggExpr = AsterixBuiltinFunctions
                             .makeSerializableAggregateFunctionExpression(fd.getIdentifier(), expr.getArguments());
-                    ISerializableAggregateFunctionDynamicDescriptor afdd = (ISerializableAggregateFunctionDynamicDescriptor) compiledDecls
-                            .getFormat().resolveFunction(serialAggExpr, env);
-                    return afdd.createAggregateFunctionFactory(args);
+                    IFunctionDescriptor afdd = getFunctionDescriptor(serialAggExpr, env, context);
+                    return afdd.createSerializableAggregateFunctionFactory(args);
                 } else {
                     throw new AlgebricksException(
                             "Trying to create a serializable aggregate from a non-serializable aggregate function descriptor. (fi="
@@ -278,22 +171,23 @@
                 }
             }
             case SERIALAGGREGATE: {
-                ISerializableAggregateFunctionDynamicDescriptor afdd = (ISerializableAggregateFunctionDynamicDescriptor) fd;
-                return afdd.createAggregateFunctionFactory(args);
-            }
-            case RUNNINGAGGREGATE: {
-                throw new AlgebricksException(
-                        "Trying to create an aggregate from a running aggregate function descriptor.");
-            }
-            case UNNEST: {
-                throw new AlgebricksException(
-                        "Trying to create an aggregate from an unnesting aggregate function descriptor.");
+                return fd.createSerializableAggregateFunctionFactory(args);
             }
 
-            default: {
-                throw new IllegalStateException();
-            }
+            default:
+                throw new IllegalStateException("Invalid function descriptor " + fd.getFunctionDescriptorTag()
+                        + " expected " + FunctionDescriptorTag.SERIALAGGREGATE + " or "
+                        + FunctionDescriptorTag.AGGREGATE);
         }
     }
 
+    private IFunctionDescriptor getFunctionDescriptor(AbstractFunctionCallExpression expr,
+            IVariableTypeEnvironment env, JobGenContext context) throws AlgebricksException {
+        IFunctionDescriptor fd;
+        AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
+        AqlCompiledMetadataDeclarations compiledDecls = mp.getMetadataDeclarations();
+        fd = compiledDecls.getFormat().resolveFunction(expr, env);
+        return fd;
+    }
+
 }
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java
index 76039ab..754067a 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java
@@ -28,7 +28,6 @@
 import edu.uci.ics.asterix.optimizer.rules.FuzzyEqRule;
 import edu.uci.ics.asterix.optimizer.rules.FuzzyJoinRule;
 import edu.uci.ics.asterix.optimizer.rules.IfElseToSwitchCaseFunctionRule;
-import edu.uci.ics.asterix.optimizer.rules.InlineAssignIntoAggregateRule;
 import edu.uci.ics.asterix.optimizer.rules.IntroduceDynamicTypeCastRule;
 import edu.uci.ics.asterix.optimizer.rules.IntroduceSecondaryIndexInsertDeleteRule;
 import edu.uci.ics.asterix.optimizer.rules.IntroduceStaticTypeCastRule;
@@ -59,6 +58,7 @@
 import edu.uci.ics.hyracks.algebricks.rewriter.rules.ExtractGbyExpressionsRule;
 import edu.uci.ics.hyracks.algebricks.rewriter.rules.FactorRedundantGroupAndDecorVarsRule;
 import edu.uci.ics.hyracks.algebricks.rewriter.rules.InferTypesRule;
+import edu.uci.ics.hyracks.algebricks.rewriter.rules.InlineAssignIntoAggregateRule;
 import edu.uci.ics.hyracks.algebricks.rewriter.rules.InsertOuterJoinRule;
 import edu.uci.ics.hyracks.algebricks.rewriter.rules.InsertProjectBeforeUnionRule;
 import edu.uci.ics.hyracks.algebricks.rewriter.rules.IntroHashPartitionMergeExchange;
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/InlineAssignIntoAggregateRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/InlineAssignIntoAggregateRule.java
deleted file mode 100644
index 5f98a1b..0000000
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/InlineAssignIntoAggregateRule.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package edu.uci.ics.asterix.optimizer.rules;
-
-import java.util.List;
-
-import org.apache.commons.lang3.mutable.Mutable;
-
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator;
-import edu.uci.ics.hyracks.algebricks.core.algebra.visitors.AbstractConstVarFunVisitor;
-import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
-
-
-
-public class InlineAssignIntoAggregateRule implements IAlgebraicRewriteRule {
-
-    @Override
-    public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) {
-        return false;
-    }
-
-    @Override
-    public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
-        AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
-        if (op.getOperatorTag() != LogicalOperatorTag.GROUP) {
-            return false;
-        }
-        boolean changed = false;
-        GroupByOperator gbyOp = (GroupByOperator) op;
-        for (ILogicalPlan p : gbyOp.getNestedPlans()) {
-            for (Mutable<ILogicalOperator> r : p.getRoots()) {
-                if (inlined(r)) {
-                    changed = true;
-                }
-            }
-        }
-        return changed;
-    }
-
-    private boolean inlined(Mutable<ILogicalOperator> r) throws AlgebricksException {
-        AbstractLogicalOperator op1 = (AbstractLogicalOperator) r.getValue();
-        if (op1.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
-            return false;
-        }
-        AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
-        if (op2.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
-            return false;
-        }
-        AggregateOperator agg = (AggregateOperator) op1;
-        AssignOperator assign = (AssignOperator) op2;
-        VarExprSubstitution ves = new VarExprSubstitution(assign.getVariables(), assign.getExpressions());
-        for (Mutable<ILogicalExpression> exprRef : agg.getExpressions()) {
-            ILogicalExpression expr = exprRef.getValue();
-            Pair<Boolean, ILogicalExpression> p = expr.accept(ves, null);
-            if (p.first == true) {
-                exprRef.setValue(p.second);
-            }
-            // AbstractLogicalExpression ale = (AbstractLogicalExpression) expr;
-            // ale.accept(ves, null);
-        }
-        List<Mutable<ILogicalOperator>> op1InpList = op1.getInputs();
-        op1InpList.clear();
-        op1InpList.add(op2.getInputs().get(0));
-        return true;
-    }
-
-    private class VarExprSubstitution extends AbstractConstVarFunVisitor<Pair<Boolean, ILogicalExpression>, Void> {
-
-        private List<LogicalVariable> variables;
-        private List<Mutable<ILogicalExpression>> expressions;
-
-        public VarExprSubstitution(List<LogicalVariable> variables, List<Mutable<ILogicalExpression>> expressions) {
-            this.variables = variables;
-            this.expressions = expressions;
-        }
-
-        @Override
-        public Pair<Boolean, ILogicalExpression> visitConstantExpression(ConstantExpression expr, Void arg) {
-            return new Pair<Boolean, ILogicalExpression>(false, expr);
-        }
-
-        @Override
-        public Pair<Boolean, ILogicalExpression> visitFunctionCallExpression(AbstractFunctionCallExpression expr,
-                Void arg) throws AlgebricksException {
-            boolean changed = false;
-            for (Mutable<ILogicalExpression> eRef : expr.getArguments()) {
-                ILogicalExpression e = eRef.getValue();
-                Pair<Boolean, ILogicalExpression> p = e.accept(this, arg);
-                if (p.first) {
-                    eRef.setValue(p.second);
-                    changed = true;
-                }
-            }
-            return new Pair<Boolean, ILogicalExpression>(changed, expr);
-        }
-
-        @Override
-        public Pair<Boolean, ILogicalExpression> visitVariableReferenceExpression(VariableReferenceExpression expr,
-                Void arg) {
-            LogicalVariable v = expr.getVariableReference();
-            int idx = variables.indexOf(v);
-            if (idx < 0) {
-                return new Pair<Boolean, ILogicalExpression>(false, expr);
-            } else {
-                return new Pair<Boolean, ILogicalExpression>(true, expressions.get(idx).getValue());
-            }
-
-        }
-
-    }
-}
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java
index 414dca3..6baf1b5 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java
@@ -1,6 +1,7 @@
 package edu.uci.ics.asterix.optimizer.rules.am;
 
 import java.util.ArrayList;
+import java.util.BitSet;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -116,6 +117,9 @@
         // If we can't figure out how to integrate a certain funcExpr into the current predicate, we just bail by setting this flag.
         boolean couldntFigureOut = false;
         boolean doneWithExprs = false;
+        // TODO: For now don't consider prefix searches.
+        BitSet setLowKeys = new BitSet(numSecondaryKeys);
+        BitSet setHighKeys = new BitSet(numSecondaryKeys);
         // Go through the func exprs listed as optimizable by the chosen index, 
         // and formulate a range predicate on the secondary-index keys.
         for (Integer exprIndex : exprList) {
@@ -132,11 +136,17 @@
                         lowKeyLimits[keyPos] = highKeyLimits[keyPos] = limit;
                         lowKeyInclusive[keyPos] = highKeyInclusive[keyPos] = true;
                         lowKeyConstants[keyPos] = highKeyConstants[keyPos] = optFuncExpr.getConstantVal(0);
+                        setLowKeys.set(keyPos);
+                        setHighKeys.set(keyPos);
                     } else {
                         couldntFigureOut = true;
                     }
-                    // Mmmm, we would need an inference system here.
-                    doneWithExprs = true;
+                    // TODO: For now don't consider prefix searches.
+                    // If high and low keys are set, we exit for now.
+                    if (setLowKeys.cardinality() == numSecondaryKeys
+                            && setHighKeys.cardinality() == numSecondaryKeys) {
+                    	doneWithExprs = true;
+                    }             
                     break;
                 }
                 case HIGH_EXCLUSIVE: {
diff --git a/asterix-app/src/test/resources/optimizerts/queries/orders-composite-index-search.aql b/asterix-app/src/test/resources/optimizerts/queries/orders-composite-index-search.aql
new file mode 100644
index 0000000..d82be3c
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/orders-composite-index-search.aql
@@ -0,0 +1,30 @@
+drop dataverse index_search if exists;
+create dataverse index_search;
+use dataverse index_search;
+
+create type OrderType as closed {
+  o_orderkey: int32, 
+  o_custkey: int32, 
+  o_orderstatus: string, 
+  o_totalprice: double, 
+  o_orderdate: string, 
+  o_orderpriority: string,
+  o_clerk: string, 
+  o_shippriority: int32, 
+  o_comment: string
+}
+
+create dataset Orders(OrderType) partitioned by key o_orderkey;
+
+create index idx_Custkey_Orderstatus on Orders(o_custkey, o_orderstatus);
+
+write output to nc1:"/tmp/index_search.adm";
+
+for $o in dataset('Orders')
+where
+  $o.o_custkey = 40 and $o.o_orderstatus = "P"
+return {  
+  "o_orderkey": $o.o_orderkey,
+  "o_custkey": $o.o_custkey,
+  "o_orderstatus": $o.o_orderstatus
+}
diff --git a/asterix-app/src/test/resources/optimizerts/results/orders-composite-index-search.plan b/asterix-app/src/test/resources/optimizerts/results/orders-composite-index-search.plan
new file mode 100644
index 0000000..2b19a64
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/results/orders-composite-index-search.plan
@@ -0,0 +1,16 @@
+-- SINK_WRITE  |PARTITIONED|
+  -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
+    -- STREAM_PROJECT  |PARTITIONED|
+      -- ASSIGN  |PARTITIONED|
+        -- ASSIGN  |PARTITIONED|
+          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+            -- BTREE_SEARCH  |PARTITIONED|
+              -- ONE_TO_ONE_EXCHANGE  |LOCAL|
+                -- STABLE_SORT [$$23(ASC)]  |LOCAL|
+                  -- 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|
diff --git a/asterix-aql/src/main/javacc/AQL.jj b/asterix-aql/src/main/javacc/AQL.jj
index 36a5d3e..9a47c77 100644
--- a/asterix-aql/src/main/javacc/AQL.jj
+++ b/asterix-aql/src/main/javacc/AQL.jj
@@ -601,7 +601,7 @@
     	itemTypeName = new Identifier(token.image);
   	}
   	< RIGHTPAREN >
-  )?
+  )
   {
   	  if(datasetType == DatasetType.INTERNAL) {
       	idd = InternalDatasetDeclaration();
@@ -863,6 +863,7 @@
   )?
   "as"
   ( typeExpr = TypeExpr() )
+  (";")?
   {
     long numValues = -1;
     String filename = null;
@@ -1146,11 +1147,12 @@
 }
 {
     expr = Expression()
-
+    (";")?
     {
       query.setBody(expr);
       return query;
     }
+     
 }
 
 
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Index.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Index.java
index 7c6d9ed..2aade27 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Index.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Index.java
@@ -123,4 +123,27 @@
         }
         throw new AlgebricksException("Could not find field " + expr + " in the schema.");
     }
+    
+    @Override
+    public int hashCode() {
+    	return indexName.hashCode() ^ datasetName.hashCode() ^ dataverseName.hashCode();
+    }
+    
+    @Override
+    public boolean equals(Object other) {
+    	if (!(other instanceof Index)) {
+    		return false;
+    	}
+    	Index otherIndex = (Index) other;
+    	if (!indexName.equals(otherIndex.getIndexName())) {
+    		return false;
+    	}
+    	if (!datasetName.equals(otherIndex.getDatasetName())) {
+    		return false;
+    	}
+    	if (!dataverseName.equals(otherIndex.getDataverseName())) {
+    		return false;
+    	}
+    	return true;
+    }
 }
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AbstractFunctionDescriptor.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AbstractFunctionDescriptor.java
new file mode 100644
index 0000000..caf3b91
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AbstractFunctionDescriptor.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.om.functions;
+
+import edu.uci.ics.asterix.common.functions.FunctionDescriptorTag;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyRunningAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyUnnestingFunctionFactory;
+
+public abstract class AbstractFunctionDescriptor implements IFunctionDescriptor {
+
+    @Override
+    public abstract FunctionIdentifier getIdentifier();
+
+    @Override
+    public abstract FunctionDescriptorTag getFunctionDescriptorTag();
+
+    @Override
+    public ICopyEvaluatorFactory createEvaluatorFactory(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        throw new NotImplementedException("Not Implemented");
+    }
+
+    @Override
+    public ICopyRunningAggregateFunctionFactory createRunningAggregateFunctionFactory(ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        throw new NotImplementedException("Not Implemented");
+    }
+
+    @Override
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
+            ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        throw new NotImplementedException("Not Implemented");
+    }
+
+    @Override
+    public ICopyUnnestingFunctionFactory createUnnestingFunctionFactory(ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        throw new NotImplementedException("Not Implemented");
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        throw new NotImplementedException("Not Implemented");
+
+    }
+
+}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
index 417948f..e95cb6f 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
@@ -163,51 +163,51 @@
             "numeric-idiv", 2);
     public final static FunctionIdentifier CARET = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "caret", 2);
 
-	public final static FunctionIdentifier NUMERIC_ABS = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "numeric-abs", 1);
-	public final static FunctionIdentifier NUMERIC_CEILING = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "numeric-ceiling", 1);
-	public final static FunctionIdentifier NUMERIC_FLOOR = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "numeric-floor", 1);
-	public final static FunctionIdentifier NUMERIC_ROUND = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "numeric-round", 1);
-	public final static FunctionIdentifier NUMERIC_ROUND_HALF_TO_EVEN = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "numeric-round-half-to-even", 1);
-	public final static FunctionIdentifier NUMERIC_ROUND_HALF_TO_EVEN2 = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "numeric-round-half-to-even2", 2);
-	// String funcitons
-	public final static FunctionIdentifier STRING_EQUAL = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "string-equal", 2);
-	public final static FunctionIdentifier STRING_START_WITH = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "start-with", 2);
-	public final static FunctionIdentifier STRING_END_WITH = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "end-with", 2);
-	public final static FunctionIdentifier STRING_MATCHES = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "matches", 2);
-	public final static FunctionIdentifier STRING_MATCHES_WITH_FLAG = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "matches2", 3);
-	public final static FunctionIdentifier STRING_LOWERCASE = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "lowercase", 1);
-	public final static FunctionIdentifier STRING_REPLACE = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "replace", 3);
-	public final static FunctionIdentifier STRING_REPLACE_WITH_FLAG = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "replace2", 4);
-	public final static FunctionIdentifier STRING_LENGTH = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "string-length", 1);
-	public final static FunctionIdentifier SUBSTRING2 = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "substring2", 2);
-	public final static FunctionIdentifier SUBSTRING_BEFORE = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "substring-before", 2);
-	public final static FunctionIdentifier SUBSTRING_AFTER = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "substring-after", 2);
-	public final static FunctionIdentifier STRING_TO_CODEPOINT = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "string-to-codepoint", 1);
-	public final static FunctionIdentifier CODEPOINT_TO_STRING = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "codepoint-to-string", 1);
-	public final static FunctionIdentifier STRING_CONCAT = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "string-concat", 1);
-	public final static FunctionIdentifier STRING_JOIN = new FunctionIdentifier(
-			FunctionConstants.ASTERIX_NS, "string-join", 2);
+    public final static FunctionIdentifier NUMERIC_ABS = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "numeric-abs", 1);
+    public final static FunctionIdentifier NUMERIC_CEILING = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "numeric-ceiling", 1);
+    public final static FunctionIdentifier NUMERIC_FLOOR = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "numeric-floor", 1);
+    public final static FunctionIdentifier NUMERIC_ROUND = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "numeric-round", 1);
+    public final static FunctionIdentifier NUMERIC_ROUND_HALF_TO_EVEN = new FunctionIdentifier(
+            FunctionConstants.ASTERIX_NS, "numeric-round-half-to-even", 1);
+    public final static FunctionIdentifier NUMERIC_ROUND_HALF_TO_EVEN2 = new FunctionIdentifier(
+            FunctionConstants.ASTERIX_NS, "numeric-round-half-to-even2", 2);
+    // String funcitons
+    public final static FunctionIdentifier STRING_EQUAL = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "string-equal", 2);
+    public final static FunctionIdentifier STRING_START_WITH = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "start-with", 2);
+    public final static FunctionIdentifier STRING_END_WITH = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "end-with", 2);
+    public final static FunctionIdentifier STRING_MATCHES = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "matches", 2);
+    public final static FunctionIdentifier STRING_MATCHES_WITH_FLAG = new FunctionIdentifier(
+            FunctionConstants.ASTERIX_NS, "matches2", 3);
+    public final static FunctionIdentifier STRING_LOWERCASE = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "lowercase", 1);
+    public final static FunctionIdentifier STRING_REPLACE = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "replace", 3);
+    public final static FunctionIdentifier STRING_REPLACE_WITH_FLAG = new FunctionIdentifier(
+            FunctionConstants.ASTERIX_NS, "replace2", 4);
+    public final static FunctionIdentifier STRING_LENGTH = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "string-length", 1);
+    public final static FunctionIdentifier SUBSTRING2 = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "substring2", 2);
+    public final static FunctionIdentifier SUBSTRING_BEFORE = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "substring-before", 2);
+    public final static FunctionIdentifier SUBSTRING_AFTER = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "substring-after", 2);
+    public final static FunctionIdentifier STRING_TO_CODEPOINT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "string-to-codepoint", 1);
+    public final static FunctionIdentifier CODEPOINT_TO_STRING = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "codepoint-to-string", 1);
+    public final static FunctionIdentifier STRING_CONCAT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "string-concat", 1);
+    public final static FunctionIdentifier STRING_JOIN = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "string-join", 2);
 
     public final static FunctionIdentifier DATASET = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "dataset", 1);
     public final static FunctionIdentifier FEED_INGEST = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
@@ -404,9 +404,6 @@
         IFunctionInfo finfo = asterixFunctionIdToInfo.get(fid);
         if (finfo == null) {
             finfo = new AsterixFunctionInfo(fid);
-            //   if (fid.isBuiltin()) {
-            asterixFunctionIdToInfo.put(fid, finfo);
-            //  }
         }
         return finfo;
     }
@@ -432,7 +429,7 @@
 
         // and then, Asterix builtin functions
         add(ANY_COLLECTION_MEMBER, NonTaggedCollectionMemberResultType.INSTANCE);
-        add(AVG, OptionalADoubleTypeComputer.INSTANCE);
+        addPrivateFunction(AVG, OptionalADoubleTypeComputer.INSTANCE);
         add(BOOLEAN_CONSTRUCTOR, UnaryBooleanOrNullFunctionTypeComputer.INSTANCE);
         add(CARET, NonTaggedNumericAddSubMulDivTypeComputer.INSTANCE);
         add(CIRCLE_CONSTRUCTOR, OptionalACircleTypeComputer.INSTANCE);
@@ -454,7 +451,7 @@
             }
         });
         add(CONTAINS, ABooleanTypeComputer.INSTANCE);
-        add(COUNT, AInt32TypeComputer.INSTANCE);
+        addPrivateFunction(COUNT, AInt32TypeComputer.INSTANCE);
         add(COUNTHASHED_GRAM_TOKENS, OrderedListOfAInt32TypeComputer.INSTANCE);
         add(COUNTHASHED_WORD_TOKENS, OrderedListOfAInt32TypeComputer.INSTANCE);
         add(CREATE_CIRCLE, ACircleTypeComputer.INSTANCE);
@@ -489,7 +486,7 @@
         add(GET_HANDLE, null); // TODO
         add(GET_ITEM, NonTaggedGetItemResultType.INSTANCE);
         add(GET_DATA, null); // TODO
-        add(GLOBAL_AVG, OptionalADoubleTypeComputer.INSTANCE);
+        addPrivateFunction(GLOBAL_AVG, OptionalADoubleTypeComputer.INSTANCE);
         add(GRAM_TOKENS, OrderedListOfAStringTypeComputer.INSTANCE);
         add(GLOBAL_AVG, OptionalADoubleTypeComputer.INSTANCE);
         add(HASHED_GRAM_TOKENS, OrderedListOfAInt32TypeComputer.INSTANCE);
@@ -510,11 +507,11 @@
         add(LIKE, BinaryBooleanOrNullFunctionTypeComputer.INSTANCE);
         add(LINE_CONSTRUCTOR, OptionalALineTypeComputer.INSTANCE);
         add(LISTIFY, OrderedListConstructorResultType.INSTANCE);
-        add(LOCAL_AVG, NonTaggedLocalAvgTypeComputer.INSTANCE);
+        addPrivateFunction(LOCAL_AVG, NonTaggedLocalAvgTypeComputer.INSTANCE);
         add(MAKE_FIELD_INDEX_HANDLE, null); // TODO
         add(MAKE_FIELD_NAME_HANDLE, null); // TODO
-        add(MAX, NonTaggedSumTypeComputer.INSTANCE);
-        add(MIN, NonTaggedSumTypeComputer.INSTANCE);
+        addPrivateFunction(MAX, NonTaggedSumTypeComputer.INSTANCE);
+        addPrivateFunction(MIN, NonTaggedSumTypeComputer.INSTANCE);
         add(NON_EMPTY_STREAM, ABooleanTypeComputer.INSTANCE);
         add(NULL_CONSTRUCTOR, ANullTypeComputer.INSTANCE);
         add(NUMERIC_UNARY_MINUS, NonTaggedUnaryMinusTypeComputer.INSTANCE);
@@ -523,15 +520,14 @@
         add(NUMERIC_DIVIDE, NonTaggedNumericAddSubMulDivTypeComputer.INSTANCE);
         add(NUMERIC_MOD, NonTaggedNumericAddSubMulDivTypeComputer.INSTANCE);
         add(NUMERIC_IDIV, AInt32TypeComputer.INSTANCE);
-        
-        // Xiaoyu Ma Add for new functions
+
         add(NUMERIC_ABS, NonTaggedNumericUnaryFunctionTypeComputer.INSTANCE);
         add(NUMERIC_CEILING, NonTaggedNumericUnaryFunctionTypeComputer.INSTANCE);
         add(NUMERIC_FLOOR, NonTaggedNumericUnaryFunctionTypeComputer.INSTANCE);
         add(NUMERIC_ROUND, NonTaggedNumericUnaryFunctionTypeComputer.INSTANCE);
         add(NUMERIC_ROUND_HALF_TO_EVEN, NonTaggedNumericUnaryFunctionTypeComputer.INSTANCE);
         add(NUMERIC_ROUND_HALF_TO_EVEN2, NonTaggedNumericRoundHalfToEven2TypeComputer.INSTANCE);
-        
+
         add(STRING_TO_CODEPOINT, OrderedListOfAInt32TypeComputer.INSTANCE);
         add(CODEPOINT_TO_STRING, AStringTypeComputer.INSTANCE);
         add(STRING_CONCAT, AStringTypeComputer.INSTANCE);
@@ -548,7 +544,7 @@
         add(SUBSTRING_AFTER, BinaryStringStringOrNullTypeComputer.INSTANCE);
         add(STRING_EQUAL, BinaryStringBoolOrNullTypeComputer.INSTANCE);
         add(STRING_JOIN, AStringTypeComputer.INSTANCE);
-        
+
         add(OPEN_RECORD_CONSTRUCTOR, OpenRecordConstructorResultType.INSTANCE);
         add(ORDERED_LIST_CONSTRUCTOR, OrderedListConstructorResultType.INSTANCE);
         add(POINT_CONSTRUCTOR, OptionalAPointTypeComputer.INSTANCE);
@@ -621,7 +617,7 @@
             }
         });
         add(SUBSTRING, SubstringTypeComputer.INSTANCE);
-        add(SUM, NonTaggedSumTypeComputer.INSTANCE);
+        addPrivateFunction(SUM, NonTaggedSumTypeComputer.INSTANCE);
         add(SWITCH_CASE, NonTaggedSwitchCaseComputer.INSTANCE);
         add(REG_EXP, ABooleanTypeComputer.INSTANCE);
         add(INJECT_FAILURE, InjectFailureTypeComputer.INSTANCE);
@@ -820,6 +816,13 @@
         asterixFunctionIdToInfo.put(fi, functionInfo);
     }
 
+    private static IFunctionInfo addPrivateFunction(FunctionIdentifier fi, IResultTypeComputer typeComputer) {
+        IFunctionInfo functionInfo = getAsterixFunctionInfo(fi);
+        builtinFunctionsSet.put(functionInfo, functionInfo);
+        funTypeComputer.put(functionInfo, typeComputer);
+        return functionInfo;
+    }
+
     private static void addAgg(FunctionIdentifier fi) {
         builtinAggregateFunctions.add(getAsterixFunctionInfo(fi));
     }
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/IFunctionDescriptor.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/IFunctionDescriptor.java
index 2fb5447..c372dec 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/IFunctionDescriptor.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/IFunctionDescriptor.java
@@ -1,12 +1,47 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed 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 from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package edu.uci.ics.asterix.om.functions;
 
 import java.io.Serializable;
 
 import edu.uci.ics.asterix.common.functions.FunctionDescriptorTag;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyRunningAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyUnnestingFunctionFactory;
 
 public interface IFunctionDescriptor extends Serializable {
     public FunctionIdentifier getIdentifier();
 
     public FunctionDescriptorTag getFunctionDescriptorTag();
+
+    public ICopyEvaluatorFactory createEvaluatorFactory(ICopyEvaluatorFactory[] args) throws AlgebricksException;
+
+    public ICopyRunningAggregateFunctionFactory createRunningAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException;
+
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException;
+
+    public ICopyUnnestingFunctionFactory createUnnestingFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException;
+
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException;
+
 }
\ No newline at end of file
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/base/AbstractAggregateFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/base/AbstractAggregateFunctionDynamicDescriptor.java
index 07d8141..09325e4 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/base/AbstractAggregateFunctionDynamicDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/base/AbstractAggregateFunctionDynamicDescriptor.java
@@ -1,12 +1,14 @@
 package edu.uci.ics.asterix.runtime.aggregates.base;
 
 import edu.uci.ics.asterix.common.functions.FunctionDescriptorTag;
-import edu.uci.ics.asterix.runtime.base.IAggregateFunctionDynamicDescriptor;
+import edu.uci.ics.asterix.om.functions.AbstractFunctionDescriptor;
 
-public abstract class AbstractAggregateFunctionDynamicDescriptor implements IAggregateFunctionDynamicDescriptor {
+public abstract class AbstractAggregateFunctionDynamicDescriptor extends AbstractFunctionDescriptor  {
     private static final long serialVersionUID = 1L;
 
     public FunctionDescriptorTag getFunctionDescriptorTag() {
         return FunctionDescriptorTag.AGGREGATE;
     }
+
+   
 }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/base/AbstractSerializableAggregateFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/base/AbstractSerializableAggregateFunctionDynamicDescriptor.java
index 0634868..abde117 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/base/AbstractSerializableAggregateFunctionDynamicDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/base/AbstractSerializableAggregateFunctionDynamicDescriptor.java
@@ -1,10 +1,9 @@
 package edu.uci.ics.asterix.runtime.aggregates.base;
 
 import edu.uci.ics.asterix.common.functions.FunctionDescriptorTag;
-import edu.uci.ics.asterix.runtime.base.ISerializableAggregateFunctionDynamicDescriptor;
+import edu.uci.ics.asterix.om.functions.AbstractFunctionDescriptor;
 
-public abstract class AbstractSerializableAggregateFunctionDynamicDescriptor implements
-        ISerializableAggregateFunctionDynamicDescriptor {
+public abstract class AbstractSerializableAggregateFunctionDynamicDescriptor extends AbstractFunctionDescriptor {
     private static final long serialVersionUID = 1L;
 
     @Override
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateDescriptor.java
index 057c274..6c9989d 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateDescriptor.java
@@ -48,8 +48,8 @@
     }
 
     @Override
-    public ICopySerializableAggregateFunctionFactory createAggregateFunctionFactory(ICopyEvaluatorFactory[] args)
-            throws AlgebricksException {
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
+            ICopyEvaluatorFactory[] args) throws AlgebricksException {
         final ICopyEvaluatorFactory[] evals = args;
 
         return new ICopySerializableAggregateFunctionFactory() {
@@ -89,8 +89,8 @@
                         boolean metNull = BufferSerDeUtil.getBoolean(state, start + 16);
                         if (inputVal.getLength() > 0) {
                             ++count;
-                            ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER
-                                    .deserialize(inputVal.getByteArray()[0]);
+                            ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal
+                                    .getByteArray()[0]);
                             switch (typeTag) {
                                 case INT8: {
                                     byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateDescriptor.java
index 98e86d2..d8f2553 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateDescriptor.java
@@ -39,7 +39,7 @@
     }
 
     @Override
-    public ICopySerializableAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
             throws AlgebricksException {
         return new ICopySerializableAggregateFunctionFactory() {
             private static final long serialVersionUID = 1L;
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateDescriptor.java
index 31d9345..02d24a0 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateDescriptor.java
@@ -58,7 +58,7 @@
     }
 
     @Override
-    public ICopySerializableAggregateFunctionFactory createAggregateFunctionFactory(ICopyEvaluatorFactory[] args)
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(ICopyEvaluatorFactory[] args)
             throws AlgebricksException {
         final ICopyEvaluatorFactory[] evals = args;
         List<IAType> unionList = new ArrayList<IAType>();
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateDescriptor.java
index c12a9a6..d96e488 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateDescriptor.java
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public ICopySerializableAggregateFunctionFactory createAggregateFunctionFactory(ICopyEvaluatorFactory[] args)
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(ICopyEvaluatorFactory[] args)
             throws AlgebricksException {
         final ICopyEvaluatorFactory[] evals = args;
         List<IAType> unionList = new ArrayList<IAType>();
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSumAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSumAggregateDescriptor.java
index 2b53d89..510921a 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSumAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSumAggregateDescriptor.java
@@ -52,7 +52,7 @@
     }
 
     @Override
-    public ICopySerializableAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
             throws AlgebricksException {
         return new ICopySerializableAggregateFunctionFactory() {
             private static final long serialVersionUID = 1L;
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IAggregateFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IAggregateFunctionDynamicDescriptor.java
deleted file mode 100644
index 95c604a..0000000
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IAggregateFunctionDynamicDescriptor.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package edu.uci.ics.asterix.runtime.base;
-
-import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
-
-public interface IAggregateFunctionDynamicDescriptor extends IFunctionDescriptor {
-    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
-            throws AlgebricksException;
-}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IRunningAggregateFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IRunningAggregateFunctionDynamicDescriptor.java
deleted file mode 100644
index 7ab7261..0000000
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IRunningAggregateFunctionDynamicDescriptor.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package edu.uci.ics.asterix.runtime.base;
-
-
-import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyRunningAggregateFunctionFactory;
-
-public interface IRunningAggregateFunctionDynamicDescriptor extends IFunctionDescriptor {
-    public ICopyRunningAggregateFunctionFactory createRunningAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
-            throws AlgebricksException;
-}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IScalarFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IScalarFunctionDynamicDescriptor.java
deleted file mode 100644
index 8e4353e..0000000
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IScalarFunctionDynamicDescriptor.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package edu.uci.ics.asterix.runtime.base;
-
-
-import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
-
-public interface IScalarFunctionDynamicDescriptor extends IFunctionDescriptor {
-    public ICopyEvaluatorFactory createEvaluatorFactory(ICopyEvaluatorFactory[] args) throws AlgebricksException;
-}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/ISerializableAggregateFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/ISerializableAggregateFunctionDynamicDescriptor.java
deleted file mode 100644
index 810af16..0000000
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/ISerializableAggregateFunctionDynamicDescriptor.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package edu.uci.ics.asterix.runtime.base;
-
-import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
-
-public interface ISerializableAggregateFunctionDynamicDescriptor extends IFunctionDescriptor {
-    public ICopySerializableAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
-            throws AlgebricksException;
-}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IUnnestingFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IUnnestingFunctionDynamicDescriptor.java
deleted file mode 100644
index 3f55539..0000000
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/base/IUnnestingFunctionDynamicDescriptor.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package edu.uci.ics.asterix.runtime.base;
-
-import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyUnnestingFunctionFactory;
-
-public interface IUnnestingFunctionDynamicDescriptor extends IFunctionDescriptor {
-    public ICopyUnnestingFunctionFactory createUnnestingFunctionFactory(final ICopyEvaluatorFactory[] args)
-            throws AlgebricksException;
-}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/base/AbstractScalarFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/base/AbstractScalarFunctionDynamicDescriptor.java
index 06aa928..a2f00ff 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/base/AbstractScalarFunctionDynamicDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/base/AbstractScalarFunctionDynamicDescriptor.java
@@ -1,9 +1,9 @@
 package edu.uci.ics.asterix.runtime.evaluators.base;
 
 import edu.uci.ics.asterix.common.functions.FunctionDescriptorTag;
-import edu.uci.ics.asterix.runtime.base.IScalarFunctionDynamicDescriptor;
+import edu.uci.ics.asterix.om.functions.AbstractFunctionDescriptor;
 
-public abstract class AbstractScalarFunctionDynamicDescriptor implements IScalarFunctionDynamicDescriptor {
+public abstract class AbstractScalarFunctionDynamicDescriptor extends AbstractFunctionDescriptor {
 
     private static final long serialVersionUID = 1L;
 
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/runningaggregates/base/AbstractRunningAggregateFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/runningaggregates/base/AbstractRunningAggregateFunctionDynamicDescriptor.java
index c8f12f0..9be4046 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/runningaggregates/base/AbstractRunningAggregateFunctionDynamicDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/runningaggregates/base/AbstractRunningAggregateFunctionDynamicDescriptor.java
@@ -1,10 +1,9 @@
 package edu.uci.ics.asterix.runtime.runningaggregates.base;
 
 import edu.uci.ics.asterix.common.functions.FunctionDescriptorTag;
-import edu.uci.ics.asterix.runtime.base.IRunningAggregateFunctionDynamicDescriptor;
+import edu.uci.ics.asterix.om.functions.AbstractFunctionDescriptor;
 
-public abstract class AbstractRunningAggregateFunctionDynamicDescriptor implements
-        IRunningAggregateFunctionDynamicDescriptor {
+public abstract class AbstractRunningAggregateFunctionDynamicDescriptor extends AbstractFunctionDescriptor {
     private static final long serialVersionUID = 1L;
 
     public FunctionDescriptorTag getFunctionDescriptorTag() {
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/unnestingfunctions/base/AbstractUnnestingFunctionDynamicDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/unnestingfunctions/base/AbstractUnnestingFunctionDynamicDescriptor.java
index 52a44ae..bcab30f 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/unnestingfunctions/base/AbstractUnnestingFunctionDynamicDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/unnestingfunctions/base/AbstractUnnestingFunctionDynamicDescriptor.java
@@ -1,9 +1,9 @@
 package edu.uci.ics.asterix.runtime.unnestingfunctions.base;
 
 import edu.uci.ics.asterix.common.functions.FunctionDescriptorTag;
-import edu.uci.ics.asterix.runtime.base.IUnnestingFunctionDynamicDescriptor;
+import edu.uci.ics.asterix.om.functions.AbstractFunctionDescriptor;
 
-public abstract class AbstractUnnestingFunctionDynamicDescriptor implements IUnnestingFunctionDynamicDescriptor {
+public abstract class AbstractUnnestingFunctionDynamicDescriptor extends AbstractFunctionDescriptor {
     private static final long serialVersionUID = 1L;
 
     public FunctionDescriptorTag getFunctionDescriptorTag() {