Clean up GROUP BY and WITH clause.

- fix ASTERIXDB-971, i.e., the expression to plan translator for FLWOGR without a "for";
- fix the scoping for nested WITH clause;
- fix the scoping for nested GROUP BY clause;
- fix default fields in group variables;
- fix/unify the expression substition AST visitor;
- enhance RemoveUnusedAssignAndAggregateRule to be able to remove unused GROUP BY
  decoration varaibles;
- clearly sperate SQL++ aggregate functions and SQL-92 aggregate functions, i.e.,
  SQL-92 aggregate sugars cannot apply to SQL++ aggregate functions;
- fix PushAggregateIntoGroupbyRule for nested plan deletions;
- enhance RemoveCartesianProductWithEmptyBranchRule;
- add ExtractGroupByDecorVariablesRule;
- add an aggregate function first-element;
- fix ASTERIXDB-1560, an error message issue.

Change-Id: I62fca7f937aa007d97ed87c75cef19f6aa3e5ade
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1050
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <tillw@apache.org>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
index eb4751d..720de76 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
@@ -33,6 +33,7 @@
 import org.apache.asterix.optimizer.rules.CountVarToCountOneRule;
 import org.apache.asterix.optimizer.rules.DisjunctivePredicateToJoinRule;
 import org.apache.asterix.optimizer.rules.ExtractDistinctByExpressionsRule;
+import org.apache.hyracks.algebricks.rewriter.rules.ExtractGroupByDecorVariablesRule;
 import org.apache.asterix.optimizer.rules.ExtractOrderExpressionsRule;
 import org.apache.asterix.optimizer.rules.FeedScanCollectionToUnnest;
 import org.apache.asterix.optimizer.rules.FuzzyEqRule;
@@ -131,9 +132,10 @@
     }
 
     public static final List<IAlgebraicRewriteRule> buildInitialTranslationRuleCollection() {
-        List<IAlgebraicRewriteRule> typeInfer = new LinkedList<>();
-        typeInfer.add(new TranslateIntervalExpressionRule());
-        return typeInfer;
+        List<IAlgebraicRewriteRule> translationRules = new LinkedList<>();
+        translationRules.add(new TranslateIntervalExpressionRule());
+        translationRules.add(new ExtractGroupByDecorVariablesRule());
+        return translationRules;
     }
 
     public static final List<IAlgebraicRewriteRule> buildTypeInferenceRuleCollection() {
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushAggregateIntoGroupbyRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushAggregateIntoGroupbyRule.java
index a162209..168019b 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushAggregateIntoGroupbyRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/PushAggregateIntoGroupbyRule.java
@@ -100,8 +100,24 @@
                 }
             }
         }
+
+        // Collects subplans that is to be removed.
+        Map<GroupByOperator, List<ILogicalPlan>> gbyToSubplanListMap = new HashMap<>();
         for (Pair<GroupByOperator, Integer> remove : removeList) {
-            remove.first.getNestedPlans().remove((int)remove.second);
+            GroupByOperator groupByOperator = remove.first;
+            ILogicalPlan subplan = remove.first.getNestedPlans().get(remove.second);
+            if(gbyToSubplanListMap.containsKey(groupByOperator)) {
+                List<ILogicalPlan> subplans =  gbyToSubplanListMap.get(groupByOperator);
+                subplans.add(subplan);
+            } else {
+                List<ILogicalPlan> subplans = new ArrayList<>();
+                subplans.add(subplan);
+                gbyToSubplanListMap.put(groupByOperator, subplans);
+            }
+        }
+        // Removes subplans.
+        for(Map.Entry<GroupByOperator, List<ILogicalPlan>> entry: gbyToSubplanListMap.entrySet()){
+            entry.getKey().getNestedPlans().removeAll(entry.getValue());
         }
     }
 
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ResolveVariableRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ResolveVariableRule.java
index d407a7b..1d3e904 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ResolveVariableRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ResolveVariableRule.java
@@ -43,20 +43,18 @@
 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.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.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;
 import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 
 /**
  * This rule resolves references to undefined identifiers as:
- * 1. variable/field-access paths, or
+ * 1. expression + field-access paths, or
  * 2. datasets
- * based on the available type and metatadata information.
+ * based on the available type and metadata information.
  */
 public class ResolveVariableRule implements IAlgebraicRewriteRule {
 
@@ -94,8 +92,8 @@
         }
         boolean changed = false;
         AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
-        Triple<Boolean, String, String> fullyQualifiedDatasetPathCandidate =
-                resolveFullyQualifiedPath(funcExpr, context);
+        Triple<Boolean, String, String> fullyQualifiedDatasetPathCandidate = resolveFullyQualifiedPath(funcExpr,
+                context);
         for (Mutable<ILogicalExpression> funcArgRef : funcExpr.getArguments()) {
             if (rewriteExpressionReference(op, funcArgRef, fullyQualifiedDatasetPathCandidate, exprRef, context)) {
                 changed = true;
@@ -123,35 +121,35 @@
         ILogicalExpression arg = funcExpr.getArguments().get(0).getValue();
         String unresolvedVarName = extractConstantString(arg);
         return resolveInternal(exprRef, hasMatchedDatasetForVariableName(unresolvedVarName, context),
-                findCandidatePaths(op, extractPossibleVariables(funcExpr.getArguments()), unresolvedVarName, context),
-                unresolvedVarName, fullyQualifiedDatasetPathCandidateFromParent, parentFuncRef);
+                findCandidatePaths(op, extractExprs(funcExpr.getArguments()), unresolvedVarName, context),
+                unresolvedVarName, fullyQualifiedDatasetPathCandidateFromParent, parentFuncRef, context);
     }
 
-    // Extracts all possible variables from the arguments of the "resolve" function.
-    private List<LogicalVariable> extractPossibleVariables(List<Mutable<ILogicalExpression>> args)
-            throws AlgebricksException {
-        List<LogicalVariable> vars = new ArrayList<>();
+    // Extracts all possible expressions from the arguments of the "resolve" function.
+    private List<ILogicalExpression> extractExprs(List<Mutable<ILogicalExpression>> args) throws AlgebricksException {
+        List<ILogicalExpression> exprs = new ArrayList<>();
         // The first arg is is the name of the undefined variable.
         for (int index = 1; index < args.size(); ++index) {
-            vars.add(extractVariable(args.get(index).getValue()));
+            ILogicalExpression argExpr = args.get(index).getValue();
+            exprs.add(argExpr);
         }
-        return vars;
+        return exprs;
     }
 
     // Resolves an undefined name to a dataset or a fully qualified variable/field-access path
     // based on the given information of dataset matches and candidate paths.
     private boolean resolveInternal(Mutable<ILogicalExpression> funcRef, boolean hasMatchedDataset,
-            Collection<Pair<LogicalVariable, List<String>>> varAccessCandidates, String unresolvedVarName,
+            Collection<Pair<ILogicalExpression, List<String>>> varAccessCandidates, String unresolvedVarName,
             Triple<Boolean, String, String> fullyQualifiedDatasetPathCandidateFromParent,
-            Mutable<ILogicalExpression> parentFuncRef) throws AlgebricksException {
+            Mutable<ILogicalExpression> parentFuncRef, IOptimizationContext context) throws AlgebricksException {
         AbstractFunctionCallExpression func = (AbstractFunctionCallExpression) funcRef.getValue();
         int numVarCandidates = varAccessCandidates.size();
-        boolean hasAmbiguity =
-                hasAmbiguity(hasMatchedDataset, fullyQualifiedDatasetPathCandidateFromParent, numVarCandidates);
+        boolean hasAmbiguity = hasAmbiguity(hasMatchedDataset, fullyQualifiedDatasetPathCandidateFromParent,
+                numVarCandidates);
         if (hasAmbiguity) {
             // More than one possibilities.
-            throw new AlgebricksException(
-                    "Cannot resolve ambiguous alias (variable) reference for identifier " + unresolvedVarName);
+            throw new AlgebricksException("Cannot resolve ambiguous alias reference for undefined identifier "
+                    + unresolvedVarName);
         } else if (hasMatchedDataset) {
             // Rewrites the "resolve" function to a "dataset" function and only keep the dataset name argument.
             func.setFunctionInfo(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.DATASET));
@@ -163,15 +161,17 @@
             AbstractFunctionCallExpression parentFunc = (AbstractFunctionCallExpression) parentFuncRef.getValue();
             parentFunc.setFunctionInfo(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.DATASET));
             parentFunc.getArguments().clear();
-            parentFunc.getArguments()
-                    .add(new MutableObject<ILogicalExpression>(new ConstantExpression(
+            parentFunc.getArguments().add(
+                    new MutableObject<>(new ConstantExpression(
                             new AsterixConstantValue(new AString(fullyQualifiedDatasetPathCandidateFromParent.second
                                     + "." + fullyQualifiedDatasetPathCandidateFromParent.third)))));
         } else if (numVarCandidates == 1) {
             resolveAsFieldAccess(funcRef, varAccessCandidates.iterator().next());
         } else {
+            AqlMetadataProvider metadataProvider = (AqlMetadataProvider) context.getMetadataProvider();
             // Cannot find any resolution.
-            throw new AlgebricksException("Undefined alias (variable) reference for identifier " + unresolvedVarName);
+            throw new AlgebricksException("Cannot find dataset " + unresolvedVarName + " in dataverse "
+                    + metadataProvider.getDefaultDataverseName() + " nor an alias with name " + unresolvedVarName);
         }
         return true;
     }
@@ -187,17 +187,16 @@
 
     // Resolves a "resolve" function call as a field access.
     private void resolveAsFieldAccess(Mutable<ILogicalExpression> funcRef,
-            Pair<LogicalVariable, List<String>> varAndPath) {
+            Pair<ILogicalExpression, List<String>> varAndPath) {
         // Rewrites to field-access-by-names.
-        LogicalVariable var = varAndPath.first;
+        ILogicalExpression expr = varAndPath.first;
         List<String> path = varAndPath.second;
-        Mutable<ILogicalExpression> firstArgRef = new MutableObject<>(new VariableReferenceExpression(var));
+        Mutable<ILogicalExpression> firstArgRef = new MutableObject<>(expr);
         ILogicalExpression newFunc = null;
         for (String fieldName : path) {
             List<Mutable<ILogicalExpression>> args = new ArrayList<>();
             args.add(firstArgRef);
-            args.add(new MutableObject<ILogicalExpression>(
-                    new ConstantExpression(new AsterixConstantValue(new AString(fieldName)))));
+            args.add(new MutableObject<>(new ConstantExpression(new AsterixConstantValue(new AString(fieldName)))));
             newFunc = new ScalarFunctionCallExpression(
                     FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.FIELD_ACCESS_BY_NAME), args);
             firstArgRef = new MutableObject<>(newFunc);
@@ -205,23 +204,23 @@
         funcRef.setValue(newFunc);
     }
 
-    // Finds all candidate fully qualified variable/field-access paths.
-    private Set<Pair<LogicalVariable, List<String>>> findCandidatePaths(ILogicalOperator op,
-            Collection<LogicalVariable> inputLiveVars, String unresolvedVarName, IOptimizationContext context)
+    // Finds all candidate fully qualified expression/field-access paths.
+    private Set<Pair<ILogicalExpression, List<String>>> findCandidatePaths(ILogicalOperator op,
+            Collection<ILogicalExpression> referenceExprs, String unresolvedVarName, IOptimizationContext context)
             throws AlgebricksException {
-        Set<Pair<LogicalVariable, List<String>>> candidates = new HashSet<>();
+        Set<Pair<ILogicalExpression, List<String>>> candidates = new HashSet<>();
         IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op.getInputs().get(0).getValue());
-        for (LogicalVariable var : inputLiveVars) {
-            IAType type = (IAType) env.getVarType(var);
-            candidates.addAll(findCandidatePathsForVariable(unresolvedVarName, type, var, new ArrayList<String>()));
+        for (ILogicalExpression referenceExpr : referenceExprs) {
+            IAType type = (IAType) env.getType(referenceExpr);
+            candidates.addAll(findCandidatePathsForExpr(unresolvedVarName, type, referenceExpr, new ArrayList<>()));
         }
         return candidates;
     }
 
-    // Recursively finds candidate paths under a variable.
-    private Set<Pair<LogicalVariable, List<String>>> findCandidatePathsForVariable(String unresolvedVarName,
-            IAType pathType, LogicalVariable var, List<String> parentPath) throws AlgebricksException {
-        Set<Pair<LogicalVariable, List<String>>> varAccessCandidates = new HashSet<>();
+    // Recursively finds candidate paths under an expression.
+    private Set<Pair<ILogicalExpression, List<String>>> findCandidatePathsForExpr(String unresolvedVarName,
+            IAType pathType, ILogicalExpression expr, List<String> parentPath) throws AlgebricksException {
+        Set<Pair<ILogicalExpression, List<String>>> varAccessCandidates = new HashSet<>();
         IAType type = pathType;
         if (type.getTypeTag() == ATypeTag.UNION) {
             type = ((AUnionType) type).getActualType();
@@ -230,7 +229,7 @@
         if (tag == ATypeTag.ANY) {
             List<String> path = new ArrayList<>(parentPath);
             path.add(unresolvedVarName);
-            varAccessCandidates.add(new Pair<>(var, path));
+            varAccessCandidates.add(new Pair<>(expr, path));
         }
         if (tag == ATypeTag.RECORD) {
             ARecordType recordType = (ARecordType) type;
@@ -238,7 +237,7 @@
                 // If the field name is possible.
                 List<String> path = new ArrayList<>(parentPath);
                 path.add(unresolvedVarName);
-                varAccessCandidates.add(new Pair<>(var, path));
+                varAccessCandidates.add(new Pair<>(expr, path));
             } else {
                 // Recursively identified possible paths.
                 String[] fieldNames = recordType.getFieldNames();
@@ -246,8 +245,8 @@
                 for (int index = 0; index < fieldNames.length; ++index) {
                     List<String> path = new ArrayList<>(parentPath);
                     path.add(fieldNames[index]);
-                    varAccessCandidates
-                            .addAll(findCandidatePathsForVariable(unresolvedVarName, fieldTypes[index], var, path));
+                    varAccessCandidates.addAll(findCandidatePathsForExpr(unresolvedVarName, fieldTypes[index], expr,
+                            path));
                 }
             }
         }
@@ -284,10 +283,7 @@
     private boolean hasMatchedDataverseDataset(String dataverseName, String datasetName, IOptimizationContext context)
             throws AlgebricksException {
         AqlMetadataProvider mdp = (AqlMetadataProvider) context.getMetadataProvider();
-        if (mdp.findDataset(dataverseName, datasetName) != null) {
-            return true;
-        }
-        return false;
+        return mdp.findDataset(dataverseName, datasetName) != null;
     }
 
     // Checks whether the name matches a dataset.
@@ -309,17 +305,6 @@
         return false;
     }
 
-    // Extracts the variable from a variable reference expression.
-    private LogicalVariable extractVariable(ILogicalExpression expr) throws AlgebricksException {
-        if (expr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
-            VariableReferenceExpression varRefExpr = (VariableReferenceExpression) expr;
-            return varRefExpr.getVariableReference();
-        } else {
-            // The sugar visitor gurantees this would not happen.
-            throw new AlgebricksException("The argument should be a variable reference expression.");
-        }
-    }
-
     // Cleans up scan collections on top of a "dataset" function call since "dataset"
     // is an unnest function.
     private void cleanupScanCollectionForDataset(AbstractFunctionCallExpression funcExpr) {
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
index 6bcdd90..79342c9 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
@@ -30,8 +30,8 @@
 import org.apache.asterix.lang.aql.visitor.base.IAQLVisitor;
 import org.apache.asterix.lang.common.base.Clause;
 import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.statement.Query;
 import org.apache.asterix.metadata.declared.AqlMetadataProvider;
@@ -42,7 +42,10 @@
 import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+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.VariableReferenceExpression;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistinctOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator;
@@ -103,13 +106,13 @@
         }
 
         Expression r = flwor.getReturnExpr();
-        boolean noFlworClause = flwor.noForClause();
+        boolean noForClause = flwor.noForClause();
 
         Pair<ILogicalOperator, LogicalVariable> result;
         if (r.getKind() == Kind.VARIABLE_EXPRESSION) {
             VariableExpr v = (VariableExpr) r;
             LogicalVariable var = context.getVar(v.getVar().getId());
-            result = produceFlworPlan(noFlworClause, isTop, flworPlan, var);
+            result = produceFlworPlan(noForClause, isTop, flworPlan, var);
         } else {
             Mutable<ILogicalOperator> baseOp = new MutableObject<>(flworPlan.getValue());
             Pair<ILogicalOperator, LogicalVariable> rRes = r.accept(this, baseOp);
@@ -125,7 +128,7 @@
                 baseOp.setValue(new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(s)));
             }
             Mutable<ILogicalOperator> resOpRef = new MutableObject<>(resOp);
-            result = produceFlworPlan(noFlworClause, isTop, resOpRef, rRes.second);
+            result = produceFlworPlan(noForClause, isTop, resOpRef, rRes.second);
         }
         if (!isTop) {
             context.exitSubplan();
@@ -164,6 +167,17 @@
         return aggListifyForSubquery(result.second, new MutableObject<>(result.first), false);
     }
 
+    @Override
+    protected boolean expressionNeedsNoNesting(Expression expr) {
+        boolean noForFLWOR = false;
+        // No nesting is needed for a FLWOR expression without a FOR clause.
+        if (expr.getKind() == Kind.FLWOGR_EXPRESSION) {
+            FLWOGRExpression flwor = (FLWOGRExpression) expr;
+            noForFLWOR = flwor.noForClause();
+        }
+        return noForFLWOR || super.expressionNeedsNoNesting(expr);
+    }
+
     private Pair<ILogicalOperator, LogicalVariable> produceFlworPlan(boolean noForClause, boolean isTop,
             Mutable<ILogicalOperator> resOpRef, LogicalVariable resVar) {
         if (isTop) {
@@ -171,7 +185,15 @@
             pr.getInputs().add(resOpRef);
             return new Pair<>(pr, resVar);
         } else if (noForClause) {
-            return new Pair<>(resOpRef.getValue(), resVar);
+            ILogicalOperator resOp = resOpRef.getValue();
+            if (resOp.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
+                return new Pair<>(resOp, resVar);
+            }
+            LogicalVariable newResVar = context.newVar();
+            ILogicalOperator assign =
+                    new AssignOperator(newResVar, new MutableObject<>(new VariableReferenceExpression(resVar)));
+            assign.getInputs().add(resOpRef);
+            return new Pair<>(assign, newResVar);
         } else {
             return aggListifyForSubquery(resVar, resOpRef, false);
         }
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlPlusExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlPlusExpressionToPlanTranslator.java
index 39648d1..334436a 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlPlusExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlPlusExpressionToPlanTranslator.java
@@ -22,6 +22,7 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map.Entry;
 import java.util.logging.Logger;
 
 import org.apache.asterix.common.config.DatasetConfig.DatasetType;
@@ -547,22 +548,22 @@
         }
         gOp.getInputs().add(topOp);
 
-        for (VariableExpr var : gc.getWithVarList()) {
+        for (Entry<Expression, VariableExpr> entry : gc.getWithVarMap().entrySet()) {
             LogicalVariable aggVar = context.newVar();
-            LogicalVariable oldVar = context.getVar(var);
-            List<Mutable<ILogicalExpression>> flArgs = new ArrayList<Mutable<ILogicalExpression>>(1);
-            flArgs.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(oldVar)));
+            Pair<ILogicalExpression, Mutable<ILogicalOperator>> listifyInput = aqlExprToAlgExpression(entry.getKey(),
+                    new MutableObject<>(new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(gOp))));
+            List<Mutable<ILogicalExpression>> flArgs = new ArrayList<>(1);
+            flArgs.add(new MutableObject<>(listifyInput.first));
             AggregateFunctionCallExpression fListify =
                     AsterixBuiltinFunctions.makeAggregateFunctionExpression(AsterixBuiltinFunctions.LISTIFY, flArgs);
             AggregateOperator agg = new AggregateOperator(mkSingletonArrayList(aggVar),
-                    (List) mkSingletonArrayList(new MutableObject<ILogicalExpression>(fListify)));
-            agg.getInputs().add(new MutableObject<ILogicalOperator>(
-                    new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(gOp))));
-            ILogicalPlan plan = new ALogicalPlanImpl(new MutableObject<ILogicalOperator>(agg));
+                    mkSingletonArrayList(new MutableObject<>(fListify)));
+            agg.getInputs().add(listifyInput.second);
+            ILogicalPlan plan = new ALogicalPlanImpl(new MutableObject<>(agg));
             gOp.getNestedPlans().add(plan);
             // Hide the variable that was part of the "with", replacing it with
             // the one bound by the aggregation op.
-            context.setVar(var, aggVar);
+            context.setVar(entry.getValue(), aggVar);
         }
 
         gOp.getAnnotations().put(OperatorAnnotations.USE_HASH_GROUP_BY, gc.hasHashGroupByHint());
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index d85419e..bd87e6e 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -18,6 +18,8 @@
  */
 package org.apache.asterix.translator;
 
+import static java.util.logging.Logger.global;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -28,6 +30,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Map.Entry;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
@@ -38,15 +41,15 @@
 import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.lang.aql.util.RangeMapBuilder;
 import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.base.ILangExpression;
 import org.apache.asterix.lang.common.base.Statement;
+import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.clause.GroupbyClause;
 import org.apache.asterix.lang.common.clause.LetClause;
 import org.apache.asterix.lang.common.clause.LimitClause;
 import org.apache.asterix.lang.common.clause.OrderbyClause;
-import org.apache.asterix.lang.common.clause.OrderbyClause.OrderModifier;
 import org.apache.asterix.lang.common.clause.WhereClause;
+import org.apache.asterix.lang.common.clause.OrderbyClause.OrderModifier;
 import org.apache.asterix.lang.common.expression.CallExpr;
 import org.apache.asterix.lang.common.expression.FieldAccessor;
 import org.apache.asterix.lang.common.expression.FieldBinding;
@@ -54,14 +57,14 @@
 import org.apache.asterix.lang.common.expression.IfExpr;
 import org.apache.asterix.lang.common.expression.IndexAccessor;
 import org.apache.asterix.lang.common.expression.ListConstructor;
-import org.apache.asterix.lang.common.expression.ListConstructor.Type;
 import org.apache.asterix.lang.common.expression.LiteralExpr;
 import org.apache.asterix.lang.common.expression.OperatorExpr;
 import org.apache.asterix.lang.common.expression.QuantifiedExpression;
-import org.apache.asterix.lang.common.expression.QuantifiedExpression.Quantifier;
 import org.apache.asterix.lang.common.expression.RecordConstructor;
 import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.expression.ListConstructor.Type;
+import org.apache.asterix.lang.common.expression.QuantifiedExpression.Quantifier;
 import org.apache.asterix.lang.common.literal.StringLiteral;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.Query;
@@ -72,13 +75,13 @@
 import org.apache.asterix.lang.common.visitor.base.AbstractQueryExpressionVisitor;
 import org.apache.asterix.metadata.MetadataException;
 import org.apache.asterix.metadata.MetadataManager;
-import org.apache.asterix.metadata.declared.AqlDataSource.AqlDataSourceType;
 import org.apache.asterix.metadata.declared.AqlMetadataProvider;
 import org.apache.asterix.metadata.declared.AqlSourceId;
 import org.apache.asterix.metadata.declared.DatasetDataSource;
 import org.apache.asterix.metadata.declared.LoadableDataSource;
 import org.apache.asterix.metadata.declared.ResultSetDataSink;
 import org.apache.asterix.metadata.declared.ResultSetSinkId;
+import org.apache.asterix.metadata.declared.AqlDataSource.AqlDataSourceType;
 import org.apache.asterix.metadata.entities.Dataset;
 import org.apache.asterix.metadata.entities.Function;
 import org.apache.asterix.metadata.entities.InternalDatasetDetails;
@@ -114,15 +117,15 @@
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
 import org.apache.hyracks.algebricks.core.algebra.base.OperatorAnnotations;
 import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression.FunctionKind;
 import org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.BroadcastExpressionAnnotation;
-import org.apache.hyracks.algebricks.core.algebra.expressions.BroadcastExpressionAnnotation.BroadcastSide;
 import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionAnnotation;
 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;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression.FunctionKind;
+import org.apache.hyracks.algebricks.core.algebra.expressions.BroadcastExpressionAnnotation.BroadcastSide;
 import org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
@@ -138,13 +141,13 @@
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.LimitOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator.IOrder.OrderKind;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SinkOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator.IOrder.OrderKind;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.LogicalOperatorDeepCopyWithNewVariablesVisitor;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
@@ -786,18 +789,38 @@
         if (gc.isGroupAll()) {
             List<LogicalVariable> aggVars = new ArrayList<>();
             List<Mutable<ILogicalExpression>> aggFuncs = new ArrayList<>();
-            for (VariableExpr var : gc.getWithVarList()) {
-                LogicalVariable aggVar = context.newVar();
-                LogicalVariable oldVar = context.getVar(var);
+            // A global aggregation can still have a decoration variable list which are used for propagate
+            // outer-scope variables. Example query:
+            // asterixdb/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09
+            for (GbyVariableExpressionPair ve : gc.getDecorPairList()) {
+                VariableExpr vexpr = ve.getVar();
+                LogicalVariable decorVar = vexpr == null ? context.newVar() : context.newVar(vexpr);
+                Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = langExprToAlgExpression(ve.getExpr(), topOp);
+                topOp = eo.second;
                 List<Mutable<ILogicalExpression>> flArgs = new ArrayList<>();
-                flArgs.add(new MutableObject<>(new VariableReferenceExpression(oldVar)));
+                flArgs.add(new MutableObject<>(eo.first));
+                // Calls the first-element aggregate function on a decoration variable to make sure the value
+                // is propagated through a global aggregation.
+                AggregateFunctionCallExpression firstElementAgg = AsterixBuiltinFunctions
+                        .makeAggregateFunctionExpression(
+                        AsterixBuiltinFunctions.FIRST_ELEMENT, flArgs);
+                aggVars.add(decorVar);
+                aggFuncs.add(new MutableObject<>(firstElementAgg));
+            }
+            for (Entry<Expression, VariableExpr> entry : gc.getWithVarMap().entrySet()) {
+                Pair<ILogicalExpression, Mutable<ILogicalOperator>> listifyInput =
+                        langExprToAlgExpression(entry.getKey(), topOp);
+                topOp = listifyInput.second;
+                List<Mutable<ILogicalExpression>> flArgs = new ArrayList<>();
+                flArgs.add(new MutableObject<>(listifyInput.first));
                 AggregateFunctionCallExpression fListify = AsterixBuiltinFunctions
                         .makeAggregateFunctionExpression(AsterixBuiltinFunctions.LISTIFY, flArgs);
+                LogicalVariable aggVar = context.newVar();
                 aggVars.add(aggVar);
                 aggFuncs.add(new MutableObject<>(fListify));
                 // Hide the variable that was part of the "with", replacing it with
                 // the one bound by the aggregation op.
-                context.setVar(var, aggVar);
+                context.setVar(entry.getValue(), aggVar);
             }
             AggregateOperator aggOp = new AggregateOperator(aggVars, aggFuncs);
             aggOp.getInputs().add(topOp);
@@ -830,22 +853,23 @@
             }
 
             gOp.getInputs().add(topOp);
-            for (VariableExpr var : gc.getWithVarList()) {
-                LogicalVariable aggVar = context.newVar();
-                LogicalVariable oldVar = context.getVar(var);
+            for (Entry<Expression, VariableExpr> entry : gc.getWithVarMap().entrySet()) {
+                Pair<ILogicalExpression, Mutable<ILogicalOperator>> listifyInput = langExprToAlgExpression(
+                        entry.getKey(), new MutableObject<>(new NestedTupleSourceOperator(new MutableObject<>(gOp))));
                 List<Mutable<ILogicalExpression>> flArgs = new ArrayList<>(1);
-                flArgs.add(new MutableObject<>(new VariableReferenceExpression(oldVar)));
+                flArgs.add(new MutableObject<>(listifyInput.first));
                 AggregateFunctionCallExpression fListify = AsterixBuiltinFunctions
                         .makeAggregateFunctionExpression(AsterixBuiltinFunctions.LISTIFY, flArgs);
+                LogicalVariable aggVar = context.newVar();
                 AggregateOperator agg = new AggregateOperator(mkSingletonArrayList(aggVar),
-                        (List) mkSingletonArrayList(new MutableObject<>(fListify)));
+                        mkSingletonArrayList(new MutableObject<>(fListify)));
 
-                agg.getInputs().add(new MutableObject<>(new NestedTupleSourceOperator(new MutableObject<>(gOp))));
+                agg.getInputs().add(listifyInput.second);
                 ILogicalPlan plan = new ALogicalPlanImpl(new MutableObject<>(agg));
                 gOp.getNestedPlans().add(plan);
                 // Hide the variable that was part of the "with", replacing it with
                 // the one bound by the aggregation op.
-                context.setVar(var, aggVar);
+                context.setVar(entry.getValue(), aggVar);
             }
             gOp.getAnnotations().put(OperatorAnnotations.USE_HASH_GROUP_BY, gc.hasHashGroupByHint());
             return new Pair<>(gOp, null);
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index 982a334..f2ba140 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -173,9 +173,6 @@
             Mutable<ILogicalOperator> tupleSource) throws AsterixException {
         Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo =
                 langExprToAlgExpression(independentSubquery.getExpr(), tupleSource);
-        // Replaces nested tuple source with empty tuple source so that the subquery can be independent
-        // from its input operators.
-        replaceNtsWithEts(eo.second.getValue());
         LogicalVariable var = context.newVar();
         AssignOperator assignOp = new AssignOperator(var, new MutableObject<ILogicalExpression>(eo.first));
         assignOp.getInputs().add(eo.second);
@@ -586,20 +583,6 @@
         }
     }
 
-    // Replaces nested tuple source with empty tuple source in nested subplans of
-    // a subplan operator.
-    private void replaceNtsWithEts(ILogicalOperator op) {
-        if (op.getOperatorTag() != LogicalOperatorTag.SUBPLAN) {
-            return;
-        }
-        SubplanOperator subplanOp = (SubplanOperator) op;
-        for (ILogicalPlan plan : subplanOp.getNestedPlans()) {
-            for (Mutable<ILogicalOperator> rootRef : plan.getRoots()) {
-                replaceNtsWithEtsTopDown(rootRef);
-            }
-        }
-    }
-
     // Recursively replaces nested tuple source with empty tuple source
     // in the operator tree under opRef.
     private void replaceNtsWithEtsTopDown(Mutable<ILogicalOperator> opRef) {
@@ -691,7 +674,10 @@
         for (GbyVariableExpressionPair pair : groupbyClause.getGbyPairList()) {
             fieldBindings.add(getFieldBinding(pair.getVar()));
         }
-        fieldBindings.add(getFieldBinding(groupbyClause.getGroupVar()));
+        if (groupbyClause.hasWithMap() && groupbyClause.hasGroupVar()) {
+            // Makes sure that we add the re-mapped group variable which refers to a collection.
+            fieldBindings.add(getFieldBinding(groupbyClause.getWithVarMap().get(groupbyClause.getGroupVar())));
+        }
         return fieldBindings;
     }
 
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
index 2c0aef4..3201d9e 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
@@ -24,7 +24,9 @@
 import java.util.List;
 
 import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.aggregates.collections.FirstElementAggregateDescriptor;
 import org.apache.asterix.runtime.aggregates.collections.ListifyAggregateDescriptor;
+import org.apache.asterix.runtime.aggregates.collections.LocalFirstElementAggregateDescriptor;
 import org.apache.asterix.runtime.aggregates.scalar.ScalarAvgAggregateDescriptor;
 import org.apache.asterix.runtime.aggregates.scalar.ScalarCountAggregateDescriptor;
 import org.apache.asterix.runtime.aggregates.scalar.ScalarMaxAggregateDescriptor;
@@ -313,6 +315,8 @@
         temp.add(LocalMaxAggregateDescriptor.FACTORY);
         temp.add(MinAggregateDescriptor.FACTORY);
         temp.add(LocalMinAggregateDescriptor.FACTORY);
+        temp.add(FirstElementAggregateDescriptor.FACTORY);
+        temp.add(LocalFirstElementAggregateDescriptor.FACTORY);
 
         // serializable aggregates
         temp.add(SerializableCountAggregateDescriptor.FACTORY);
diff --git a/asterixdb/asterix-algebra/src/main/javacc/AQLPlus.jj b/asterixdb/asterix-algebra/src/main/javacc/AQLPlus.jj
index 98cae63..e0e9388 100644
--- a/asterixdb/asterix-algebra/src/main/javacc/AQLPlus.jj
+++ b/asterixdb/asterix-algebra/src/main/javacc/AQLPlus.jj
@@ -1381,7 +1381,7 @@
       // GbyVariableExpressionPair pair = new GbyVariableExpressionPair();
      List<GbyVariableExpressionPair> vePairList = new ArrayList<GbyVariableExpressionPair>();
     List<GbyVariableExpressionPair> decorPairList = new ArrayList<GbyVariableExpressionPair>();
-    List<VariableExpr> withVarList= new ArrayList<VariableExpr>();
+    Map<Expression, VariableExpr> withVarMap= new HashMap<Expression, VariableExpr>();
     VariableExpr var = null;
     VariableExpr withVar = null;
     Expression expr = null;
@@ -1437,20 +1437,20 @@
     {
       if(withVar.getIsNewVar()==true)
           throw new ParseException("can't find variable " + withVar.getVar());
-      withVarList.add(withVar);
+      withVarMap.put(withVar, withVar);
       newScope.addNewVarSymbolToScope(withVar.getVar());
     }
     ("," withVar = VariableRef()
     {
       if(withVar.getIsNewVar()==true)
           throw new ParseException("can't find variable " + withVar.getVar());
-      withVarList.add(withVar);
+      withVarMap.put(withVar, withVar);
       newScope.addNewVarSymbolToScope(withVar.getVar());
     })*
     {
       gbc.setGbyPairList(vePairList);
       gbc.setDecorPairList(decorPairList);
-      gbc.setWithVarList(withVarList);
+      gbc.setWithVarMap(withVarMap);
       replaceCurrentScope(newScope);
       return gbc;
     }
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-gby-agg.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-gby-agg.plan
index 4495551..773be15 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-gby-agg.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-gby-agg.plan
@@ -3,13 +3,13 @@
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-          -- PRE_CLUSTERED_GROUP_BY[$$19]  |PARTITIONED|
+          -- PRE_CLUSTERED_GROUP_BY[$$26]  |PARTITIONED|
                   {
                     -- AGGREGATE  |LOCAL|
                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                   }
-            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$19(ASC)] HASH:[$$19]  |PARTITIONED|
-              -- SORT_GROUP_BY[$$15]  |PARTITIONED|
+            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$26(ASC)] HASH:[$$26]  |PARTITIONED|
+              -- SORT_GROUP_BY[$$22]  |PARTITIONED|
                       {
                         -- AGGREGATE  |LOCAL|
                           -- NESTED_TUPLE_SOURCE  |LOCAL|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/loj-core.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/loj-core.plan
index 1d34c95..fb6d5fb 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/loj-core.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/loj-core.plan
@@ -2,20 +2,20 @@
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
-        -- SORT_MERGE_EXCHANGE [$$15(ASC) ]  |PARTITIONED|
-          -- STABLE_SORT [$$15(ASC)]  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$18(ASC) ]  |PARTITIONED|
+          -- STABLE_SORT [$$18(ASC)]  |PARTITIONED|
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
               -- STREAM_PROJECT  |PARTITIONED|
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  -- HYBRID_HASH_JOIN [$$17][$$18]  |PARTITIONED|
-                    -- HASH_PARTITION_EXCHANGE [$$17]  |PARTITIONED|
+                  -- HYBRID_HASH_JOIN [$$20][$$21]  |PARTITIONED|
+                    -- HASH_PARTITION_EXCHANGE [$$20]  |PARTITIONED|
                       -- STREAM_PROJECT  |PARTITIONED|
                         -- ASSIGN  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                             -- DATASOURCE_SCAN  |PARTITIONED|
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                    -- HASH_PARTITION_EXCHANGE [$$18]  |PARTITIONED|
+                    -- HASH_PARTITION_EXCHANGE [$$21]  |PARTITIONED|
                       -- ASSIGN  |PARTITIONED|
                         -- STREAM_PROJECT  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/loj-sugar.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/loj-sugar.plan
index 1d34c95..c712344 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/loj-sugar.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/loj-sugar.plan
@@ -2,20 +2,20 @@
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
-        -- SORT_MERGE_EXCHANGE [$$15(ASC) ]  |PARTITIONED|
-          -- STABLE_SORT [$$15(ASC)]  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$17(ASC) ]  |PARTITIONED|
+          -- STABLE_SORT [$$17(ASC)]  |PARTITIONED|
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
               -- STREAM_PROJECT  |PARTITIONED|
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  -- HYBRID_HASH_JOIN [$$17][$$18]  |PARTITIONED|
-                    -- HASH_PARTITION_EXCHANGE [$$17]  |PARTITIONED|
+                  -- HYBRID_HASH_JOIN [$$19][$$20]  |PARTITIONED|
+                    -- HASH_PARTITION_EXCHANGE [$$19]  |PARTITIONED|
                       -- STREAM_PROJECT  |PARTITIONED|
                         -- ASSIGN  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                             -- DATASOURCE_SCAN  |PARTITIONED|
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                    -- HASH_PARTITION_EXCHANGE [$$18]  |PARTITIONED|
+                    -- HASH_PARTITION_EXCHANGE [$$20]  |PARTITIONED|
                       -- ASSIGN  |PARTITIONED|
                         -- STREAM_PROJECT  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/orderby-desc-using-gby.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/orderby-desc-using-gby.plan
index fa71b96..8c86c6b 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/orderby-desc-using-gby.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/orderby-desc-using-gby.plan
@@ -3,12 +3,12 @@
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
         -- SORT_MERGE_EXCHANGE [$$1(DESC) ]  |PARTITIONED|
-          -- SORT_GROUP_BY[$$9]  |PARTITIONED|
+          -- SORT_GROUP_BY[$$10]  |PARTITIONED|
                   {
                     -- AGGREGATE  |LOCAL|
                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                   }
-            -- HASH_PARTITION_EXCHANGE [$$9]  |PARTITIONED|
+            -- HASH_PARTITION_EXCHANGE [$$10]  |PARTITIONED|
               -- STREAM_PROJECT  |PARTITIONED|
                 -- ASSIGN  |PARTITIONED|
                   -- STREAM_PROJECT  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/exists.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/exists.plan
index cd0a17e..54716d3 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/exists.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/exists.plan
@@ -2,14 +2,14 @@
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
-        -- SORT_MERGE_EXCHANGE [$$8(ASC) ]  |PARTITIONED|
-          -- PRE_CLUSTERED_GROUP_BY[$$82]  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$31(ASC) ]  |PARTITIONED|
+          -- PRE_CLUSTERED_GROUP_BY[$$104]  |PARTITIONED|
                   {
                     -- AGGREGATE  |LOCAL|
                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                   }
-            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$82(ASC)] HASH:[$$82]  |PARTITIONED|
-              -- SORT_GROUP_BY[$$59]  |PARTITIONED|
+            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$104(ASC)] HASH:[$$104]  |PARTITIONED|
+              -- SORT_GROUP_BY[$$81]  |PARTITIONED|
                       {
                         -- AGGREGATE  |LOCAL|
                           -- NESTED_TUPLE_SOURCE  |LOCAL|
@@ -21,25 +21,25 @@
                         -- STREAM_SELECT  |PARTITIONED|
                           -- STREAM_PROJECT  |PARTITIONED|
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- PRE_CLUSTERED_GROUP_BY[$$79]  |PARTITIONED|
+                              -- PRE_CLUSTERED_GROUP_BY[$$101]  |PARTITIONED|
                                       {
                                         -- AGGREGATE  |LOCAL|
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                       }
-                                -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$79(ASC)] HASH:[$$79]  |PARTITIONED|
-                                  -- PRE_CLUSTERED_GROUP_BY[$$72]  |PARTITIONED|
+                                -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$101(ASC)] HASH:[$$101]  |PARTITIONED|
+                                  -- PRE_CLUSTERED_GROUP_BY[$$94]  |PARTITIONED|
                                           {
                                             -- AGGREGATE  |LOCAL|
                                               -- STREAM_SELECT  |LOCAL|
                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                                           }
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      -- STABLE_SORT [$$72(ASC)]  |PARTITIONED|
+                                      -- STABLE_SORT [$$94(ASC)]  |PARTITIONED|
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                           -- STREAM_PROJECT  |PARTITIONED|
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              -- HYBRID_HASH_JOIN [$$67][$$64]  |PARTITIONED|
-                                                -- HASH_PARTITION_EXCHANGE [$$67]  |PARTITIONED|
+                                              -- HYBRID_HASH_JOIN [$$89][$$86]  |PARTITIONED|
+                                                -- HASH_PARTITION_EXCHANGE [$$89]  |PARTITIONED|
                                                   -- ASSIGN  |PARTITIONED|
                                                     -- STREAM_PROJECT  |PARTITIONED|
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -66,7 +66,7 @@
                                                                                 -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                     -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                -- HASH_PARTITION_EXCHANGE [$$64]  |PARTITIONED|
+                                                -- HASH_PARTITION_EXCHANGE [$$86]  |PARTITIONED|
                                                   -- ASSIGN  |PARTITIONED|
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                       -- DATASOURCE_SCAN  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in.plan
index 8276df2..9efd93d 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in.plan
@@ -2,13 +2,13 @@
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
-        -- SORT_MERGE_EXCHANGE [$$26(ASC) ]  |PARTITIONED|
-          -- STABLE_SORT [$$26(ASC)]  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$29(ASC) ]  |PARTITIONED|
+          -- STABLE_SORT [$$29(ASC)]  |PARTITIONED|
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
               -- STREAM_PROJECT  |PARTITIONED|
                 -- STREAM_SELECT  |PARTITIONED|
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                    -- PRE_CLUSTERED_GROUP_BY[$$19]  |PARTITIONED|
+                    -- PRE_CLUSTERED_GROUP_BY[$$22]  |PARTITIONED|
                             {
                               -- AGGREGATE  |LOCAL|
                                 -- STREAM_SELECT  |LOCAL|
@@ -17,7 +17,7 @@
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                         -- STREAM_PROJECT  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            -- HYBRID_HASH_JOIN [$$19][$$7]  |PARTITIONED|
+                            -- HYBRID_HASH_JOIN [$$22][$$10]  |PARTITIONED|
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                 -- STREAM_PROJECT  |PARTITIONED|
                                   -- STREAM_SELECT  |PARTITIONED|
@@ -25,7 +25,7 @@
                                       -- DATASOURCE_SCAN  |PARTITIONED|
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                              -- HASH_PARTITION_EXCHANGE [$$7]  |PARTITIONED|
+                              -- HASH_PARTITION_EXCHANGE [$$10]  |PARTITIONED|
                                 -- STREAM_PROJECT  |PARTITIONED|
                                   -- ASSIGN  |PARTITIONED|
                                     -- STREAM_PROJECT  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in_correlated.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in_correlated.plan
index e0b4473..f967282 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in_correlated.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/in_correlated.plan
@@ -2,28 +2,35 @@
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
-        -- SORT_MERGE_EXCHANGE [$$31(ASC) ]  |PARTITIONED|
-          -- STABLE_SORT [$$31(ASC)]  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$34(ASC) ]  |PARTITIONED|
+          -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
               -- STREAM_PROJECT  |PARTITIONED|
                 -- STREAM_SELECT  |PARTITIONED|
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                    -- PRE_CLUSTERED_GROUP_BY[$$23]  |PARTITIONED|
+                    -- PRE_CLUSTERED_GROUP_BY[$$26]  |PARTITIONED|
                             {
                               -- AGGREGATE  |LOCAL|
                                 -- STREAM_SELECT  |LOCAL|
-                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                  -- UNNEST  |LOCAL|
+                                    -- MICRO_PRE_CLUSTERED_GROUP_BY[]  |LOCAL|
+                                            {
+                                              -- AGGREGATE  |LOCAL|
+                                                -- STREAM_SELECT  |LOCAL|
+                                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                            }
+                                      -- NESTED_TUPLE_SOURCE  |LOCAL|
                             }
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        -- HYBRID_HASH_JOIN [$$23][$$22]  |PARTITIONED|
+                        -- HYBRID_HASH_JOIN [$$26][$$25]  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            -- STREAM_PROJECT  |PARTITIONED|
-                              -- STREAM_SELECT  |PARTITIONED|
+                            -- STREAM_SELECT  |PARTITIONED|
+                              -- ASSIGN  |PARTITIONED|
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                   -- DATASOURCE_SCAN  |PARTITIONED|
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                       -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                          -- HASH_PARTITION_EXCHANGE [$$22]  |PARTITIONED|
+                          -- HASH_PARTITION_EXCHANGE [$$25]  |PARTITIONED|
                             -- STREAM_PROJECT  |PARTITIONED|
                               -- ASSIGN  |PARTITIONED|
                                 -- STREAM_PROJECT  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/not_exists.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/not_exists.plan
index 2a9841f..14b3f08 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/not_exists.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/subquery/not_exists.plan
@@ -2,14 +2,14 @@
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
-        -- SORT_MERGE_EXCHANGE [$$8(ASC) ]  |PARTITIONED|
-          -- PRE_CLUSTERED_GROUP_BY[$$83]  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$31(ASC) ]  |PARTITIONED|
+          -- PRE_CLUSTERED_GROUP_BY[$$105]  |PARTITIONED|
                   {
                     -- AGGREGATE  |LOCAL|
                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                   }
-            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$83(ASC)] HASH:[$$83]  |PARTITIONED|
-              -- SORT_GROUP_BY[$$60]  |PARTITIONED|
+            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$105(ASC)] HASH:[$$105]  |PARTITIONED|
+              -- SORT_GROUP_BY[$$82]  |PARTITIONED|
                       {
                         -- AGGREGATE  |LOCAL|
                           -- NESTED_TUPLE_SOURCE  |LOCAL|
@@ -21,25 +21,25 @@
                         -- STREAM_SELECT  |PARTITIONED|
                           -- STREAM_PROJECT  |PARTITIONED|
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- PRE_CLUSTERED_GROUP_BY[$$80]  |PARTITIONED|
+                              -- PRE_CLUSTERED_GROUP_BY[$$102]  |PARTITIONED|
                                       {
                                         -- AGGREGATE  |LOCAL|
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                       }
-                                -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$80(ASC)] HASH:[$$80]  |PARTITIONED|
-                                  -- PRE_CLUSTERED_GROUP_BY[$$73]  |PARTITIONED|
+                                -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$102(ASC)] HASH:[$$102]  |PARTITIONED|
+                                  -- PRE_CLUSTERED_GROUP_BY[$$95]  |PARTITIONED|
                                           {
                                             -- AGGREGATE  |LOCAL|
                                               -- STREAM_SELECT  |LOCAL|
                                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
                                           }
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      -- STABLE_SORT [$$73(ASC)]  |PARTITIONED|
+                                      -- STABLE_SORT [$$95(ASC)]  |PARTITIONED|
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                           -- STREAM_PROJECT  |PARTITIONED|
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              -- HYBRID_HASH_JOIN [$$68][$$65]  |PARTITIONED|
-                                                -- HASH_PARTITION_EXCHANGE [$$68]  |PARTITIONED|
+                                              -- HYBRID_HASH_JOIN [$$90][$$87]  |PARTITIONED|
+                                                -- HASH_PARTITION_EXCHANGE [$$90]  |PARTITIONED|
                                                   -- ASSIGN  |PARTITIONED|
                                                     -- STREAM_PROJECT  |PARTITIONED|
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -66,7 +66,7 @@
                                                                                 -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                     -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                -- HASH_PARTITION_EXCHANGE [$$65]  |PARTITIONED|
+                                                -- HASH_PARTITION_EXCHANGE [$$87]  |PARTITIONED|
                                                   -- ASSIGN  |PARTITIONED|
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                       -- DATASOURCE_SCAN  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q12_shipping.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q12_shipping.plan
index 7c1af83..754e03b 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q12_shipping.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/tpch/q12_shipping.plan
@@ -2,14 +2,14 @@
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
     -- STREAM_PROJECT  |PARTITIONED|
       -- ASSIGN  |PARTITIONED|
-        -- SORT_MERGE_EXCHANGE [$$3(ASC) ]  |PARTITIONED|
-          -- PRE_CLUSTERED_GROUP_BY[$$94]  |PARTITIONED|
+        -- SORT_MERGE_EXCHANGE [$$12(ASC) ]  |PARTITIONED|
+          -- PRE_CLUSTERED_GROUP_BY[$$104]  |PARTITIONED|
                   {
                     -- AGGREGATE  |LOCAL|
                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                   }
-            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$94(ASC)] HASH:[$$94]  |PARTITIONED|
-              -- SORT_GROUP_BY[$$76]  |PARTITIONED|
+            -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$104(ASC)] HASH:[$$104]  |PARTITIONED|
+              -- SORT_GROUP_BY[$$86]  |PARTITIONED|
                       {
                         -- AGGREGATE  |LOCAL|
                           -- NESTED_TUPLE_SOURCE  |LOCAL|
@@ -17,15 +17,15 @@
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                   -- STREAM_PROJECT  |PARTITIONED|
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      -- HYBRID_HASH_JOIN [$$83][$$76]  |PARTITIONED|
-                        -- HASH_PARTITION_EXCHANGE [$$83]  |PARTITIONED|
+                      -- HYBRID_HASH_JOIN [$$93][$$86]  |PARTITIONED|
+                        -- HASH_PARTITION_EXCHANGE [$$93]  |PARTITIONED|
                           -- UNNEST  |UNPARTITIONED|
                             -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
-                        -- HASH_PARTITION_EXCHANGE [$$76]  |PARTITIONED|
+                        -- HASH_PARTITION_EXCHANGE [$$86]  |PARTITIONED|
                           -- STREAM_PROJECT  |PARTITIONED|
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- HYBRID_HASH_JOIN [$$85][$$80]  |PARTITIONED|
-                                -- HASH_PARTITION_EXCHANGE [$$85]  |PARTITIONED|
+                              -- HYBRID_HASH_JOIN [$$95][$$90]  |PARTITIONED|
+                                -- HASH_PARTITION_EXCHANGE [$$95]  |PARTITIONED|
                                   -- STREAM_PROJECT  |PARTITIONED|
                                     -- STREAM_SELECT  |PARTITIONED|
                                       -- ASSIGN  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-2.plan
index 28c4ffd..80014c7 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-2.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-2.plan
@@ -4,7 +4,7 @@
       -- ASSIGN  |PARTITIONED|
         -- STREAM_PROJECT  |PARTITIONED|
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            -- HYBRID_HASH_JOIN [$$33][$$48]  |PARTITIONED|
+            -- HYBRID_HASH_JOIN [$$34][$$49]  |PARTITIONED|
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                 -- STREAM_PROJECT  |PARTITIONED|
                   -- ASSIGN  |PARTITIONED|
@@ -12,22 +12,22 @@
                       -- DATASOURCE_SCAN  |PARTITIONED|
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-              -- HASH_PARTITION_EXCHANGE [$$48]  |PARTITIONED|
+              -- HASH_PARTITION_EXCHANGE [$$49]  |PARTITIONED|
                 -- NESTED_LOOP  |PARTITIONED|
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                     -- STREAM_PROJECT  |PARTITIONED|
                       -- STREAM_SELECT  |PARTITIONED|
                         -- STREAM_PROJECT  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            -- PRE_CLUSTERED_GROUP_BY[$$34, $$47]  |PARTITIONED|
+                            -- PRE_CLUSTERED_GROUP_BY[$$35, $$48]  |PARTITIONED|
                                     {
                                       -- AGGREGATE  |LOCAL|
                                         -- STREAM_SELECT  |LOCAL|
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                     }
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                -- STABLE_SORT [$$34(ASC), $$47(ASC)]  |PARTITIONED|
-                                  -- HASH_PARTITION_EXCHANGE [$$34, $$47]  |PARTITIONED|
+                                -- STABLE_SORT [$$35(ASC), $$48(ASC)]  |PARTITIONED|
+                                  -- HASH_PARTITION_EXCHANGE [$$35, $$48]  |PARTITIONED|
                                     -- STREAM_PROJECT  |PARTITIONED|
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                         -- NESTED_LOOP  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-recursive-2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-recursive-2.plan
index 525500d..b1998f3 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-recursive-2.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-recursive-2.plan
@@ -4,7 +4,7 @@
       -- ASSIGN  |PARTITIONED|
         -- STREAM_PROJECT  |PARTITIONED|
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            -- HYBRID_HASH_JOIN [$$56][$$63]  |PARTITIONED|
+            -- HYBRID_HASH_JOIN [$$57][$$64]  |PARTITIONED|
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                 -- STREAM_PROJECT  |PARTITIONED|
                   -- ASSIGN  |PARTITIONED|
@@ -12,22 +12,22 @@
                       -- DATASOURCE_SCAN  |PARTITIONED|
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-              -- HASH_PARTITION_EXCHANGE [$$63]  |PARTITIONED|
+              -- HASH_PARTITION_EXCHANGE [$$64]  |PARTITIONED|
                 -- NESTED_LOOP  |PARTITIONED|
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                     -- STREAM_PROJECT  |PARTITIONED|
                       -- STREAM_SELECT  |PARTITIONED|
                         -- STREAM_PROJECT  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            -- PRE_CLUSTERED_GROUP_BY[$$43, $$62]  |PARTITIONED|
+                            -- PRE_CLUSTERED_GROUP_BY[$$44, $$63]  |PARTITIONED|
                                     {
                                       -- AGGREGATE  |LOCAL|
                                         -- STREAM_SELECT  |LOCAL|
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                     }
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                -- STABLE_SORT [$$43(ASC), $$62(ASC)]  |PARTITIONED|
-                                  -- HASH_PARTITION_EXCHANGE [$$43, $$62]  |PARTITIONED|
+                                -- STABLE_SORT [$$44(ASC), $$63(ASC)]  |PARTITIONED|
+                                  -- HASH_PARTITION_EXCHANGE [$$44, $$63]  |PARTITIONED|
                                     -- STREAM_PROJECT  |PARTITIONED|
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                         -- NESTED_LOOP  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-recursive.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-recursive.plan
index b429c28..62352d7 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-recursive.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017-recursive.plan
@@ -4,7 +4,7 @@
       -- ASSIGN  |PARTITIONED|
         -- STREAM_PROJECT  |PARTITIONED|
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            -- HYBRID_HASH_JOIN [$$52][$$58]  |PARTITIONED|
+            -- HYBRID_HASH_JOIN [$$53][$$59]  |PARTITIONED|
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                 -- STREAM_PROJECT  |PARTITIONED|
                   -- ASSIGN  |PARTITIONED|
@@ -17,22 +17,22 @@
                                 -- DATASOURCE_SCAN  |PARTITIONED|
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                     -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-              -- HASH_PARTITION_EXCHANGE [$$58]  |PARTITIONED|
+              -- HASH_PARTITION_EXCHANGE [$$59]  |PARTITIONED|
                 -- NESTED_LOOP  |PARTITIONED|
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                     -- STREAM_PROJECT  |PARTITIONED|
                       -- STREAM_SELECT  |PARTITIONED|
                         -- STREAM_PROJECT  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            -- PRE_CLUSTERED_GROUP_BY[$$41, $$57]  |PARTITIONED|
+                            -- PRE_CLUSTERED_GROUP_BY[$$42, $$58]  |PARTITIONED|
                                     {
                                       -- AGGREGATE  |LOCAL|
                                         -- STREAM_SELECT  |LOCAL|
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                     }
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                -- STABLE_SORT [$$41(ASC), $$57(ASC)]  |PARTITIONED|
-                                  -- HASH_PARTITION_EXCHANGE [$$41, $$57]  |PARTITIONED|
+                                -- STABLE_SORT [$$42(ASC), $$58(ASC)]  |PARTITIONED|
+                                  -- HASH_PARTITION_EXCHANGE [$$42, $$58]  |PARTITIONED|
                                     -- STREAM_PROJECT  |PARTITIONED|
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                         -- NESTED_LOOP  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017.plan
index 929d3da..2697384 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1017.plan
@@ -4,7 +4,7 @@
       -- ASSIGN  |PARTITIONED|
         -- STREAM_PROJECT  |PARTITIONED|
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            -- HYBRID_HASH_JOIN [$$30][$$42]  |PARTITIONED|
+            -- HYBRID_HASH_JOIN [$$31][$$43]  |PARTITIONED|
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                 -- STREAM_PROJECT  |PARTITIONED|
                   -- ASSIGN  |PARTITIONED|
@@ -12,26 +12,26 @@
                       -- DATASOURCE_SCAN  |PARTITIONED|
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-              -- HASH_PARTITION_EXCHANGE [$$42]  |PARTITIONED|
+              -- HASH_PARTITION_EXCHANGE [$$43]  |PARTITIONED|
                 -- NESTED_LOOP  |PARTITIONED|
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                     -- STREAM_PROJECT  |PARTITIONED|
                       -- STREAM_SELECT  |PARTITIONED|
                         -- STREAM_PROJECT  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            -- PRE_CLUSTERED_GROUP_BY[$$31, $$41]  |PARTITIONED|
+                            -- PRE_CLUSTERED_GROUP_BY[$$32, $$42]  |PARTITIONED|
                                     {
                                       -- AGGREGATE  |LOCAL|
                                         -- STREAM_SELECT  |LOCAL|
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                     }
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                -- STABLE_SORT [$$31(ASC), $$41(ASC)]  |PARTITIONED|
-                                  -- HASH_PARTITION_EXCHANGE [$$31, $$41]  |PARTITIONED|
+                                -- STABLE_SORT [$$32(ASC), $$42(ASC)]  |PARTITIONED|
+                                  -- HASH_PARTITION_EXCHANGE [$$32, $$42]  |PARTITIONED|
                                     -- STREAM_PROJECT  |PARTITIONED|
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        -- HYBRID_HASH_JOIN [$$38][$$34]  |PARTITIONED|
-                                          -- HASH_PARTITION_EXCHANGE [$$38]  |PARTITIONED|
+                                        -- HYBRID_HASH_JOIN [$$39][$$35]  |PARTITIONED|
+                                          -- HASH_PARTITION_EXCHANGE [$$39]  |PARTITIONED|
                                             -- NESTED_LOOP  |PARTITIONED|
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                 -- STREAM_PROJECT  |PARTITIONED|
@@ -46,7 +46,7 @@
                                                     -- DATASOURCE_SCAN  |PARTITIONED|
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                         -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                          -- HASH_PARTITION_EXCHANGE [$$34]  |PARTITIONED|
+                                          -- HASH_PARTITION_EXCHANGE [$$35]  |PARTITIONED|
                                             -- STREAM_PROJECT  |PARTITIONED|
                                               -- ASSIGN  |PARTITIONED|
                                                 -- STREAM_PROJECT  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1018.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1018.plan
index d7b279e..3eb81d9 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1018.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1018.plan
@@ -4,46 +4,46 @@
       -- ASSIGN  |PARTITIONED|
         -- STREAM_PROJECT  |PARTITIONED|
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            -- HYBRID_HASH_JOIN [$$34][$$47]  |PARTITIONED|
+            -- HYBRID_HASH_JOIN [$$35][$$48]  |PARTITIONED|
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                 -- STREAM_PROJECT  |PARTITIONED|
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                     -- DATASOURCE_SCAN  |PARTITIONED|
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                         -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-              -- HASH_PARTITION_EXCHANGE [$$47]  |PARTITIONED|
+              -- HASH_PARTITION_EXCHANGE [$$48]  |PARTITIONED|
                 -- STREAM_PROJECT  |PARTITIONED|
                   -- ASSIGN  |PARTITIONED|
                     -- STREAM_PROJECT  |PARTITIONED|
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        -- PRE_CLUSTERED_GROUP_BY[$$51, $$24, $$52]  |PARTITIONED|
+                        -- PRE_CLUSTERED_GROUP_BY[$$52, $$24, $$53]  |PARTITIONED|
                                 {
                                   -- AGGREGATE  |LOCAL|
                                     -- STREAM_SELECT  |LOCAL|
                                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                                 }
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            -- STABLE_SORT [$$51(ASC), $$24(ASC), $$52(ASC)]  |PARTITIONED|
-                              -- HASH_PARTITION_EXCHANGE [$$51, $$24, $$52]  |PARTITIONED|
+                            -- STABLE_SORT [$$52(ASC), $$24(ASC), $$53(ASC)]  |PARTITIONED|
+                              -- HASH_PARTITION_EXCHANGE [$$52, $$24, $$53]  |PARTITIONED|
                                 -- STREAM_PROJECT  |PARTITIONED|
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                     -- NESTED_LOOP  |PARTITIONED|
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                         -- STREAM_SELECT  |PARTITIONED|
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            -- PRE_CLUSTERED_GROUP_BY[$$35, $$46]  |PARTITIONED|
+                                            -- PRE_CLUSTERED_GROUP_BY[$$36, $$47]  |PARTITIONED|
                                                     {
                                                       -- AGGREGATE  |LOCAL|
                                                         -- STREAM_SELECT  |LOCAL|
                                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                     }
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                -- STABLE_SORT [$$35(ASC), $$46(ASC)]  |PARTITIONED|
-                                                  -- HASH_PARTITION_EXCHANGE [$$35, $$46]  |PARTITIONED|
+                                                -- STABLE_SORT [$$36(ASC), $$47(ASC)]  |PARTITIONED|
+                                                  -- HASH_PARTITION_EXCHANGE [$$36, $$47]  |PARTITIONED|
                                                     -- STREAM_PROJECT  |PARTITIONED|
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        -- HYBRID_HASH_JOIN [$$44][$$38]  |PARTITIONED|
-                                                          -- HASH_PARTITION_EXCHANGE [$$44]  |PARTITIONED|
+                                                        -- HYBRID_HASH_JOIN [$$45][$$39]  |PARTITIONED|
+                                                          -- HASH_PARTITION_EXCHANGE [$$45]  |PARTITIONED|
                                                             -- NESTED_LOOP  |PARTITIONED|
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                 -- STREAM_PROJECT  |PARTITIONED|
@@ -59,7 +59,7 @@
                                                                       -- DATASOURCE_SCAN  |PARTITIONED|
                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                          -- HASH_PARTITION_EXCHANGE [$$38]  |PARTITIONED|
+                                                          -- HASH_PARTITION_EXCHANGE [$$39]  |PARTITIONED|
                                                             -- STREAM_PROJECT  |PARTITIONED|
                                                               -- ASSIGN  |PARTITIONED|
                                                                 -- STREAM_PROJECT  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1019.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1019.plan
index 5b2405b..b910acf 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1019.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1019.plan
@@ -2,7 +2,7 @@
   -- STREAM_PROJECT  |PARTITIONED|
     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
       -- INSERT_DELETE  |PARTITIONED|
-        -- HASH_PARTITION_EXCHANGE [$$34]  |PARTITIONED|
+        -- HASH_PARTITION_EXCHANGE [$$35]  |PARTITIONED|
           -- ASSIGN  |PARTITIONED|
             -- STREAM_PROJECT  |PARTITIONED|
               -- ASSIGN  |PARTITIONED|
@@ -12,46 +12,46 @@
                       -- ASSIGN  |PARTITIONED|
                         -- STREAM_PROJECT  |PARTITIONED|
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            -- HYBRID_HASH_JOIN [$$38][$$51]  |PARTITIONED|
+                            -- HYBRID_HASH_JOIN [$$39][$$52]  |PARTITIONED|
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                 -- STREAM_PROJECT  |PARTITIONED|
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                     -- DATASOURCE_SCAN  |PARTITIONED|
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                         -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                              -- HASH_PARTITION_EXCHANGE [$$51]  |PARTITIONED|
+                              -- HASH_PARTITION_EXCHANGE [$$52]  |PARTITIONED|
                                 -- STREAM_PROJECT  |PARTITIONED|
                                   -- ASSIGN  |PARTITIONED|
                                     -- STREAM_PROJECT  |PARTITIONED|
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        -- PRE_CLUSTERED_GROUP_BY[$$56, $$24, $$55]  |PARTITIONED|
+                                        -- PRE_CLUSTERED_GROUP_BY[$$57, $$24, $$56]  |PARTITIONED|
                                                 {
                                                   -- AGGREGATE  |LOCAL|
                                                     -- STREAM_SELECT  |LOCAL|
                                                       -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                 }
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            -- STABLE_SORT [$$56(ASC), $$24(ASC), $$55(ASC)]  |PARTITIONED|
-                                              -- HASH_PARTITION_EXCHANGE [$$56, $$24, $$55]  |PARTITIONED|
+                                            -- STABLE_SORT [$$57(ASC), $$24(ASC), $$56(ASC)]  |PARTITIONED|
+                                              -- HASH_PARTITION_EXCHANGE [$$57, $$24, $$56]  |PARTITIONED|
                                                 -- STREAM_PROJECT  |PARTITIONED|
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                     -- NESTED_LOOP  |PARTITIONED|
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                         -- STREAM_SELECT  |PARTITIONED|
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            -- PRE_CLUSTERED_GROUP_BY[$$50, $$39]  |PARTITIONED|
+                                                            -- PRE_CLUSTERED_GROUP_BY[$$51, $$40]  |PARTITIONED|
                                                                     {
                                                                       -- AGGREGATE  |LOCAL|
                                                                         -- STREAM_SELECT  |LOCAL|
                                                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
                                                                     }
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                -- STABLE_SORT [$$50(ASC), $$39(ASC)]  |PARTITIONED|
-                                                                  -- HASH_PARTITION_EXCHANGE [$$50, $$39]  |PARTITIONED|
+                                                                -- STABLE_SORT [$$51(ASC), $$40(ASC)]  |PARTITIONED|
+                                                                  -- HASH_PARTITION_EXCHANGE [$$51, $$40]  |PARTITIONED|
                                                                     -- STREAM_PROJECT  |PARTITIONED|
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        -- HYBRID_HASH_JOIN [$$48][$$42]  |PARTITIONED|
-                                                                          -- HASH_PARTITION_EXCHANGE [$$48]  |PARTITIONED|
+                                                                        -- HYBRID_HASH_JOIN [$$49][$$43]  |PARTITIONED|
+                                                                          -- HASH_PARTITION_EXCHANGE [$$49]  |PARTITIONED|
                                                                             -- NESTED_LOOP  |PARTITIONED|
                                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                 -- STREAM_PROJECT  |PARTITIONED|
@@ -67,7 +67,7 @@
                                                                                       -- DATASOURCE_SCAN  |PARTITIONED|
                                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                          -- HASH_PARTITION_EXCHANGE [$$42]  |PARTITIONED|
+                                                                          -- HASH_PARTITION_EXCHANGE [$$43]  |PARTITIONED|
                                                                             -- STREAM_PROJECT  |PARTITIONED|
                                                                               -- ASSIGN  |PARTITIONED|
                                                                                 -- STREAM_PROJECT  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1020.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1020.plan
index 7eb6d35..5558ad4 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1020.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1020.plan
@@ -14,15 +14,15 @@
               -- STREAM_SELECT  |PARTITIONED|
                 -- STREAM_PROJECT  |PARTITIONED|
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                    -- PRE_CLUSTERED_GROUP_BY[$$32]  |PARTITIONED|
+                    -- PRE_CLUSTERED_GROUP_BY[$$33]  |PARTITIONED|
                             {
                               -- AGGREGATE  |LOCAL|
                                 -- STREAM_SELECT  |LOCAL|
                                   -- NESTED_TUPLE_SOURCE  |LOCAL|
                             }
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        -- STABLE_SORT [$$32(ASC)]  |PARTITIONED|
-                          -- HASH_PARTITION_EXCHANGE [$$32]  |PARTITIONED|
+                        -- STABLE_SORT [$$33(ASC)]  |PARTITIONED|
+                          -- HASH_PARTITION_EXCHANGE [$$33]  |PARTITIONED|
                             -- STREAM_PROJECT  |PARTITIONED|
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                 -- NESTED_LOOP  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-1.plan
index 3664ed8..99240dc 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-1.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-1.plan
@@ -23,25 +23,19 @@
                                 -- ASSIGN  |UNPARTITIONED|
                                   -- STREAM_PROJECT  |UNPARTITIONED|
                                     -- UNNEST  |UNPARTITIONED|
-                                      -- STREAM_PROJECT  |UNPARTITIONED|
-                                        -- SUBPLAN  |UNPARTITIONED|
-                                                {
-                                                  -- ASSIGN  |UNPARTITIONED|
-                                                    -- SUBPLAN  |UNPARTITIONED|
-                                                            {
-                                                              -- AGGREGATE  |UNPARTITIONED|
-                                                                -- STREAM_SELECT  |UNPARTITIONED|
-                                                                  -- UNNEST  |UNPARTITIONED|
-                                                                    -- SUBPLAN  |UNPARTITIONED|
-                                                                            {
-                                                                              -- AGGREGATE  |UNPARTITIONED|
-                                                                                -- IN_MEMORY_STABLE_SORT [$$21(ASC)]  |UNPARTITIONED|
-                                                                                  -- UNNEST  |UNPARTITIONED|
-                                                                                    -- NESTED_TUPLE_SOURCE  |UNPARTITIONED|
-                                                                            }
+                                      -- SUBPLAN  |UNPARTITIONED|
+                                              {
+                                                -- AGGREGATE  |UNPARTITIONED|
+                                                  -- STREAM_SELECT  |UNPARTITIONED|
+                                                    -- UNNEST  |UNPARTITIONED|
+                                                      -- SUBPLAN  |UNPARTITIONED|
+                                                              {
+                                                                -- AGGREGATE  |UNPARTITIONED|
+                                                                  -- IN_MEMORY_STABLE_SORT [$$21(ASC)]  |UNPARTITIONED|
+                                                                    -- UNNEST  |UNPARTITIONED|
                                                                       -- NESTED_TUPLE_SOURCE  |UNPARTITIONED|
-                                                            }
-                                                      -- NESTED_TUPLE_SOURCE  |UNPARTITIONED|
-                                                }
-                                          -- ASSIGN  |UNPARTITIONED|
-                                            -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
+                                                              }
+                                                        -- NESTED_TUPLE_SOURCE  |UNPARTITIONED|
+                                              }
+                                        -- ASSIGN  |UNPARTITIONED|
+                                          -- EMPTY_TUPLE_SOURCE  |UNPARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-2.plan
index caf4c48..aa22db0 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-2.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/udfs/query-ASTERIXDB-1308-2.plan
@@ -5,73 +5,56 @@
         -- STREAM_PROJECT  |PARTITIONED|
           -- SUBPLAN  |PARTITIONED|
                   {
-                    -- SUBPLAN  |LOCAL|
-                            {
-                              -- SUBPLAN  |LOCAL|
-                                      {
-                                        -- ASSIGN  |LOCAL|
-                                          -- SUBPLAN  |LOCAL|
-                                                  {
-                                                    -- AGGREGATE  |LOCAL|
-                                                      -- STREAM_SELECT  |LOCAL|
-                                                        -- ASSIGN  |LOCAL|
-                                                          -- UNNEST  |LOCAL|
-                                                            -- SUBPLAN  |LOCAL|
-                                                                    {
-                                                                      -- AGGREGATE  |LOCAL|
-                                                                        -- IN_MEMORY_STABLE_SORT [$$38(ASC)]  |LOCAL|
-                                                                          -- UNNEST  |LOCAL|
-                                                                            -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                                    }
-                                                              -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                  }
+                    -- AGGREGATE  |LOCAL|
+                      -- STREAM_SELECT  |LOCAL|
+                        -- ASSIGN  |LOCAL|
+                          -- UNNEST  |LOCAL|
+                            -- SUBPLAN  |LOCAL|
+                                    {
+                                      -- AGGREGATE  |LOCAL|
+                                        -- IN_MEMORY_STABLE_SORT [$$38(ASC)]  |LOCAL|
+                                          -- UNNEST  |LOCAL|
                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                      }
-                                -- SUBPLAN  |LOCAL|
-                                        {
-                                          -- AGGREGATE  |LOCAL|
-                                            -- IN_MEMORY_STABLE_SORT [$$98(ASC)]  |LOCAL|
-                                              -- ASSIGN  |LOCAL|
-                                                -- UNNEST  |LOCAL|
-                                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                        }
-                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
-                            }
-                      -- SUBPLAN  |LOCAL|
-                              {
-                                -- ASSIGN  |LOCAL|
+                                    }
+                              -- NESTED_TUPLE_SOURCE  |LOCAL|
+                  }
+            -- STREAM_PROJECT  |PARTITIONED|
+              -- SUBPLAN  |PARTITIONED|
+                      {
+                        -- AGGREGATE  |LOCAL|
+                          -- IN_MEMORY_STABLE_SORT [$$98(ASC)]  |LOCAL|
+                            -- ASSIGN  |LOCAL|
+                              -- UNNEST  |LOCAL|
+                                -- NESTED_TUPLE_SOURCE  |LOCAL|
+                      }
+                -- SUBPLAN  |PARTITIONED|
+                        {
+                          -- AGGREGATE  |LOCAL|
+                            -- STREAM_SELECT  |LOCAL|
+                              -- ASSIGN  |LOCAL|
+                                -- UNNEST  |LOCAL|
                                   -- SUBPLAN  |LOCAL|
                                           {
                                             -- AGGREGATE  |LOCAL|
-                                              -- STREAM_SELECT  |LOCAL|
-                                                -- ASSIGN  |LOCAL|
-                                                  -- UNNEST  |LOCAL|
-                                                    -- SUBPLAN  |LOCAL|
-                                                            {
-                                                              -- AGGREGATE  |LOCAL|
-                                                                -- IN_MEMORY_STABLE_SORT [$$31(ASC)]  |LOCAL|
-                                                                  -- UNNEST  |LOCAL|
-                                                                    -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                            }
-                                                      -- NESTED_TUPLE_SOURCE  |LOCAL|
+                                              -- IN_MEMORY_STABLE_SORT [$$31(ASC)]  |LOCAL|
+                                                -- UNNEST  |LOCAL|
+                                                  -- NESTED_TUPLE_SOURCE  |LOCAL|
                                           }
                                     -- NESTED_TUPLE_SOURCE  |LOCAL|
-                              }
-                        -- NESTED_TUPLE_SOURCE  |LOCAL|
-                  }
-            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              -- PRE_CLUSTERED_GROUP_BY[$$94, $$95, $$96, $$97]  |PARTITIONED|
-                      {
-                        -- AGGREGATE  |LOCAL|
-                          -- NESTED_TUPLE_SOURCE  |LOCAL|
-                      }
-                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  -- STABLE_SORT [$$94(ASC), $$95(ASC), $$96(ASC), $$97(ASC)]  |PARTITIONED|
-                    -- HASH_PARTITION_EXCHANGE [$$94, $$95, $$96, $$97]  |PARTITIONED|
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        -- ASSIGN  |PARTITIONED|
-                          -- STREAM_PROJECT  |PARTITIONED|
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              -- DATASOURCE_SCAN  |PARTITIONED|
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                        }
+                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                    -- PRE_CLUSTERED_GROUP_BY[$$94, $$95, $$96, $$97]  |PARTITIONED|
+                            {
+                              -- AGGREGATE  |LOCAL|
+                                -- NESTED_TUPLE_SOURCE  |LOCAL|
+                            }
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        -- STABLE_SORT [$$94(ASC), $$95(ASC), $$96(ASC), $$97(ASC)]  |PARTITIONED|
+                          -- HASH_PARTITION_EXCHANGE [$$94, $$95, $$96, $$97]  |PARTITIONED|
+                            -- STREAM_PROJECT  |PARTITIONED|
+                              -- ASSIGN  |PARTITIONED|
+                                -- STREAM_PROJECT  |PARTITIONED|
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    -- DATASOURCE_SCAN  |PARTITIONED|
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/count-tweets.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/count-tweets.ast
index a727fb4..4208580 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/count-tweets.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/count-tweets.ast
@@ -61,8 +61,7 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    tokens:=Variable [ Name=$tokens ]
-    token:=Variable [ Name=$token ]
     t:=Variable [ Name=$t ]
+    token:=Variable [ Name=$token ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/denorm-cust-order.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/denorm-cust-order.ast
index 41092db..557eece 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/denorm-cust-order.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/denorm-cust-order.ast
@@ -102,7 +102,7 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    o:=Variable [ Name=$o ]
     c:=Variable [ Name=$c ]
+    o:=Variable [ Name=$o ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-dblp-csx.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-dblp-csx.ast
index 3ca4a03..3367a13 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-dblp-csx.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-dblp-csx.ast
@@ -172,16 +172,10 @@
   Variable [ Name=$idCSX ]
   GROUP AS Variable [ Name=#1 ]
   (
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    unrankedTokensCSX:=Variable [ Name=$unrankedTokensCSX ]
-    idCSX:=Variable [ Name=$idCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    unrankedTokensDBLP:=Variable [ Name=$unrankedTokensDBLP ]
-    idDBLP:=Variable [ Name=$idDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-phase1.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-phase1.ast
index b5e5161..2210b9c 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-phase1.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-phase1.ast
@@ -74,8 +74,8 @@
           Variable [ Name=$lottery_number ]
           GROUP AS Variable [ Name=#1 ]
           (
-            lottery_number:=Variable [ Name=$lottery_number ]
             user:=Variable [ Name=$user ]
+            lottery_number:=Variable [ Name=$lottery_number ]
           )
 
         Let Variable [ Name=$count ]
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-phase2-with-hints.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-phase2-with-hints.ast
index ee802a0..dabf888 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-phase2-with-hints.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/fj-phase2-with-hints.ast
@@ -73,10 +73,8 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            unrankedTokensDBLP:=Variable [ Name=$unrankedTokensDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/inlined_q18_large_volume_customer.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/inlined_q18_large_volume_customer.ast
index 72a1958..c503d72 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/inlined_q18_large_volume_customer.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/inlined_q18_large_volume_customer.ast
@@ -147,8 +147,6 @@
       GROUP AS Variable [ Name=#1 ]
       (
         l:=Variable [ Name=$l ]
-        o:=Variable [ Name=$o ]
-        c:=Variable [ Name=$c ]
       )
 
   )
@@ -241,10 +239,10 @@
   ]
   GROUP AS Variable [ Name=#2 ]
   (
-    l:=Variable [ Name=$l ]
-    t:=Variable [ Name=$t ]
-    o:=Variable [ Name=$o ]
     c:=Variable [ Name=$c ]
+    o:=Variable [ Name=$o ]
+    t:=Variable [ Name=$t ]
+    l:=Variable [ Name=$l ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/nest_aggregate.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/nest_aggregate.ast
index 951e744..d69ca94 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/nest_aggregate.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/nest_aggregate.ast
@@ -162,10 +162,8 @@
         ]
         GROUP AS Variable [ Name=#1 ]
         (
-          customer:=Variable [ Name=$customer ]
           orders:=Variable [ Name=$orders ]
-          sn:=Variable [ Name=$sn ]
-          nation:=Variable [ Name=$nation ]
+          customer:=Variable [ Name=$customer ]
         )
 
       Let Variable [ Name=$sum ]
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/orders-aggreg.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/orders-aggreg.ast
index 3f1faf2..91378e0 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/orders-aggreg.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/orders-aggreg.ast
@@ -23,17 +23,7 @@
     LiteralExpr [STRING] [ordpercust]
     :
     FunctionCall orders-aggreg.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=o
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$o ]
     ]
   )
   (
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q01_pricing_summary_report_nt.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q01_pricing_summary_report_nt.ast
index 1a91b41..d36738f 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q01_pricing_summary_report_nt.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q01_pricing_summary_report_nt.ast
@@ -188,17 +188,7 @@
     LiteralExpr [STRING] [count_order]
     :
     FunctionCall tpch.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=l
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$l ]
     ]
   )
 ]
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q03_shipping_priority.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q03_shipping_priority.ast
index 2a34cb7..041dfb7 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q03_shipping_priority.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q03_shipping_priority.ast
@@ -166,9 +166,9 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    l:=Variable [ Name=$l ]
-    o:=Variable [ Name=$o ]
     c:=Variable [ Name=$c ]
+    o:=Variable [ Name=$o ]
+    l:=Variable [ Name=$l ]
   )
 
 Let Variable [ Name=$revenue ]
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q05_local_supplier_volume.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q05_local_supplier_volume.ast
index f913928..4340fed 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q05_local_supplier_volume.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q05_local_supplier_volume.ast
@@ -388,8 +388,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    o1:=Variable [ Name=$o1 ]
     c:=Variable [ Name=$c ]
+    o1:=Variable [ Name=$o1 ]
   )
 
 Let Variable [ Name=$revenue ]
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q2.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q2.ast
index 37eefd4..1b01e10 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q2.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/q2.ast
@@ -85,9 +85,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    es:=Variable [ Name=$es ]
-    sponsor:=Variable [ Name=$sponsor ]
     event:=Variable [ Name=$event ]
+    sponsor:=Variable [ Name=$sponsor ]
   )
 
 Let Variable [ Name=$sig_sponsorship_count ]
@@ -95,9 +94,8 @@
   FunctionCall events.sql-count@1[
     (
       SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=es
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [es]
       ]
       ]
       FROM [        Variable [ Name=#1 ]
@@ -134,7 +132,9 @@
       )
     ]
     ]
-    FROM [      Variable [ Name=$es ]
+    FROM [      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [es]
+      ]
       AS Variable [ Name=$e ]
     ]
     Groupby
@@ -150,12 +150,6 @@
       GROUP AS Variable [ Name=#3 ]
       (
         e:=Variable [ Name=$e ]
-        sig_sponsorship_count:=Variable [ Name=$sig_sponsorship_count ]
-        es:=Variable [ Name=$es ]
-        event:=Variable [ Name=$event ]
-        sponsor:=Variable [ Name=$sponsor ]
-        sig_name:=Variable [ Name=$sig_name ]
-        #1:=Variable [ Name=#1 ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue550.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue550.ast
index f8988ad..e5a516d 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue550.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue550.ast
@@ -181,6 +181,5 @@
   GROUP AS Variable [ Name=#1 ]
   (
     s:=Variable [ Name=$s ]
-    sample:=Variable [ Name=$sample ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue562.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue562.ast
index 4025ed0..24cafba 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue562.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue562.ast
@@ -227,17 +227,7 @@
     LiteralExpr [STRING] [numcust]
     :
     FunctionCall tpch.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=ct
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$ct ]
     ]
   )
   (
@@ -302,7 +292,6 @@
   GROUP AS Variable [ Name=#1 ]
   (
     ct:=Variable [ Name=$ct ]
-    avg:=Variable [ Name=$avg ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue785.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue785.ast
index 31d5bbc..cf4c9c1 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue785.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/query-issue785.ast
@@ -179,10 +179,9 @@
       ]
       GROUP AS Variable [ Name=#1 ]
       (
-        orders:=Variable [ Name=$orders ]
-        customer:=Variable [ Name=$customer ]
         n:=Variable [ Name=$n ]
-        t:=Variable [ Name=$t ]
+        customer:=Variable [ Name=$customer ]
+        orders:=Variable [ Name=$orders ]
       )
 
     Let Variable [ Name=$sum ]
@@ -261,7 +260,5 @@
   GROUP AS Variable [ Name=#2 ]
   (
     x:=Variable [ Name=$x ]
-    X:=Variable [ Name=$X ]
-    t:=Variable [ Name=$t ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/split-materialization-above-join.ast b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/split-materialization-above-join.ast
index 7f7b2f3..b12ce2a 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/split-materialization-above-join.ast
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_parser_sqlpp/split-materialization-above-join.ast
@@ -60,7 +60,9 @@
         LiteralExpr [STRING] [sim]
         :
         IndexAccessor [
-          Variable [ Name=$sim ]
+          FunctionCall Metadata.dataset@1[
+            LiteralExpr [STRING] [sim]
+          ]
           Index:           LiteralExpr [LONG] [0]
         ]
       )
@@ -151,14 +153,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenLeft:=Variable [ Name=$lenLeft ]
-                prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-                paperRight:=Variable [ Name=$paperRight ]
-                prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
-                paperLeft:=Variable [ Name=$paperLeft ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -242,16 +238,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenRight:=Variable [ Name=$lenRight ]
-                tokensLeft:=Variable [ Name=$tokensLeft ]
-                lenLeft:=Variable [ Name=$lenLeft ]
-                prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-                paperRight:=Variable [ Name=$paperRight ]
-                prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
-                paperLeft:=Variable [ Name=$paperLeft ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -341,15 +329,10 @@
       ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensRight:=Variable [ Name=$tokensRight ]
-        lenRight:=Variable [ Name=$lenRight ]
-        tokensLeft:=Variable [ Name=$tokensLeft ]
-        lenLeft:=Variable [ Name=$lenLeft ]
-        prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-        paperRight:=Variable [ Name=$paperRight ]
-        prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
         paperLeft:=Variable [ Name=$paperLeft ]
+        prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
+        paperRight:=Variable [ Name=$paperRight ]
+        prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/2.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/2.ast
index a57de72..a5cdcdf 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/2.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/2.ast
@@ -52,9 +52,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    es:=Variable [ Name=$es ]
-    sponsor:=Variable [ Name=$sponsor ]
     event:=Variable [ Name=$event ]
+    sponsor:=Variable [ Name=$sponsor ]
   )
 
 Let Variable [ Name=$sig_sponsorship_count ]
@@ -62,9 +61,8 @@
   FunctionCall null.sql-count@1[
     (
       SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=es
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [es]
       ]
       ]
       FROM [        Variable [ Name=#1 ]
@@ -88,9 +86,8 @@
         FunctionCall null.sql-count@1[
           (
             SELECT ELEMENT [
-            FieldAccessor [
-              Variable [ Name=#4 ]
-              Field=es
+            FunctionCall Metadata.dataset@1[
+              LiteralExpr [STRING] [es]
             ]
             ]
             FROM [              Variable [ Name=#3 ]
@@ -101,7 +98,9 @@
       )
     ]
     ]
-    FROM [      Variable [ Name=$es ]
+    FROM [      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [es]
+      ]
       AS Variable [ Name=$e ]
     ]
     Groupby
@@ -117,12 +116,6 @@
       GROUP AS Variable [ Name=#3 ]
       (
         e:=Variable [ Name=$e ]
-        sig_sponsorship_count:=Variable [ Name=$sig_sponsorship_count ]
-        es:=Variable [ Name=$es ]
-        event:=Variable [ Name=$event ]
-        sponsor:=Variable [ Name=$sponsor ]
-        sig_name:=Variable [ Name=$sig_name ]
-        #1:=Variable [ Name=#1 ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/columnalias.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/columnalias.ast
index 14b5108..78d6362 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/columnalias.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/columnalias.ast
@@ -1,6 +1,18 @@
 Query:
 SELECT [
-Variable [ Name=$root ]
+FunctionCall null.SQRT@1[
+  OperatorExpr [
+    FieldAccessor [
+      Variable [ Name=$t ]
+      Field=a
+    ]
+    *
+    FieldAccessor [
+      Variable [ Name=$t ]
+      Field=b
+    ]
+  ]
+]
 root
 ]
 FROM [  FunctionCall Metadata.dataset@1[
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/columnalias3.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/columnalias3.ast
index cdd4653..056fe36 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/columnalias3.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/columnalias3.ast
@@ -4,7 +4,19 @@
   (
     LiteralExpr [STRING] [root]
     :
-    Variable [ Name=$root ]
+    FunctionCall null.SQRT@1[
+      OperatorExpr [
+        FieldAccessor [
+          Variable [ Name=$t ]
+          Field=a
+        ]
+        *
+        FieldAccessor [
+          Variable [ Name=$t ]
+          Field=b
+        ]
+      ]
+    ]
   )
 ]
 ]
diff --git a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR3.ast b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR3.ast
index f4fcf1f..9454ebc 100644
--- a/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR3.ast
+++ b/asterixdb/asterix-app/src/test/resources/parserts/results_parser_sqlpp/nestedFLWOGR3.ast
@@ -52,9 +52,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    es:=Variable [ Name=$es ]
-    sponsor:=Variable [ Name=$sponsor ]
     event:=Variable [ Name=$event ]
+    sponsor:=Variable [ Name=$sponsor ]
   )
 
 Let Variable [ Name=$sig_sponsorship_count ]
@@ -62,9 +61,8 @@
   FunctionCall null.sql-count@1[
     (
       SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=es
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [es]
       ]
       ]
       FROM [        Variable [ Name=#1 ]
@@ -88,9 +86,8 @@
         FunctionCall null.sql-count@1[
           (
             SELECT ELEMENT [
-            FieldAccessor [
-              Variable [ Name=#4 ]
-              Field=es
+            FunctionCall Metadata.dataset@1[
+              LiteralExpr [STRING] [es]
             ]
             ]
             FROM [              Variable [ Name=#3 ]
@@ -101,7 +98,9 @@
       )
     ]
     ]
-    FROM [      Variable [ Name=$es ]
+    FROM [      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [es]
+      ]
       AS Variable [ Name=$e ]
     ]
     Groupby
@@ -117,12 +116,6 @@
       GROUP AS Variable [ Name=#3 ]
       (
         e:=Variable [ Name=$e ]
-        sig_sponsorship_count:=Variable [ Name=$sig_sponsorship_count ]
-        es:=Variable [ Name=$es ]
-        event:=Variable [ Name=$event ]
-        sponsor:=Variable [ Name=$sponsor ]
-        sig_name:=Variable [ Name=$sig_name ]
-        #1:=Variable [ Name=#1 ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.1.ddl.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.1.ddl.aql
new file mode 100644
index 0000000..ed74a09
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.1.ddl.aql
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type account as open
+{ id: int32, sum:int32 }
+
+create dataset Accounts(account) primary key id;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.2.update.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.2.update.aql
new file mode 100644
index 0000000..477beec
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.2.update.aql
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+use dataverse test;
+
+insert into dataset Accounts(
+{"id": 1, "sum":100}
+)
+insert into dataset Accounts(
+{"id": 2, "sum":150}
+)
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.3.query.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.3.query.aql
new file mode 100644
index 0000000..70954bd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.3.query.aql
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+use dataverse test;
+
+for $x in range(1,2)
+return(
+     let $z:=(for $y in dataset Accounts where $y.id=$x return $y)
+     return {"x":$x, "z":$z}
+)
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-10/q2-10.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-10/q2-10.1.ddl.sqlpp
new file mode 100644
index 0000000..99eae31
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-10/q2-10.1.ddl.sqlpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+drop  dataverse test if exists;
+create  dataverse test;
+
+use test;
+
+
+create type test.AddressType as
+ closed {
+  street : string,
+  city : string,
+  zip : string,
+  latlong : point
+}
+
+create type test.EventType as
+ closed {
+  event_id : int64,
+  name : string,
+  location : AddressType?,
+  organizers : {{{
+          name : string
+      }
+}},
+  sponsoring_sigs : [{
+          sig_id : int64,
+          chapter_name : string
+      }
+],
+  interest_keywords : {{string}},
+  price : double?,
+  start_time : datetime,
+  end_time : datetime
+}
+
+create external  dataset Event(EventType) using localfs((`path`=`asterix_nc1://data/events/tiny/event.adm`),(`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-10/q2-10.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-10/q2-10.2.update.sqlpp
new file mode 100644
index 0000000..bd244d0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-10/q2-10.2.update.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-10/q2-10.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-10/q2-10.3.query.sqlpp
new file mode 100644
index 0000000..119f28b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-10/q2-10.3.query.sqlpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+
+USE test;
+
+// Tests references to a WITH binding variable in nested GROUP BY.
+WITH t AS 1
+
+SELECT sponsor.sig_id, COUNT(2 * t) total_count,
+       (
+         SELECT e.sponsor.chapter_name, COUNT(2 * t) AS escount
+         FROM es AS e
+         GROUP BY e.sponsor.chapter_name
+       ) chapter_breakdown
+FROM  Event,
+      Event.sponsoring_sigs AS sponsor
+GROUP BY sponsor.sig_id GROUP AS es
+ORDER BY total_count DESC
+LIMIT 5
+;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11/q2-11.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11/q2-11.1.ddl.sqlpp
new file mode 100644
index 0000000..99eae31
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11/q2-11.1.ddl.sqlpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+drop  dataverse test if exists;
+create  dataverse test;
+
+use test;
+
+
+create type test.AddressType as
+ closed {
+  street : string,
+  city : string,
+  zip : string,
+  latlong : point
+}
+
+create type test.EventType as
+ closed {
+  event_id : int64,
+  name : string,
+  location : AddressType?,
+  organizers : {{{
+          name : string
+      }
+}},
+  sponsoring_sigs : [{
+          sig_id : int64,
+          chapter_name : string
+      }
+],
+  interest_keywords : {{string}},
+  price : double?,
+  start_time : datetime,
+  end_time : datetime
+}
+
+create external  dataset Event(EventType) using localfs((`path`=`asterix_nc1://data/events/tiny/event.adm`),(`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11/q2-11.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11/q2-11.2.update.sqlpp
new file mode 100644
index 0000000..bd244d0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11/q2-11.2.update.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11/q2-11.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11/q2-11.3.query.sqlpp
new file mode 100644
index 0000000..0b90993
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11/q2-11.3.query.sqlpp
@@ -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.
+ */
+
+
+USE test;
+
+// Tests references to a WITH binding variable for a select query in nested GROUP BY.
+WITH t AS (
+   SELECT VALUE AVG(v)
+   FROM [1, 2, 3] v
+)[0]
+
+SELECT sponsor.sig_id, COUNT(2 * t) total_count,
+       (
+         SELECT e.sponsor.chapter_name, COUNT(2 * t) AS escount
+         FROM es AS e
+         GROUP BY e.sponsor.chapter_name
+       ) chapter_breakdown
+FROM  Event,
+      Event.sponsoring_sigs AS sponsor
+GROUP BY sponsor.sig_id GROUP AS es
+ORDER BY total_count DESC
+LIMIT 5
+;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-12/q2-12.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-12/q2-12.1.ddl.sqlpp
new file mode 100644
index 0000000..99eae31
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-12/q2-12.1.ddl.sqlpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+drop  dataverse test if exists;
+create  dataverse test;
+
+use test;
+
+
+create type test.AddressType as
+ closed {
+  street : string,
+  city : string,
+  zip : string,
+  latlong : point
+}
+
+create type test.EventType as
+ closed {
+  event_id : int64,
+  name : string,
+  location : AddressType?,
+  organizers : {{{
+          name : string
+      }
+}},
+  sponsoring_sigs : [{
+          sig_id : int64,
+          chapter_name : string
+      }
+],
+  interest_keywords : {{string}},
+  price : double?,
+  start_time : datetime,
+  end_time : datetime
+}
+
+create external  dataset Event(EventType) using localfs((`path`=`asterix_nc1://data/events/tiny/event.adm`),(`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-12/q2-12.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-12/q2-12.2.update.sqlpp
new file mode 100644
index 0000000..bd244d0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-12/q2-12.2.update.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-12/q2-12.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-12/q2-12.3.query.sqlpp
new file mode 100644
index 0000000..5210ced
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-12/q2-12.3.query.sqlpp
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+
+USE test;
+
+// Tests references to an outer scope variable in a nested global aggregate.
+WITH t AS (
+   SELECT VALUE AVG(v)
+   FROM [1, 2, 3] v
+)[0]
+
+SELECT sponsor.sig_id, COUNT(2 * t) total_count,
+       (
+         SELECT sponsor.sig_id, COUNT(e)
+         FROM es AS e
+       ) chapter_breakdown
+FROM  Event,
+      Event.sponsoring_sigs AS sponsor
+GROUP BY sponsor.sig_id GROUP AS es
+ORDER BY total_count DESC
+LIMIT 5
+;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2-negative/q2-2-negative.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2-negative/q2-2-negative.1.ddl.sqlpp
new file mode 100644
index 0000000..99eae31
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2-negative/q2-2-negative.1.ddl.sqlpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+drop  dataverse test if exists;
+create  dataverse test;
+
+use test;
+
+
+create type test.AddressType as
+ closed {
+  street : string,
+  city : string,
+  zip : string,
+  latlong : point
+}
+
+create type test.EventType as
+ closed {
+  event_id : int64,
+  name : string,
+  location : AddressType?,
+  organizers : {{{
+          name : string
+      }
+}},
+  sponsoring_sigs : [{
+          sig_id : int64,
+          chapter_name : string
+      }
+],
+  interest_keywords : {{string}},
+  price : double?,
+  start_time : datetime,
+  end_time : datetime
+}
+
+create external  dataset Event(EventType) using localfs((`path`=`asterix_nc1://data/events/tiny/event.adm`),(`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2-negative/q2-2-negative.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2-negative/q2-2-negative.2.update.sqlpp
new file mode 100644
index 0000000..bd244d0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2-negative/q2-2-negative.2.update.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2-negative/q2-2-negative.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2-negative/q2-2-negative.3.query.sqlpp
new file mode 100644
index 0000000..8a5d32d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2-negative/q2-2-negative.3.query.sqlpp
@@ -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.
+ */
+
+/*
+ * This query is a negative test for default group variable's fields.
+ */
+
+use test;
+
+
+select element {'sig_id':sig_id,'total_count':sig_sponsorship_count,'chapter_breakdown':by_chapter}
+from  Event as event,
+      event.sponsoring_sigs as sponsor
+let  e = {'event':event,'sponsor':sponsor}
+group by sponsor.sig_id as sig_id
+let  sig_sponsorship_count = count(1),
+      by_chapter = (
+      select element {'chapter_name':chapter_name,'escount':count(e)}
+      from  e as e
+      group by e.sponsor.chapter_name as chapter_name
+  )
+order by sig_sponsorship_count desc
+limit 5
+;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2/q2-2.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2/q2-2.3.query.sqlpp
index 307ad80..bf968cc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2/q2-2.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-2/q2-2.3.query.sqlpp
@@ -27,10 +27,9 @@
 select element {'sig_id':sig_id,'total_count':sig_sponsorship_count,'chapter_breakdown':by_chapter}
 from  Event as event,
       event.sponsoring_sigs as sponsor
-with  e as {'event':event,'sponsor':sponsor}
-group by sponsor.sig_id as sig_id
-with  sig_sponsorship_count as count(e),
-      by_chapter as (
+group by sponsor.sig_id as sig_id group as e
+let  sig_sponsorship_count = count(1),
+      by_chapter = (
       select element {'chapter_name':chapter_name,'escount':count(e)}
       from  e as e
       group by e.sponsor.chapter_name as chapter_name
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-7/q2-7.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-7/q2-7.1.ddl.sqlpp
new file mode 100644
index 0000000..99eae31
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-7/q2-7.1.ddl.sqlpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+drop  dataverse test if exists;
+create  dataverse test;
+
+use test;
+
+
+create type test.AddressType as
+ closed {
+  street : string,
+  city : string,
+  zip : string,
+  latlong : point
+}
+
+create type test.EventType as
+ closed {
+  event_id : int64,
+  name : string,
+  location : AddressType?,
+  organizers : {{{
+          name : string
+      }
+}},
+  sponsoring_sigs : [{
+          sig_id : int64,
+          chapter_name : string
+      }
+],
+  interest_keywords : {{string}},
+  price : double?,
+  start_time : datetime,
+  end_time : datetime
+}
+
+create external  dataset Event(EventType) using localfs((`path`=`asterix_nc1://data/events/tiny/event.adm`),(`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-7/q2-7.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-7/q2-7.2.update.sqlpp
new file mode 100644
index 0000000..bd244d0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-7/q2-7.2.update.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-7/q2-7.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-7/q2-7.3.query.sqlpp
new file mode 100644
index 0000000..92039e0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-7/q2-7.3.query.sqlpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+
+USE test;
+
+// Tests nested SELECT * for nested GROUP BY.
+SELECT sponsor.sig_id, COUNT(1) total_count,
+       (
+         SELECT *
+         FROM es AS e
+         GROUP BY e.sponsor.chapter_name
+       ) chapter_breakdown
+FROM  Event,
+      Event.sponsoring_sigs AS sponsor
+GROUP BY sponsor.sig_id GROUP AS es
+ORDER BY total_count DESC
+LIMIT 5
+;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-8/q2-8.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-8/q2-8.1.ddl.sqlpp
new file mode 100644
index 0000000..99eae31
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-8/q2-8.1.ddl.sqlpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+drop  dataverse test if exists;
+create  dataverse test;
+
+use test;
+
+
+create type test.AddressType as
+ closed {
+  street : string,
+  city : string,
+  zip : string,
+  latlong : point
+}
+
+create type test.EventType as
+ closed {
+  event_id : int64,
+  name : string,
+  location : AddressType?,
+  organizers : {{{
+          name : string
+      }
+}},
+  sponsoring_sigs : [{
+          sig_id : int64,
+          chapter_name : string
+      }
+],
+  interest_keywords : {{string}},
+  price : double?,
+  start_time : datetime,
+  end_time : datetime
+}
+
+create external  dataset Event(EventType) using localfs((`path`=`asterix_nc1://data/events/tiny/event.adm`),(`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-8/q2-8.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-8/q2-8.2.update.sqlpp
new file mode 100644
index 0000000..bd244d0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-8/q2-8.2.update.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-8/q2-8.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-8/q2-8.3.query.sqlpp
new file mode 100644
index 0000000..28a3317
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-8/q2-8.3.query.sqlpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+
+USE test;
+
+// Tests the case that a GROUP BY key expression appears in an aggregation function.
+SELECT sponsor.sig_id, COUNT(sponsor.sig_id) total_count,
+       (
+         SELECT e.sponsor.chapter_name, COUNT(e.sponsor.chapter_name) AS escount
+         FROM es AS e
+         GROUP BY e.sponsor.chapter_name
+       ) chapter_breakdown
+FROM  Event,
+      Event.sponsoring_sigs AS sponsor
+GROUP BY sponsor.sig_id GROUP AS es
+ORDER BY total_count DESC
+LIMIT 5
+;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-9/q2-9.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-9/q2-9.1.ddl.sqlpp
new file mode 100644
index 0000000..99eae31
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-9/q2-9.1.ddl.sqlpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+drop  dataverse test if exists;
+create  dataverse test;
+
+use test;
+
+
+create type test.AddressType as
+ closed {
+  street : string,
+  city : string,
+  zip : string,
+  latlong : point
+}
+
+create type test.EventType as
+ closed {
+  event_id : int64,
+  name : string,
+  location : AddressType?,
+  organizers : {{{
+          name : string
+      }
+}},
+  sponsoring_sigs : [{
+          sig_id : int64,
+          chapter_name : string
+      }
+],
+  interest_keywords : {{string}},
+  price : double?,
+  start_time : datetime,
+  end_time : datetime
+}
+
+create external  dataset Event(EventType) using localfs((`path`=`asterix_nc1://data/events/tiny/event.adm`),(`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-9/q2-9.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-9/q2-9.2.update.sqlpp
new file mode 100644
index 0000000..bd244d0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-9/q2-9.2.update.sqlpp
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-9/q2-9.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-9/q2-9.3.query.sqlpp
new file mode 100644
index 0000000..7044711
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-9/q2-9.3.query.sqlpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+
+USE test;
+
+// Tests outer scope variable references in nested GROUP BY.
+SELECT sponsor.sig_id, COUNT(1) total_count,
+       (
+         SELECT sponsor.sig_id, e.sponsor.chapter_name, COUNT(e.sponsor.chapter_name) AS escount
+         FROM es AS e
+         GROUP BY e.sponsor.chapter_name
+       ) chapter_breakdown
+FROM  Event,
+      Event.sponsoring_sigs AS sponsor
+GROUP BY sponsor.sig_id GROUP AS es
+ORDER BY total_count DESC
+LIMIT 5
+;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2/q2.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2/q2.3.query.sqlpp
index f88e846..eb29743 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2/q2.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2/q2.3.query.sqlpp
@@ -23,14 +23,13 @@
 select element {'sig_id':sig_id,'total_count':sig_sponsorship_count,'chapter_breakdown':by_chapter}
 from  Event as event,
       event.sponsoring_sigs as sponsor
-with  es as {'event':event,'sponsor':sponsor}
-group by sponsor.sig_id as sig_id
-with  sig_sponsorship_count as count(es),
-      by_chapter as (
+group by sponsor.sig_id as sig_id group as es
+let sig_sponsorship_count = count(1),
+    by_chapter = (
       select element {'chapter_name':chapter_name,'escount':count(e)}
-      from  es as e
+      from es as e
       group by e.sponsor.chapter_name as chapter_name
-  )
+    )
 order by sig_sponsorship_count desc
 limit 5
 ;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09/q09.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09/q09.1.ddl.sqlpp
new file mode 100644
index 0000000..f78afef
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09/q09.1.ddl.sqlpp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+drop  dataverse TinySocial if exists;
+create  dataverse TinySocial;
+
+use TinySocial;
+
+
+create type TinySocial.TwitterUserType as
+{
+  `screen-name` : string
+}
+
+create type TinySocial.TweetMessageType as {
+  tweetid : string
+}
+
+create type TinySocial.FacebookUserType as
+ open {
+  id : int64
+}
+
+create type TinySocial.FacebookMessageType as
+ open {
+  `message-id` : int64
+}
+
+create  dataset FacebookUsers(FacebookUserType) primary key id;
+create  dataset FacebookMessages(FacebookMessageType) primary key `message-id`;
+create  dataset TwitterUsers(TwitterUserType) primary key `screen-name`;
+create  dataset TweetMessages(TweetMessageType) primary key tweetid hints (`CARDINALITY`=`100`);
+create  index fbUserSinceIdx  on FacebookUsers (`user-since`:datetime) type btree enforced;
+create  index fbAuthorIdx  on FacebookMessages (`author-id`:int64) type btree enforced;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09/q09.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09/q09.2.update.sqlpp
new file mode 100644
index 0000000..5211fb6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09/q09.2.update.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+use TinySocial;
+
+
+load  dataset FacebookUsers using localfs ((`path`=`asterix_nc1://data/tinysocial/fbu.adm`),(`format`=`adm`));
+
+load  dataset FacebookMessages using localfs ((`path`=`asterix_nc1://data/tinysocial/fbm.adm`),(`format`=`adm`));
+
+load  dataset TwitterUsers using localfs ((`path`=`asterix_nc1://data/tinysocial/twu.adm`),(`format`=`adm`));
+
+load  dataset TweetMessages using localfs ((`path`=`asterix_nc1://data/tinysocial/twm.adm`),(`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09/q09.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09/q09.3.query.sqlpp
new file mode 100644
index 0000000..a3b0ce6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q09/q09.3.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+USE TinySocial;
+
+// Tests the propagation for WITH binding variables in global aggregates.
+WITH t AS 1
+
+SELECT COUNT(1) count, t
+FROM FacebookUsers u;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q10/q10.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q10/q10.1.ddl.sqlpp
new file mode 100644
index 0000000..f78afef
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q10/q10.1.ddl.sqlpp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+drop  dataverse TinySocial if exists;
+create  dataverse TinySocial;
+
+use TinySocial;
+
+
+create type TinySocial.TwitterUserType as
+{
+  `screen-name` : string
+}
+
+create type TinySocial.TweetMessageType as {
+  tweetid : string
+}
+
+create type TinySocial.FacebookUserType as
+ open {
+  id : int64
+}
+
+create type TinySocial.FacebookMessageType as
+ open {
+  `message-id` : int64
+}
+
+create  dataset FacebookUsers(FacebookUserType) primary key id;
+create  dataset FacebookMessages(FacebookMessageType) primary key `message-id`;
+create  dataset TwitterUsers(TwitterUserType) primary key `screen-name`;
+create  dataset TweetMessages(TweetMessageType) primary key tweetid hints (`CARDINALITY`=`100`);
+create  index fbUserSinceIdx  on FacebookUsers (`user-since`:datetime) type btree enforced;
+create  index fbAuthorIdx  on FacebookMessages (`author-id`:int64) type btree enforced;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q10/q10.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q10/q10.2.update.sqlpp
new file mode 100644
index 0000000..5211fb6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q10/q10.2.update.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+use TinySocial;
+
+
+load  dataset FacebookUsers using localfs ((`path`=`asterix_nc1://data/tinysocial/fbu.adm`),(`format`=`adm`));
+
+load  dataset FacebookMessages using localfs ((`path`=`asterix_nc1://data/tinysocial/fbm.adm`),(`format`=`adm`));
+
+load  dataset TwitterUsers using localfs ((`path`=`asterix_nc1://data/tinysocial/twu.adm`),(`format`=`adm`));
+
+load  dataset TweetMessages using localfs ((`path`=`asterix_nc1://data/tinysocial/twm.adm`),(`format`=`adm`));
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q10/q10.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q10/q10.3.query.sqlpp
new file mode 100644
index 0000000..a5fa88c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/global-aggregate/q10/q10.3.query.sqlpp
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+USE TinySocial;
+
+// Tests the propagation for WITH binding variables for subqueries in global aggregates.
+WITH t AS (
+   SELECT VALUE MIN(v)
+   FROM [1, 2, 3] v
+)[0]
+
+SELECT COUNT(1) count, t
+FROM FacebookUsers u;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01-negative/sugar-01-negative.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01-negative/sugar-01-negative.1.ddl.sqlpp
new file mode 100644
index 0000000..7cb4811
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01-negative/sugar-01-negative.1.ddl.sqlpp
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+DROP DATAVERSE gby IF EXISTS;
+CREATE DATAVERSE gby;
+
+USE gby;
+
+CREATE TYPE EmpType AS {
+  name : string
+}
+
+CREATE DATASET Employee(EmpType) PRIMARY KEY name;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01-negative/sugar-01-negative.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01-negative/sugar-01-negative.2.update.sqlpp
new file mode 100644
index 0000000..99116f6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01-negative/sugar-01-negative.2.update.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+USE gby;
+
+INSERT INTO Employee (
+  [
+   { 'name': 'Bill',
+     'deptno': 'K55',
+     'salary': 2000 },
+
+   { 'name': 'Fred',
+     'deptno': 'K55',
+     'salary': 3000 }
+  ]
+);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01-negative/sugar-01-negative.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01-negative/sugar-01-negative.3.query.sqlpp
new file mode 100644
index 0000000..e278914
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01-negative/sugar-01-negative.3.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+USE gby;
+
+// Tests that a SQL++ core aggregate function, e.g., COLL_AVG,
+// cannot be used like a SQL-92 sugar, e.g., AVG. Its input must be a collection.
+FROM Employee e
+GROUP BY e.deptno AS deptno GROUP AS g
+SELECT deptno AS deptno, COLL_AVG(e.salary) AS avgpay,
+       (SELECT i.e.name AS name, i.e.salary AS salary FROM g AS i) AS workers;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01/sugar-01.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01/sugar-01.3.query.sqlpp
index c695e87..9ac8546 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01/sugar-01.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-01/sugar-01.3.query.sqlpp
@@ -22,5 +22,5 @@
 
 FROM Employee e
 GROUP BY e.deptno AS deptno GROUP AS g
-SELECT deptno AS deptno, coll_avg(e.salary) AS avgpay,
+SELECT deptno AS deptno, AVG(e.salary) AS avgpay,
        (SELECT i.e.name AS name, i.e.salary AS salary FROM g AS i) AS workers;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-02/sugar-02.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-02/sugar-02.4.query.sqlpp
index c86cd18..e526091 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-02/sugar-02.4.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-02/sugar-02.4.query.sqlpp
@@ -26,6 +26,6 @@
     JOIN SuperStars s ON e.id = s.id
 GROUP BY deptId
 HAVING deptId = 'K55'
-SELECT e.department_id AS deptId, coll_sum(e.salary + i.bonus) AS star_cost
+SELECT e.department_id AS deptId, SUM(e.salary + i.bonus) AS star_cost
 ORDER BY deptId;
 
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-03/sugar-03.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-03/sugar-03.3.query.sqlpp
index c747382..4832b22 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-03/sugar-03.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-03/sugar-03.3.query.sqlpp
@@ -24,7 +24,7 @@
     JOIN SuperStars s ON e.id = s.id
 GROUP BY e.department_id AS deptId GROUP AS eis
 SELECT deptId as deptId,
-    coll_avg(e.salary + i.bonus) AS avgpay,
+    AVG(e.salary + i.bonus) AS avgpay,
     (FROM eis AS v
          SELECT v.e.id AS id, v.e.salary AS salary, v.i.bonus AS bonus
          ORDER BY v.i.bonus DESC LIMIT 3
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-05/sugar-05.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-05/sugar-05.3.query.sqlpp
index 45c3528..37cf60c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-05/sugar-05.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/sugar-05/sugar-05.3.query.sqlpp
@@ -25,7 +25,7 @@
             FROM Car c JOIN Tire t ON c.tire_size = t.size
             GROUP BY c.tire_size AS tire_size GROUP AS g
             SELECT tire_size AS tire_size,
-                   coll_avg(c.price + 4 * t.price) AS avg_total_price,
+                   AVG(c.price + 4 * t.price) AS avg_total_price,
                    ( FROM g AS g
                      SELECT g.c.make AS make,
                             g.c.model AS model,
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.1.ddl.sqlpp
new file mode 100644
index 0000000..82f182e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.1.ddl.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+create type account as open
+{ id: int32, sum:int32 }
+
+create dataset Accounts(account) primary key id;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.2.update.sqlpp
new file mode 100644
index 0000000..3af2128
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.2.update.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+use test;
+
+insert into Accounts(
+{"id": 1, "sum":100}
+)
+insert into Accounts(
+{"id": 2, "sum":150}
+)
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.3.query.sqlpp
new file mode 100644
index 0000000..6856726
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/query-ASTERIXDB-971/query-ASTERIXDB-971.3.query.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+USE test;
+
+FROM range(1,2) AS x
+SELECT ELEMENT (
+    WITH z AS (FROM Accounts AS y WHERE y.id=x SELECT VALUE y)
+    SELECT x, z
+);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/subquery/exists/exists.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/subquery/exists/exists.3.query.sqlpp
index 8f89da4..e7328f3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/subquery/exists/exists.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/subquery/exists/exists.3.query.sqlpp
@@ -23,14 +23,13 @@
 (
     SELECT c_acctbal, c_custkey, substring(c_phone,1,2) AS cntrycode
     FROM  Customer
-)
-,
+),
 avg AS (
         SELECT ELEMENT AVG(c_acctbal)
         FROM  Customer
         WHERE c_acctbal > 0.0
 )[0]
-SELECT  cntrycode, count(ct) AS numcust, SUM(c_acctbal) AS totacctbal
+SELECT cntrycode, count(ct) AS numcust, SUM(c_acctbal) AS totacctbal
 FROM  q22_customer_tmp AS ct
 WHERE c_acctbal > avg
       AND EXISTS (SELECT * FROM Orders o WHERE o.o_custkey = ct.c_custkey)
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
index 7a14b25..445da07 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
@@ -34,5 +34,5 @@
       Part as p
 let lp = {'p_type': p.p_type, 'l_extendedprice': l.l_extendedprice, 'l_discount': l.l_discount}
 where ((l.l_partkey = p.p_partkey) and (l.l_shipdate >= '1995-09-01') and (l.l_shipdate < '1995-10-01'))
-group by 1 as t
+group by 1 as t group as g(lp as lp)
 ;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
index 5de0352..c20b6ae 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch-with-index/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
@@ -34,5 +34,5 @@
       Part as p
 let lp = {'p_type': p.p_type, 'l_extendedprice': l.l_extendedprice, 'l_discount': l.l_discount}
 where ((l.l_partkey = p.p_partkey) and (l.l_shipdate >= '1995-09-01') and (l.l_shipdate < '1995-10-01'))
-group by 1 as t
+group by 1 as t group as g(lp as lp)
 ;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
index 32ab76a..89ade9d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.query.sqlpp
@@ -32,4 +32,4 @@
 let lp = {'p_type': p.p_type, 'l_extendedprice': l.l_extendedprice, 'l_discount': l.l_discount}
 where ((l.l_partkey = p.p_partkey) and (l.l_shipdate >= '1995-09-01') and (l.l_shipdate < '1995-10-01'))
 group by 1 as t
-;
+group as g(lp as lp);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/dapd/q2-12/q2-12.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/dapd/q2-12/q2-12.1.adm
new file mode 100644
index 0000000..f845003
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/dapd/q2-12/q2-12.1.adm
@@ -0,0 +1,2 @@
+{ "sig_id": 14, "total_count": 3, "chapter_breakdown": [ { "sig_id": 14, "$1": 3 } ] }
+{ "sig_id": 31, "total_count": 1, "chapter_breakdown": [ { "sig_id": 31, "$1": 1 } ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/dapd/q2-7/q2-7.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/dapd/q2-7/q2-7.1.adm
new file mode 100644
index 0000000..5839a99
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/dapd/q2-7/q2-7.1.adm
@@ -0,0 +1,2 @@
+{ "sig_id": 14, "total_count": 3, "chapter_breakdown": [ { "chapter_name": "Laguna Beach", "$2": [ { "e": { "Event": { "event_id": 1023, "name": "Art Opening: Southern Orange County Beaches", "organizers": {{ { "name": "Jane Smith" } }}, "sponsoring_sigs": [ { "sig_id": 14, "chapter_name": "San Clemente" }, { "sig_id": 14, "chapter_name": "Laguna Beach" } ], "interest_keywords": {{ "art", "landscape", "nature", "vernissage" }}, "start_time": datetime("2011-02-24T02:00:00.000Z"), "end_time": datetime("2011-02-24T05:00:00.000Z") }, "sponsor": { "sig_id": 14, "chapter_name": "Laguna Beach" } } }, { "e": { "Event": { "event_id": 1042, "name": "Orange County Landmarks", "organizers": {{ { "name": "John Smith" } }}, "sponsoring_sigs": [ { "sig_id": 14, "chapter_name": "Laguna Beach" } ], "interest_keywords": {{ "architecture", "photography" }}, "price": 10.0, "start_time": datetime("2011-02-24T01:00:00.000Z"), "end_time": datetime("2011-02-24T03:00:00.000Z") }, "sponsor": { "sig_id": 14, "chapter_name": "Laguna Beach" } } } ] }, { "chapter_name": "San Clemente", "$2": [ { "e": { "Event": { "event_id": 1023, "name": "Art Opening: Southern Orange County Beaches", "organizers": {{ { "name": "Jane Smith" } }}, "sponsoring_sigs": [ { "sig_id": 14, "chapter_name": "San Clemente" }, { "sig_id": 14, "chapter_name": "Laguna Beach" } ], "interest_keywords": {{ "art", "landscape", "nature", "vernissage" }}, "start_time": datetime("2011-02-24T02:00:00.000Z"), "end_time": datetime("2011-02-24T05:00:00.000Z") }, "sponsor": { "sig_id": 14, "chapter_name": "San Clemente" } } } ] } ] }
+{ "sig_id": 31, "total_count": 1, "chapter_breakdown": [ { "chapter_name": "Huntington Beach", "$2": [ { "e": { "Event": { "event_id": 941, "name": "Intro to Scuba Diving", "organizers": {{ { "name": "Joseph Surfer", "affiliation": "Huntington Beach Scuba Assoc." } }}, "sponsoring_sigs": [ { "sig_id": 31, "chapter_name": "Huntington Beach" } ], "interest_keywords": {{ "scuba", "diving", "aquatics" }}, "price": 40.0, "start_time": datetime("2010-10-16T17:00:00.000Z"), "end_time": datetime("2010-10-16T20:00:00.000Z") }, "sponsor": { "sig_id": 31, "chapter_name": "Huntington Beach" } } } ] } ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/dapd/q2-9/q2-9.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/dapd/q2-9/q2-9.1.adm
new file mode 100644
index 0000000..9f5968c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/dapd/q2-9/q2-9.1.adm
@@ -0,0 +1,2 @@
+{ "sig_id": 14, "total_count": 3, "chapter_breakdown": [ { "sig_id": 14, "chapter_name": "Laguna Beach", "escount": 2 }, { "sig_id": 14, "chapter_name": "San Clemente", "escount": 1 } ] }
+{ "sig_id": 31, "total_count": 1, "chapter_breakdown": [ { "sig_id": 31, "chapter_name": "Huntington Beach", "escount": 1 } ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/global-aggregate/q09/q09.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/global-aggregate/q09/q09.1.adm
new file mode 100644
index 0000000..17e22f6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/global-aggregate/q09/q09.1.adm
@@ -0,0 +1 @@
+{ "count": 10, "t": 1 }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-971-aql/query-ASTERIXDB-971-aql.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-971-aql/query-ASTERIXDB-971-aql.1.adm
new file mode 100644
index 0000000..c828226
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-971-aql/query-ASTERIXDB-971-aql.1.adm
@@ -0,0 +1,2 @@
+{ "x": 1, "z": [ { "id": 1, "sum": 100 } ] }
+{ "x": 2, "z": [ { "id": 2, "sum": 150 } ] }
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-971-sqlpp/query-ASTERIXDB-971-sqlpp.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-971-sqlpp/query-ASTERIXDB-971-sqlpp.1.adm
new file mode 100644
index 0000000..6ec06aa
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/query-ASTERIXDB-971-sqlpp/query-ASTERIXDB-971-sqlpp.1.adm
@@ -0,0 +1,2 @@
+[ { "x": 1, "z": [ { "id": 1, "sum": 100 } ] } ]
+[ { "x": 2, "z": [ { "id": 2, "sum": 150 } ] } ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/dapd/q2/q2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/dapd/q2/q2.3.ast
index f8a709b..06b8dff 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/dapd/q2/q2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/dapd/q2/q2.3.ast
@@ -30,20 +30,6 @@
   ]
   AS Variable [ Name=$sponsor ]
 ]
-Let Variable [ Name=$es ]
-  :=
-  RecordConstructor [
-    (
-      LiteralExpr [STRING] [event]
-      :
-      Variable [ Name=$event ]
-    )
-    (
-      LiteralExpr [STRING] [sponsor]
-      :
-      Variable [ Name=$sponsor ]
-    )
-  ]
 Groupby
   Variable [ Name=$sig_id ]
   :=
@@ -51,11 +37,10 @@
     Variable [ Name=$sponsor ]
     Field=sig_id
   ]
-  GROUP AS Variable [ Name=#1 ]
+  GROUP AS Variable [ Name=$es ]
   (
-    es:=Variable [ Name=$es ]
-    sponsor:=Variable [ Name=$sponsor ]
     event:=Variable [ Name=$event ]
+    sponsor:=Variable [ Name=$sponsor ]
   )
 
 Let Variable [ Name=$sig_sponsorship_count ]
@@ -63,13 +48,10 @@
   FunctionCall test.sql-count@1[
     (
       SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=es
+      LiteralExpr [LONG] [1]
       ]
-      ]
-      FROM [        Variable [ Name=#1 ]
-        AS Variable [ Name=#2 ]
+      FROM [        Variable [ Name=$es ]
+        AS Variable [ Name=#1 ]
       ]
     )
   ]
@@ -90,12 +72,12 @@
           (
             SELECT ELEMENT [
             FieldAccessor [
-              Variable [ Name=#4 ]
+              Variable [ Name=#3 ]
               Field=e
             ]
             ]
-            FROM [              Variable [ Name=#3 ]
-              AS Variable [ Name=#4 ]
+            FROM [              Variable [ Name=#2 ]
+              AS Variable [ Name=#3 ]
             ]
           )
         ]
@@ -115,15 +97,9 @@
         ]
         Field=chapter_name
       ]
-      GROUP AS Variable [ Name=#3 ]
+      GROUP AS Variable [ Name=#2 ]
       (
         e:=Variable [ Name=$e ]
-        sig_sponsorship_count:=Variable [ Name=$sig_sponsorship_count ]
-        es:=Variable [ Name=$es ]
-        event:=Variable [ Name=$event ]
-        sponsor:=Variable [ Name=$sponsor ]
-        sig_id:=Variable [ Name=$sig_id ]
-        #1:=Variable [ Name=#1 ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/flwor/at02/at02.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/flwor/at02/at02.3.ast
index afd1f81..755ff18 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/flwor/at02/at02.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/flwor/at02/at02.3.ast
@@ -82,8 +82,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    m:=Variable [ Name=$m ]
     u:=Variable [ Name=$u ]
+    m:=Variable [ Name=$m ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/flwor/query-issue550/query-issue550.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/flwor/query-issue550/query-issue550.3.ast
index f8988ad..e5a516d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/flwor/query-issue550/query-issue550.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/flwor/query-issue550/query-issue550.3.ast
@@ -181,6 +181,5 @@
   GROUP AS Variable [ Name=#1 ]
   (
     s:=Variable [ Name=$s ]
-    sample:=Variable [ Name=$sample ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_1/dblp-1_1.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_1/dblp-1_1.3.ast
index 884a1aa..165a711 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_1/dblp-1_1.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_1/dblp-1_1.3.ast
@@ -23,8 +23,8 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    token:=Variable [ Name=$token ]
     paper:=Variable [ Name=$paper ]
+    token:=Variable [ Name=$token ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2.1.1/dblp-1_2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2.1.1/dblp-1_2.3.ast
index 0279463..1d14a93 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2.1.1/dblp-1_2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2.1.1/dblp-1_2.3.ast
@@ -29,18 +29,16 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    id:=Variable [ Name=$id ]
-    token:=Variable [ Name=$token ]
     paper:=Variable [ Name=$paper ]
+    token:=Variable [ Name=$token ]
   )
 
 Orderby
   FunctionCall fuzzyjoin.sql-count@1[
     (
       SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=id
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [id]
       ]
       ]
       FROM [        Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2.1/dblp-1_2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2.1/dblp-1_2.3.ast
index 0279463..1d14a93 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2.1/dblp-1_2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2.1/dblp-1_2.3.ast
@@ -29,18 +29,16 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    id:=Variable [ Name=$id ]
-    token:=Variable [ Name=$token ]
     paper:=Variable [ Name=$paper ]
+    token:=Variable [ Name=$token ]
   )
 
 Orderby
   FunctionCall fuzzyjoin.sql-count@1[
     (
       SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=id
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [id]
       ]
       ]
       FROM [        Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2/dblp-1_2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2/dblp-1_2.3.ast
index 37f1f7c..7306e80 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2/dblp-1_2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-1_2/dblp-1_2.3.ast
@@ -29,18 +29,16 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    paperid:=Variable [ Name=$paperid ]
-    token:=Variable [ Name=$token ]
     paper:=Variable [ Name=$paper ]
+    token:=Variable [ Name=$token ]
   )
 
 Orderby
   FunctionCall fuzzyjoin.sql-count@1[
     (
       SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=paperid
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [paperid]
       ]
       ]
       FROM [        Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2.1_5.3.1/dblp-2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2.1_5.3.1/dblp-2.3.ast
index 378d301..fb7aaec 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2.1_5.3.1/dblp-2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2.1_5.3.1/dblp-2.3.ast
@@ -96,24 +96,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_1/dblp-2_1.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_1/dblp-2_1.3.ast
index d77ee91..172b607 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_1/dblp-2_1.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_1/dblp-2_1.3.ast
@@ -60,10 +60,8 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_2/dblp-2_2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_2/dblp-2_2.3.ast
index de0c379..4d4ecc8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_2/dblp-2_2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_2/dblp-2_2.3.ast
@@ -66,20 +66,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_3/dblp-2_3.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_3/dblp-2_3.3.ast
index 0359a32..0e7d067 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_3/dblp-2_3.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_3/dblp-2_3.3.ast
@@ -69,21 +69,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_4/dblp-2_4.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_4/dblp-2_4.3.ast
index b43a06c..b290858 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_4/dblp-2_4.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_4/dblp-2_4.3.ast
@@ -72,22 +72,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.1/dblp-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.1/dblp-2_5.3.ast
index c8a4003..244cb0b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.1/dblp-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.1/dblp-2_5.3.ast
@@ -82,23 +82,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.2/dblp-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.2/dblp-2_5.3.ast
index c8a4003..244cb0b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.2/dblp-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.2/dblp-2_5.3.ast
@@ -82,23 +82,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.3.1/dblp-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.3.1/dblp-2_5.3.ast
index c8a4003..244cb0b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.3.1/dblp-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.3.1/dblp-2_5.3.ast
@@ -82,23 +82,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.3/dblp-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.3/dblp-2_5.3.ast
index c8a4003..244cb0b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.3/dblp-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5.3/dblp-2_5.3.ast
@@ -82,23 +82,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5/dblp-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5/dblp-2_5.3.ast
index 3ae14cf..60e0b24 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5/dblp-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-2_5/dblp-2_5.3.ast
@@ -82,23 +82,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1.1/dblp-3_1.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1.1/dblp-3_1.3.ast
index 350a380..fd16f56 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1.1/dblp-3_1.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1.1/dblp-3_1.3.ast
@@ -40,7 +40,9 @@
         LiteralExpr [STRING] [sim]
         :
         IndexAccessor [
-          Variable [ Name=$sim ]
+          FunctionCall Metadata.dataset@1[
+            LiteralExpr [STRING] [sim]
+          ]
           Index:           LiteralExpr [LONG] [0]
         ]
       )
@@ -131,14 +133,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenLeft:=Variable [ Name=$lenLeft ]
-                prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-                paperRight:=Variable [ Name=$paperRight ]
-                prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
-                paperLeft:=Variable [ Name=$paperLeft ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -222,16 +218,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenRight:=Variable [ Name=$lenRight ]
-                tokensLeft:=Variable [ Name=$tokensLeft ]
-                lenLeft:=Variable [ Name=$lenLeft ]
-                prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-                paperRight:=Variable [ Name=$paperRight ]
-                prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
-                paperLeft:=Variable [ Name=$paperLeft ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -321,15 +309,10 @@
       ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensRight:=Variable [ Name=$tokensRight ]
-        lenRight:=Variable [ Name=$lenRight ]
-        tokensLeft:=Variable [ Name=$tokensLeft ]
-        lenLeft:=Variable [ Name=$lenLeft ]
-        prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-        paperRight:=Variable [ Name=$paperRight ]
-        prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
         paperLeft:=Variable [ Name=$paperLeft ]
+        prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
+        paperRight:=Variable [ Name=$paperRight ]
+        prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1.2/dblp-3_1.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1.2/dblp-3_1.3.ast
index 350a380..fd16f56 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1.2/dblp-3_1.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1.2/dblp-3_1.3.ast
@@ -40,7 +40,9 @@
         LiteralExpr [STRING] [sim]
         :
         IndexAccessor [
-          Variable [ Name=$sim ]
+          FunctionCall Metadata.dataset@1[
+            LiteralExpr [STRING] [sim]
+          ]
           Index:           LiteralExpr [LONG] [0]
         ]
       )
@@ -131,14 +133,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenLeft:=Variable [ Name=$lenLeft ]
-                prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-                paperRight:=Variable [ Name=$paperRight ]
-                prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
-                paperLeft:=Variable [ Name=$paperLeft ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -222,16 +218,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenRight:=Variable [ Name=$lenRight ]
-                tokensLeft:=Variable [ Name=$tokensLeft ]
-                lenLeft:=Variable [ Name=$lenLeft ]
-                prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-                paperRight:=Variable [ Name=$paperRight ]
-                prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
-                paperLeft:=Variable [ Name=$paperLeft ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -321,15 +309,10 @@
       ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensRight:=Variable [ Name=$tokensRight ]
-        lenRight:=Variable [ Name=$lenRight ]
-        tokensLeft:=Variable [ Name=$tokensLeft ]
-        lenLeft:=Variable [ Name=$lenLeft ]
-        prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-        paperRight:=Variable [ Name=$paperRight ]
-        prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
         paperLeft:=Variable [ Name=$paperLeft ]
+        prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
+        paperRight:=Variable [ Name=$paperRight ]
+        prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1/dblp-3_1.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1/dblp-3_1.3.ast
index 75f9c99..05a8114 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1/dblp-3_1.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-3_1/dblp-3_1.3.ast
@@ -50,7 +50,9 @@
         LiteralExpr [STRING] [sim]
         :
         IndexAccessor [
-          Variable [ Name=$sim ]
+          FunctionCall Metadata.dataset@1[
+            LiteralExpr [STRING] [sim]
+          ]
           Index:           LiteralExpr [LONG] [0]
         ]
       )
@@ -141,14 +143,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenLeft:=Variable [ Name=$lenLeft ]
-                prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-                paperRight:=Variable [ Name=$paperRight ]
-                prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
-                paperLeft:=Variable [ Name=$paperLeft ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -232,16 +228,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenRight:=Variable [ Name=$lenRight ]
-                tokensLeft:=Variable [ Name=$tokensLeft ]
-                lenLeft:=Variable [ Name=$lenLeft ]
-                prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-                paperRight:=Variable [ Name=$paperRight ]
-                prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
-                paperLeft:=Variable [ Name=$paperLeft ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -331,15 +319,10 @@
       ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensRight:=Variable [ Name=$tokensRight ]
-        lenRight:=Variable [ Name=$lenRight ]
-        tokensLeft:=Variable [ Name=$tokensLeft ]
-        lenLeft:=Variable [ Name=$lenLeft ]
-        prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
-        paperRight:=Variable [ Name=$paperRight ]
-        prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
         paperLeft:=Variable [ Name=$paperLeft ]
+        prefixTokenLeft:=Variable [ Name=$prefixTokenLeft ]
+        paperRight:=Variable [ Name=$paperRight ]
+        prefixTokenRight:=Variable [ Name=$prefixTokenRight ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_1/dblp-csx-2_1.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_1/dblp-csx-2_1.3.ast
index d24bda4..d3b6600 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_1/dblp-csx-2_1.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_1/dblp-csx-2_1.3.ast
@@ -102,13 +102,8 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
@@ -182,14 +177,8 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#3 ]
           (
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
@@ -282,13 +271,10 @@
   Variable [ Name=$sim ]
   GROUP AS Variable [ Name=#5 ]
   (
-    sim:=Variable [ Name=$sim ]
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_2/dblp-csx-2_2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_2/dblp-csx-2_2.3.ast
index 150b749..af18d99 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_2/dblp-csx-2_2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_2/dblp-csx-2_2.3.ast
@@ -108,23 +108,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
@@ -195,24 +188,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#3 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#4 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#3 ]
@@ -296,13 +281,10 @@
   Variable [ Name=$sim ]
   GROUP AS Variable [ Name=#5 ]
   (
-    sim:=Variable [ Name=$sim ]
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_3/dblp-csx-2_3.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_3/dblp-csx-2_3.3.ast
index 31b79d2..e72a255 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_3/dblp-csx-2_3.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_3/dblp-csx-2_3.3.ast
@@ -114,24 +114,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
@@ -208,26 +200,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#3 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            idCSX:=Variable [ Name=$idCSX ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#4 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#3 ]
@@ -305,15 +287,10 @@
   Variable [ Name=$sim ]
   GROUP AS Variable [ Name=#5 ]
   (
-    sim:=Variable [ Name=$sim ]
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    idCSX:=Variable [ Name=$idCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    idDBLP:=Variable [ Name=$idDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_4/dblp-csx-2_4.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_4/dblp-csx-2_4.3.ast
index f6dcead..ce16186 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_4/dblp-csx-2_4.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_4/dblp-csx-2_4.3.ast
@@ -117,25 +117,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
@@ -215,28 +206,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#3 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-            idCSX:=Variable [ Name=$idCSX ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#4 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#3 ]
@@ -304,17 +283,10 @@
   Variable [ Name=$sim ]
   GROUP AS Variable [ Name=#5 ]
   (
-    sim:=Variable [ Name=$sim ]
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-    idCSX:=Variable [ Name=$idCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-    idDBLP:=Variable [ Name=$idDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.1/dblp-csx-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.1/dblp-csx-2_5.3.ast
index 936ac81..2b10846 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.1/dblp-csx-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.1/dblp-csx-2_5.3.ast
@@ -17,7 +17,9 @@
     LiteralExpr [STRING] [sim]
     :
     IndexAccessor [
-      Variable [ Name=$sim ]
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [sim]
+      ]
       Index:       LiteralExpr [LONG] [0]
     ]
   )
@@ -122,26 +124,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
@@ -226,30 +218,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#3 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenCSX:=Variable [ Name=$lenCSX ]
-            tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-            idCSX:=Variable [ Name=$idCSX ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#4 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#3 ]
@@ -310,19 +288,10 @@
   Variable [ Name=$idCSX ]
   GROUP AS Variable [ Name=#5 ]
   (
-    sim:=Variable [ Name=$sim ]
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    lenCSX:=Variable [ Name=$lenCSX ]
-    tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-    idCSX:=Variable [ Name=$idCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    lenDBLP:=Variable [ Name=$lenDBLP ]
-    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-    idDBLP:=Variable [ Name=$idDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.2/dblp-csx-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.2/dblp-csx-2_5.3.ast
index 936ac81..2b10846 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.2/dblp-csx-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.2/dblp-csx-2_5.3.ast
@@ -17,7 +17,9 @@
     LiteralExpr [STRING] [sim]
     :
     IndexAccessor [
-      Variable [ Name=$sim ]
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [sim]
+      ]
       Index:       LiteralExpr [LONG] [0]
     ]
   )
@@ -122,26 +124,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
@@ -226,30 +218,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#3 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenCSX:=Variable [ Name=$lenCSX ]
-            tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-            idCSX:=Variable [ Name=$idCSX ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#4 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#3 ]
@@ -310,19 +288,10 @@
   Variable [ Name=$idCSX ]
   GROUP AS Variable [ Name=#5 ]
   (
-    sim:=Variable [ Name=$sim ]
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    lenCSX:=Variable [ Name=$lenCSX ]
-    tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-    idCSX:=Variable [ Name=$idCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    lenDBLP:=Variable [ Name=$lenDBLP ]
-    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-    idDBLP:=Variable [ Name=$idDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.3.1/dblp-csx-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.3.1/dblp-csx-2_5.3.ast
index b445f35..8ac97a6 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.3.1/dblp-csx-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.3.1/dblp-csx-2_5.3.ast
@@ -122,26 +122,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
@@ -226,30 +216,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#3 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenCSX:=Variable [ Name=$lenCSX ]
-            tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-            idCSX:=Variable [ Name=$idCSX ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#4 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#3 ]
@@ -313,19 +289,10 @@
   Variable [ Name=$sim ]
   GROUP AS Variable [ Name=#5 ]
   (
-    sim:=Variable [ Name=$sim ]
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    lenCSX:=Variable [ Name=$lenCSX ]
-    tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-    idCSX:=Variable [ Name=$idCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    lenDBLP:=Variable [ Name=$lenDBLP ]
-    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-    idDBLP:=Variable [ Name=$idDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.3/dblp-csx-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.3/dblp-csx-2_5.3.ast
index 936ac81..2b10846 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.3/dblp-csx-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5.3/dblp-csx-2_5.3.ast
@@ -17,7 +17,9 @@
     LiteralExpr [STRING] [sim]
     :
     IndexAccessor [
-      Variable [ Name=$sim ]
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [sim]
+      ]
       Index:       LiteralExpr [LONG] [0]
     ]
   )
@@ -122,26 +124,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
@@ -226,30 +218,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#3 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenCSX:=Variable [ Name=$lenCSX ]
-            tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-            idCSX:=Variable [ Name=$idCSX ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#4 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#3 ]
@@ -310,19 +288,10 @@
   Variable [ Name=$idCSX ]
   GROUP AS Variable [ Name=#5 ]
   (
-    sim:=Variable [ Name=$sim ]
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    lenCSX:=Variable [ Name=$lenCSX ]
-    tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-    idCSX:=Variable [ Name=$idCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    lenDBLP:=Variable [ Name=$lenDBLP ]
-    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-    idDBLP:=Variable [ Name=$idDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5/dblp-csx-2_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5/dblp-csx-2_5.3.ast
index b445f35..8ac97a6 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5/dblp-csx-2_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-2_5/dblp-csx-2_5.3.ast
@@ -122,26 +122,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#1 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#2 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#1 ]
@@ -226,30 +216,16 @@
           Variable [ Name=$token ]
           GROUP AS Variable [ Name=#3 ]
           (
-            id:=Variable [ Name=$id ]
-            token:=Variable [ Name=$token ]
             paper:=Variable [ Name=$paper ]
-            tokenUnranked:=Variable [ Name=$tokenUnranked ]
-            lenCSX:=Variable [ Name=$lenCSX ]
-            tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-            idCSX:=Variable [ Name=$idCSX ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-            paperDBLP:=Variable [ Name=$paperDBLP ]
+            token:=Variable [ Name=$token ]
           )
 
         Orderby
           FunctionCall fuzzyjoin.sql-count@1[
             (
               SELECT ELEMENT [
-              FieldAccessor [
-                Variable [ Name=#4 ]
-                Field=id
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [id]
               ]
               ]
               FROM [                Variable [ Name=#3 ]
@@ -313,19 +289,10 @@
   Variable [ Name=$sim ]
   GROUP AS Variable [ Name=#5 ]
   (
-    sim:=Variable [ Name=$sim ]
-    tokensCSX:=Variable [ Name=$tokensCSX ]
-    lenCSX:=Variable [ Name=$lenCSX ]
-    tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-    idCSX:=Variable [ Name=$idCSX ]
-    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-    lenDBLP:=Variable [ Name=$lenDBLP ]
-    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-    idDBLP:=Variable [ Name=$idDBLP ]
-    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-    paperCSX:=Variable [ Name=$paperCSX ]
-    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
     paperDBLP:=Variable [ Name=$paperDBLP ]
+    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+    paperCSX:=Variable [ Name=$paperCSX ]
+    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_1/dblp-csx-3_1.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_1/dblp-csx-3_1.3.ast
index 6ecd6a4..ed3dd63 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_1/dblp-csx-3_1.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_1/dblp-csx-3_1.3.ast
@@ -125,13 +125,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -205,14 +200,8 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
@@ -305,13 +294,10 @@
       Variable [ Name=$sim ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensCSX:=Variable [ Name=$tokensCSX ]
-        tokensDBLP:=Variable [ Name=$tokensDBLP ]
-        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-        paperCSX:=Variable [ Name=$paperCSX ]
-        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
         paperDBLP:=Variable [ Name=$paperDBLP ]
+        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+        paperCSX:=Variable [ Name=$paperCSX ]
+        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_2/dblp-csx-3_2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_2/dblp-csx-3_2.3.ast
index b82fc31..ef063ba5 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_2/dblp-csx-3_2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_2/dblp-csx-3_2.3.ast
@@ -131,23 +131,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#2 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#1 ]
@@ -218,24 +211,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#4 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#3 ]
@@ -319,13 +304,10 @@
       Variable [ Name=$sim ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensCSX:=Variable [ Name=$tokensCSX ]
-        tokensDBLP:=Variable [ Name=$tokensDBLP ]
-        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-        paperCSX:=Variable [ Name=$paperCSX ]
-        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
         paperDBLP:=Variable [ Name=$paperDBLP ]
+        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+        paperCSX:=Variable [ Name=$paperCSX ]
+        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_3/dblp-csx-3_3.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_3/dblp-csx-3_3.3.ast
index 8fcf073..2d7c141 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_3/dblp-csx-3_3.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_3/dblp-csx-3_3.3.ast
@@ -137,24 +137,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#2 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#1 ]
@@ -231,26 +223,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                idCSX:=Variable [ Name=$idCSX ]
-                tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#4 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#3 ]
@@ -328,15 +310,10 @@
       Variable [ Name=$sim ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensCSX:=Variable [ Name=$tokensCSX ]
-        idCSX:=Variable [ Name=$idCSX ]
-        tokensDBLP:=Variable [ Name=$tokensDBLP ]
-        idDBLP:=Variable [ Name=$idDBLP ]
-        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-        paperCSX:=Variable [ Name=$paperCSX ]
-        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
         paperDBLP:=Variable [ Name=$paperDBLP ]
+        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+        paperCSX:=Variable [ Name=$paperCSX ]
+        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_4/dblp-csx-3_4.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_4/dblp-csx-3_4.3.ast
index b3923a8..c68832a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_4/dblp-csx-3_4.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_4/dblp-csx-3_4.3.ast
@@ -140,25 +140,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#2 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#1 ]
@@ -238,28 +229,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-                idCSX:=Variable [ Name=$idCSX ]
-                tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#4 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#3 ]
@@ -327,17 +306,10 @@
       Variable [ Name=$sim ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensCSX:=Variable [ Name=$tokensCSX ]
-        tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-        idCSX:=Variable [ Name=$idCSX ]
-        tokensDBLP:=Variable [ Name=$tokensDBLP ]
-        tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-        idDBLP:=Variable [ Name=$idDBLP ]
-        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-        paperCSX:=Variable [ Name=$paperCSX ]
-        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
         paperDBLP:=Variable [ Name=$paperDBLP ]
+        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+        paperCSX:=Variable [ Name=$paperCSX ]
+        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.1/dblp-csx-3_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.1/dblp-csx-3_5.3.ast
index bf3eb4e..b12fe05 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.1/dblp-csx-3_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.1/dblp-csx-3_5.3.ast
@@ -40,7 +40,9 @@
         LiteralExpr [STRING] [sim]
         :
         IndexAccessor [
-          Variable [ Name=$sim ]
+          FunctionCall Metadata.dataset@1[
+            LiteralExpr [STRING] [sim]
+          ]
           Index:           LiteralExpr [LONG] [0]
         ]
       )
@@ -145,26 +147,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#2 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#1 ]
@@ -249,30 +241,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenCSX:=Variable [ Name=$lenCSX ]
-                tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-                idCSX:=Variable [ Name=$idCSX ]
-                tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#4 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#3 ]
@@ -333,19 +311,10 @@
       Variable [ Name=$idCSX ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensCSX:=Variable [ Name=$tokensCSX ]
-        lenCSX:=Variable [ Name=$lenCSX ]
-        tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-        idCSX:=Variable [ Name=$idCSX ]
-        tokensDBLP:=Variable [ Name=$tokensDBLP ]
-        lenDBLP:=Variable [ Name=$lenDBLP ]
-        tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-        idDBLP:=Variable [ Name=$idDBLP ]
-        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-        paperCSX:=Variable [ Name=$paperCSX ]
-        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
         paperDBLP:=Variable [ Name=$paperDBLP ]
+        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+        paperCSX:=Variable [ Name=$paperCSX ]
+        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.2/dblp-csx-3_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.2/dblp-csx-3_5.3.ast
index bf3eb4e..b12fe05 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.2/dblp-csx-3_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.2/dblp-csx-3_5.3.ast
@@ -40,7 +40,9 @@
         LiteralExpr [STRING] [sim]
         :
         IndexAccessor [
-          Variable [ Name=$sim ]
+          FunctionCall Metadata.dataset@1[
+            LiteralExpr [STRING] [sim]
+          ]
           Index:           LiteralExpr [LONG] [0]
         ]
       )
@@ -145,26 +147,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#2 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#1 ]
@@ -249,30 +241,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenCSX:=Variable [ Name=$lenCSX ]
-                tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-                idCSX:=Variable [ Name=$idCSX ]
-                tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#4 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#3 ]
@@ -333,19 +311,10 @@
       Variable [ Name=$idCSX ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensCSX:=Variable [ Name=$tokensCSX ]
-        lenCSX:=Variable [ Name=$lenCSX ]
-        tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-        idCSX:=Variable [ Name=$idCSX ]
-        tokensDBLP:=Variable [ Name=$tokensDBLP ]
-        lenDBLP:=Variable [ Name=$lenDBLP ]
-        tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-        idDBLP:=Variable [ Name=$idDBLP ]
-        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-        paperCSX:=Variable [ Name=$paperCSX ]
-        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
         paperDBLP:=Variable [ Name=$paperDBLP ]
+        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+        paperCSX:=Variable [ Name=$paperCSX ]
+        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.3.1/dblp-csx-3_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.3.1/dblp-csx-3_5.3.ast
index bf3eb4e..b12fe05 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.3.1/dblp-csx-3_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.3.1/dblp-csx-3_5.3.ast
@@ -40,7 +40,9 @@
         LiteralExpr [STRING] [sim]
         :
         IndexAccessor [
-          Variable [ Name=$sim ]
+          FunctionCall Metadata.dataset@1[
+            LiteralExpr [STRING] [sim]
+          ]
           Index:           LiteralExpr [LONG] [0]
         ]
       )
@@ -145,26 +147,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#2 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#1 ]
@@ -249,30 +241,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenCSX:=Variable [ Name=$lenCSX ]
-                tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-                idCSX:=Variable [ Name=$idCSX ]
-                tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#4 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#3 ]
@@ -333,19 +311,10 @@
       Variable [ Name=$idCSX ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensCSX:=Variable [ Name=$tokensCSX ]
-        lenCSX:=Variable [ Name=$lenCSX ]
-        tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-        idCSX:=Variable [ Name=$idCSX ]
-        tokensDBLP:=Variable [ Name=$tokensDBLP ]
-        lenDBLP:=Variable [ Name=$lenDBLP ]
-        tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-        idDBLP:=Variable [ Name=$idDBLP ]
-        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-        paperCSX:=Variable [ Name=$paperCSX ]
-        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
         paperDBLP:=Variable [ Name=$paperDBLP ]
+        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+        paperCSX:=Variable [ Name=$paperCSX ]
+        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.3/dblp-csx-3_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.3/dblp-csx-3_5.3.ast
index 44ac6dd..43d5d8d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.3/dblp-csx-3_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.3/dblp-csx-3_5.3.ast
@@ -145,26 +145,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#2 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#1 ]
@@ -249,30 +239,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenCSX:=Variable [ Name=$lenCSX ]
-                tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-                idCSX:=Variable [ Name=$idCSX ]
-                tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#4 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#3 ]
@@ -336,19 +312,10 @@
       Variable [ Name=$sim ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensCSX:=Variable [ Name=$tokensCSX ]
-        lenCSX:=Variable [ Name=$lenCSX ]
-        tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-        idCSX:=Variable [ Name=$idCSX ]
-        tokensDBLP:=Variable [ Name=$tokensDBLP ]
-        lenDBLP:=Variable [ Name=$lenDBLP ]
-        tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-        idDBLP:=Variable [ Name=$idDBLP ]
-        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-        paperCSX:=Variable [ Name=$paperCSX ]
-        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
         paperDBLP:=Variable [ Name=$paperDBLP ]
+        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+        paperCSX:=Variable [ Name=$paperCSX ]
+        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.4.1/dblp-csx-3_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.4.1/dblp-csx-3_5.3.ast
index 6bc2b0b..866ebd8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.4.1/dblp-csx-3_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.4.1/dblp-csx-3_5.3.ast
@@ -87,7 +87,9 @@
             LiteralExpr [STRING] [sim]
             :
             IndexAccessor [
-              Variable [ Name=$sim ]
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [sim]
+              ]
               Index:               LiteralExpr [LONG] [0]
             ]
           )
@@ -192,26 +194,16 @@
                   Variable [ Name=$token ]
                   GROUP AS Variable [ Name=#1 ]
                   (
-                    id:=Variable [ Name=$id ]
-                    token:=Variable [ Name=$token ]
                     paper:=Variable [ Name=$paper ]
-                    tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                    lenDBLP:=Variable [ Name=$lenDBLP ]
-                    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                    idDBLP:=Variable [ Name=$idDBLP ]
-                    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                    paperCSX:=Variable [ Name=$paperCSX ]
-                    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                    paperDBLP:=Variable [ Name=$paperDBLP ]
+                    token:=Variable [ Name=$token ]
                   )
 
                 Orderby
                   FunctionCall fuzzyjoin.sql-count@1[
                     (
                       SELECT ELEMENT [
-                      FieldAccessor [
-                        Variable [ Name=#2 ]
-                        Field=id
+                      FunctionCall Metadata.dataset@1[
+                        LiteralExpr [STRING] [id]
                       ]
                       ]
                       FROM [                        Variable [ Name=#1 ]
@@ -296,30 +288,16 @@
                   Variable [ Name=$token ]
                   GROUP AS Variable [ Name=#3 ]
                   (
-                    id:=Variable [ Name=$id ]
-                    token:=Variable [ Name=$token ]
                     paper:=Variable [ Name=$paper ]
-                    tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                    lenCSX:=Variable [ Name=$lenCSX ]
-                    tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-                    idCSX:=Variable [ Name=$idCSX ]
-                    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                    lenDBLP:=Variable [ Name=$lenDBLP ]
-                    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                    idDBLP:=Variable [ Name=$idDBLP ]
-                    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                    paperCSX:=Variable [ Name=$paperCSX ]
-                    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                    paperDBLP:=Variable [ Name=$paperDBLP ]
+                    token:=Variable [ Name=$token ]
                   )
 
                 Orderby
                   FunctionCall fuzzyjoin.sql-count@1[
                     (
                       SELECT ELEMENT [
-                      FieldAccessor [
-                        Variable [ Name=#4 ]
-                        Field=id
+                      FunctionCall Metadata.dataset@1[
+                        LiteralExpr [STRING] [id]
                       ]
                       ]
                       FROM [                        Variable [ Name=#3 ]
@@ -380,19 +358,10 @@
           Variable [ Name=$idCSX ]
           GROUP AS Variable [ Name=#5 ]
           (
-            sim:=Variable [ Name=$sim ]
-            tokensCSX:=Variable [ Name=$tokensCSX ]
-            lenCSX:=Variable [ Name=$lenCSX ]
-            tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-            idCSX:=Variable [ Name=$idCSX ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
             paperDBLP:=Variable [ Name=$paperDBLP ]
+            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+            paperCSX:=Variable [ Name=$paperCSX ]
+            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
           )
 
       )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.4/dblp-csx-3_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.4/dblp-csx-3_5.3.ast
index 9545fb1..e802dde 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.4/dblp-csx-3_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5.4/dblp-csx-3_5.3.ast
@@ -87,7 +87,9 @@
             LiteralExpr [STRING] [sim]
             :
             IndexAccessor [
-              Variable [ Name=$sim ]
+              FunctionCall Metadata.dataset@1[
+                LiteralExpr [STRING] [sim]
+              ]
               Index:               LiteralExpr [LONG] [0]
             ]
           )
@@ -192,26 +194,16 @@
                   Variable [ Name=$token ]
                   GROUP AS Variable [ Name=#1 ]
                   (
-                    id:=Variable [ Name=$id ]
-                    token:=Variable [ Name=$token ]
                     paper:=Variable [ Name=$paper ]
-                    tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                    lenDBLP:=Variable [ Name=$lenDBLP ]
-                    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                    idDBLP:=Variable [ Name=$idDBLP ]
-                    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                    paperCSX:=Variable [ Name=$paperCSX ]
-                    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                    paperDBLP:=Variable [ Name=$paperDBLP ]
+                    token:=Variable [ Name=$token ]
                   )
 
                 Orderby
                   FunctionCall fuzzyjoin.sql-count@1[
                     (
                       SELECT ELEMENT [
-                      FieldAccessor [
-                        Variable [ Name=#2 ]
-                        Field=id
+                      FunctionCall Metadata.dataset@1[
+                        LiteralExpr [STRING] [id]
                       ]
                       ]
                       FROM [                        Variable [ Name=#1 ]
@@ -296,30 +288,16 @@
                   Variable [ Name=$token ]
                   GROUP AS Variable [ Name=#3 ]
                   (
-                    id:=Variable [ Name=$id ]
-                    token:=Variable [ Name=$token ]
                     paper:=Variable [ Name=$paper ]
-                    tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                    lenCSX:=Variable [ Name=$lenCSX ]
-                    tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-                    idCSX:=Variable [ Name=$idCSX ]
-                    tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                    lenDBLP:=Variable [ Name=$lenDBLP ]
-                    tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                    idDBLP:=Variable [ Name=$idDBLP ]
-                    prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                    paperCSX:=Variable [ Name=$paperCSX ]
-                    prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                    paperDBLP:=Variable [ Name=$paperDBLP ]
+                    token:=Variable [ Name=$token ]
                   )
 
                 Orderby
                   FunctionCall fuzzyjoin.sql-count@1[
                     (
                       SELECT ELEMENT [
-                      FieldAccessor [
-                        Variable [ Name=#4 ]
-                        Field=id
+                      FunctionCall Metadata.dataset@1[
+                        LiteralExpr [STRING] [id]
                       ]
                       ]
                       FROM [                        Variable [ Name=#3 ]
@@ -380,19 +358,10 @@
           Variable [ Name=$idCSX ]
           GROUP AS Variable [ Name=#5 ]
           (
-            sim:=Variable [ Name=$sim ]
-            tokensCSX:=Variable [ Name=$tokensCSX ]
-            lenCSX:=Variable [ Name=$lenCSX ]
-            tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-            idCSX:=Variable [ Name=$idCSX ]
-            tokensDBLP:=Variable [ Name=$tokensDBLP ]
-            lenDBLP:=Variable [ Name=$lenDBLP ]
-            tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-            idDBLP:=Variable [ Name=$idDBLP ]
-            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-            paperCSX:=Variable [ Name=$paperCSX ]
-            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
             paperDBLP:=Variable [ Name=$paperDBLP ]
+            prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+            paperCSX:=Variable [ Name=$paperCSX ]
+            prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
           )
 
       )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5/dblp-csx-3_5.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5/dblp-csx-3_5.3.ast
index 44ac6dd..43d5d8d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5/dblp-csx-3_5.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/fuzzyjoin/dblp-csx-3_5/dblp-csx-3_5.3.ast
@@ -145,26 +145,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#1 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#2 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#1 ]
@@ -249,30 +239,16 @@
               Variable [ Name=$token ]
               GROUP AS Variable [ Name=#3 ]
               (
-                id:=Variable [ Name=$id ]
-                token:=Variable [ Name=$token ]
                 paper:=Variable [ Name=$paper ]
-                tokenUnranked:=Variable [ Name=$tokenUnranked ]
-                lenCSX:=Variable [ Name=$lenCSX ]
-                tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-                idCSX:=Variable [ Name=$idCSX ]
-                tokensDBLP:=Variable [ Name=$tokensDBLP ]
-                lenDBLP:=Variable [ Name=$lenDBLP ]
-                tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-                idDBLP:=Variable [ Name=$idDBLP ]
-                prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-                paperCSX:=Variable [ Name=$paperCSX ]
-                prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
-                paperDBLP:=Variable [ Name=$paperDBLP ]
+                token:=Variable [ Name=$token ]
               )
 
             Orderby
               FunctionCall fuzzyjoin.sql-count@1[
                 (
                   SELECT ELEMENT [
-                  FieldAccessor [
-                    Variable [ Name=#4 ]
-                    Field=id
+                  FunctionCall Metadata.dataset@1[
+                    LiteralExpr [STRING] [id]
                   ]
                   ]
                   FROM [                    Variable [ Name=#3 ]
@@ -336,19 +312,10 @@
       Variable [ Name=$sim ]
       GROUP AS Variable [ Name=#5 ]
       (
-        sim:=Variable [ Name=$sim ]
-        tokensCSX:=Variable [ Name=$tokensCSX ]
-        lenCSX:=Variable [ Name=$lenCSX ]
-        tokensUnrankedCSX:=Variable [ Name=$tokensUnrankedCSX ]
-        idCSX:=Variable [ Name=$idCSX ]
-        tokensDBLP:=Variable [ Name=$tokensDBLP ]
-        lenDBLP:=Variable [ Name=$lenDBLP ]
-        tokensUnrankedDBLP:=Variable [ Name=$tokensUnrankedDBLP ]
-        idDBLP:=Variable [ Name=$idDBLP ]
-        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
-        paperCSX:=Variable [ Name=$paperCSX ]
-        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
         paperDBLP:=Variable [ Name=$paperDBLP ]
+        prefixTokenDBLP:=Variable [ Name=$prefixTokenDBLP ]
+        paperCSX:=Variable [ Name=$paperCSX ]
+        prefixTokenCSX:=Variable [ Name=$prefixTokenCSX ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_02/hdfs_02.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_02/hdfs_02.3.ast
index 9d99609..f1ac649 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_02/hdfs_02.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_02/hdfs_02.3.ast
@@ -11,17 +11,7 @@
     LiteralExpr [STRING] [count]
     :
     FunctionCall test.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=token
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$token ]
     ]
   )
 ]
@@ -45,8 +35,8 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    token:=Variable [ Name=$token ]
     line:=Variable [ Name=$line ]
+    token:=Variable [ Name=$token ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_03/hdfs_03.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_03/hdfs_03.3.ast
index 9d99609..f1ac649 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_03/hdfs_03.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_03/hdfs_03.3.ast
@@ -11,17 +11,7 @@
     LiteralExpr [STRING] [count]
     :
     FunctionCall test.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=token
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$token ]
     ]
   )
 ]
@@ -45,8 +35,8 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    token:=Variable [ Name=$token ]
     line:=Variable [ Name=$line ]
+    token:=Variable [ Name=$token ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_shortcircuit/hdfs_shortcircuit.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_shortcircuit/hdfs_shortcircuit.3.ast
index 9d99609..f1ac649 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_shortcircuit/hdfs_shortcircuit.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hdfs/hdfs_shortcircuit/hdfs_shortcircuit.3.ast
@@ -11,17 +11,7 @@
     LiteralExpr [STRING] [count]
     :
     FunctionCall test.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=token
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$token ]
     ]
   )
 ]
@@ -45,8 +35,8 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    token:=Variable [ Name=$token ]
     line:=Variable [ Name=$line ]
+    token:=Variable [ Name=$token ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hints/issue_251_dataset_hint_6/issue_251_dataset_hint_6.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hints/issue_251_dataset_hint_6/issue_251_dataset_hint_6.3.ast
index 9d99609..f1ac649 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hints/issue_251_dataset_hint_6/issue_251_dataset_hint_6.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/hints/issue_251_dataset_hint_6/issue_251_dataset_hint_6.3.ast
@@ -11,17 +11,7 @@
     LiteralExpr [STRING] [count]
     :
     FunctionCall test.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=token
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$token ]
     ]
   )
 ]
@@ -45,8 +35,8 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    token:=Variable [ Name=$token ]
     line:=Variable [ Name=$line ]
+    token:=Variable [ Name=$token ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/groupby-orderby-count/groupby-orderby-count.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/groupby-orderby-count/groupby-orderby-count.3.ast
index b1d80ff..259f96d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/groupby-orderby-count/groupby-orderby-count.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/misc/groupby-orderby-count/groupby-orderby-count.3.ast
@@ -11,17 +11,7 @@
     LiteralExpr [STRING] [count]
     :
     FunctionCall twitter.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#3 ]
-          Field=token
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#3 ]
-        ]
-      )
+      Variable [ Name=$token ]
     ]
   )
 ]
@@ -45,23 +35,13 @@
   Variable [ Name=$token ]
   GROUP AS Variable [ Name=#1 ]
   (
-    token:=Variable [ Name=$token ]
     t:=Variable [ Name=$t ]
+    token:=Variable [ Name=$token ]
   )
 
 Orderby
   FunctionCall twitter.count@1[
-    (
-      SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=token
-      ]
-      ]
-      FROM [        Variable [ Name=#1 ]
-        AS Variable [ Name=#2 ]
-      ]
-    )
+    Variable [ Name=$token ]
   ]
   DESC
   Variable [ Name=$tok ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/open-closed/query-issue456/query-issue456.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/open-closed/query-issue456/query-issue456.3.ast
index df48810..1dc9f40 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/open-closed/query-issue456/query-issue456.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/open-closed/query-issue456/query-issue456.3.ast
@@ -6,9 +6,8 @@
   FunctionCall test.sql-count@1[
     (
       SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=id
+      FunctionCall Metadata.dataset@1[
+        LiteralExpr [STRING] [id]
       ]
       ]
       FROM [        Variable [ Name=#1 ]
@@ -38,7 +37,6 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    id:=Variable [ Name=$id ]
     x:=Variable [ Name=$x ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/open-closed/query-proposal02/query-proposal02.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/open-closed/query-proposal02/query-proposal02.3.ast
index 94a37bf..806f0da 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/open-closed/query-proposal02/query-proposal02.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/open-closed/query-proposal02/query-proposal02.3.ast
@@ -59,8 +59,8 @@
   Variable [ Name=$reftopic ]
   GROUP AS Variable [ Name=#1 ]
   (
-    reftopic:=Variable [ Name=$reftopic ]
     tweet:=Variable [ Name=$tweet ]
+    reftopic:=Variable [ Name=$reftopic ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-no-complex-types/tiny-social-example-no-complex-types.9.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-no-complex-types/tiny-social-example-no-complex-types.9.ast
index 5e4e36a..19427c1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-no-complex-types/tiny-social-example-no-complex-types.9.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-no-complex-types/tiny-social-example-no-complex-types.9.ast
@@ -44,8 +44,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    f:=Variable [ Name=$f ]
     r:=Variable [ Name=$r ]
+    f:=Variable [ Name=$f ]
   )
 
 Let Variable [ Name=$count ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-only-lists/tiny-social-example-only-lists.9.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-only-lists/tiny-social-example-only-lists.9.ast
index 5e4e36a..19427c1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-only-lists/tiny-social-example-only-lists.9.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-only-lists/tiny-social-example-only-lists.9.ast
@@ -44,8 +44,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    f:=Variable [ Name=$f ]
     r:=Variable [ Name=$r ]
+    f:=Variable [ Name=$f ]
   )
 
 Let Variable [ Name=$count ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-only-records/tiny-social-example-only-records.9.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-only-records/tiny-social-example-only-records.9.ast
index 5e4e36a..19427c1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-only-records/tiny-social-example-only-records.9.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/records/get-record-fields/tiny-social-example-only-records/tiny-social-example-only-records.9.ast
@@ -44,8 +44,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    f:=Variable [ Name=$f ]
     r:=Variable [ Name=$r ]
+    f:=Variable [ Name=$f ]
   )
 
 Let Variable [ Name=$count ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/semistructured/count-nullable/count-nullable.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/semistructured/count-nullable/count-nullable.3.ast
index cde6b6d..5d1a417 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/semistructured/count-nullable/count-nullable.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/semistructured/count-nullable/count-nullable.3.ast
@@ -11,17 +11,7 @@
     LiteralExpr [STRING] [count]
     :
     FunctionCall test.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=c
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$c ]
     ]
   )
 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/spatial/cell-aggregation-with-filtering/cell-aggregation-with-filtering.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/spatial/cell-aggregation-with-filtering/cell-aggregation-with-filtering.3.ast
index 657dce3..91e9410 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/spatial/cell-aggregation-with-filtering/cell-aggregation-with-filtering.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/spatial/cell-aggregation-with-filtering/cell-aggregation-with-filtering.3.ast
@@ -88,25 +88,13 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    region:=Variable [ Name=$region ]
-    keywords:=Variable [ Name=$keywords ]
     t:=Variable [ Name=$t ]
   )
 
 Let Variable [ Name=$num ]
   :=
   FunctionCall test.count@1[
-    (
-      SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=t
-      ]
-      ]
-      FROM [        Variable [ Name=#1 ]
-        AS Variable [ Name=#2 ]
-      ]
-    )
+    Variable [ Name=$t ]
   ]
 Orderby
   Variable [ Name=$num ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/spatial/cell-aggregation/cell-aggregation.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/spatial/cell-aggregation/cell-aggregation.3.ast
index 193a14b..6f827cf 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/spatial/cell-aggregation/cell-aggregation.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/spatial/cell-aggregation/cell-aggregation.3.ast
@@ -45,17 +45,7 @@
     Let Variable [ Name=$num ]
       :=
       FunctionCall test.count@1[
-        (
-          SELECT ELEMENT [
-          FieldAccessor [
-            Variable [ Name=#2 ]
-            Field=o
-          ]
-          ]
-          FROM [            Variable [ Name=#1 ]
-            AS Variable [ Name=#2 ]
-          ]
-        )
+        Variable [ Name=$o ]
       ]
     Orderby
       Variable [ Name=$num ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temp-dataset/q01_pricing_summary_report_nt/q01_pricing_summary_report_nt.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temp-dataset/q01_pricing_summary_report_nt/q01_pricing_summary_report_nt.3.ast
index ae8f04d..815615d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temp-dataset/q01_pricing_summary_report_nt/q01_pricing_summary_report_nt.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temp-dataset/q01_pricing_summary_report_nt/q01_pricing_summary_report_nt.3.ast
@@ -167,17 +167,7 @@
     LiteralExpr [STRING] [count_order]
     :
     FunctionCall tpch.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=l
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$l ]
     ]
   )
 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_0/overlap_bins_gby_0.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_0/overlap_bins_gby_0.3.ast
index bff5906..cf3af4c 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_0/overlap_bins_gby_0.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_0/overlap_bins_gby_0.3.ast
@@ -88,8 +88,8 @@
       Variable [ Name=$j ]
       GROUP AS Variable [ Name=#1 ]
       (
-        j:=Variable [ Name=$j ]
         i:=Variable [ Name=$i ]
+        j:=Variable [ Name=$j ]
       )
 
     Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_1/overlap_bins_gby_1.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_1/overlap_bins_gby_1.3.ast
index 19503b9..7d10b8d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_1/overlap_bins_gby_1.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_1/overlap_bins_gby_1.3.ast
@@ -104,8 +104,8 @@
   Variable [ Name=$j ]
   GROUP AS Variable [ Name=#1 ]
   (
-    j:=Variable [ Name=$j ]
     i2:=Variable [ Name=$i2 ]
+    j:=Variable [ Name=$j ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_3/overlap_bins_gby_3.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_3/overlap_bins_gby_3.3.ast
index c43f1c7..e9435d1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_3/overlap_bins_gby_3.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/overlap_bins_gby_3/overlap_bins_gby_3.3.ast
@@ -68,7 +68,6 @@
         GROUP AS Variable [ Name=#1 ]
         (
           i:=Variable [ Name=$i ]
-          bin:=Variable [ Name=$bin ]
         )
 
       Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite-open/group-by.26.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite-open/group-by.26.ast
index db9a752..16e5ee8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite-open/group-by.26.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite-open/group-by.26.ast
@@ -113,7 +113,7 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    employment:=Variable [ Name=$employment ]
     fbu:=Variable [ Name=$fbu ]
+    employment:=Variable [ Name=$employment ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite-open/query-ASTERIXDB-1263.23.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite-open/query-ASTERIXDB-1263.23.ast
index 586630d..73652a0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite-open/query-ASTERIXDB-1263.23.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite-open/query-ASTERIXDB-1263.23.ast
@@ -51,9 +51,6 @@
     GROUP AS Variable [ Name=#2 ]
     (
       k:=Variable [ Name=$k ]
-      t:=Variable [ Name=$t ]
-      h:=Variable [ Name=$h ]
-      #1:=Variable [ Name=#1 ]
     )
 
   Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite/query-ASTERIXDB-1263.23.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite/query-ASTERIXDB-1263.23.ast
index 586630d..73652a0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite/query-ASTERIXDB-1263.23.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tinysocial/tinysocial-suite/query-ASTERIXDB-1263.23.ast
@@ -51,9 +51,6 @@
     GROUP AS Variable [ Name=#2 ]
     (
       k:=Variable [ Name=$k ]
-      t:=Variable [ Name=$t ]
-      h:=Variable [ Name=$h ]
-      #1:=Variable [ Name=#1 ]
     )
 
   Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q03_shipping_priority_nt/q03_shipping_priority_nt.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q03_shipping_priority_nt/q03_shipping_priority_nt.3.ast
index 4b04e3a..47d5a97 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q03_shipping_priority_nt/q03_shipping_priority_nt.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q03_shipping_priority_nt/q03_shipping_priority_nt.3.ast
@@ -117,9 +117,9 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    l:=Variable [ Name=$l ]
-    o:=Variable [ Name=$o ]
     c:=Variable [ Name=$c ]
+    o:=Variable [ Name=$o ]
+    l:=Variable [ Name=$l ]
   )
 
 Let Variable [ Name=$revenue ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q04_order_priority/q04_order_priority.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q04_order_priority/q04_order_priority.3.ast
index e50b0b0..6d2ab55 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q04_order_priority/q04_order_priority.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q04_order_priority/q04_order_priority.3.ast
@@ -43,17 +43,7 @@
     LiteralExpr [STRING] [count]
     :
     FunctionCall tpch.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=o
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$o ]
     ]
   )
 ]
@@ -108,8 +98,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    t:=Variable [ Name=$t ]
     o:=Variable [ Name=$o ]
+    t:=Variable [ Name=$t ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q05_local_supplier_volume/q05_local_supplier_volume.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q05_local_supplier_volume/q05_local_supplier_volume.3.ast
index fefccd1..5ee4bfe 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q05_local_supplier_volume/q05_local_supplier_volume.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q05_local_supplier_volume/q05_local_supplier_volume.3.ast
@@ -299,8 +299,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    o1:=Variable [ Name=$o1 ]
     c:=Variable [ Name=$c ]
+    o1:=Variable [ Name=$o1 ]
   )
 
 Let Variable [ Name=$revenue ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q07_volume_shipping/q07_volume_shipping.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q07_volume_shipping/q07_volume_shipping.3.ast
index f7aeb0f..cc99aab 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q07_volume_shipping/q07_volume_shipping.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q07_volume_shipping/q07_volume_shipping.3.ast
@@ -367,9 +367,8 @@
   Variable [ Name=$l_year0 ]
   GROUP AS Variable [ Name=#1 ]
   (
-    l_year0:=Variable [ Name=$l_year0 ]
-    t:=Variable [ Name=$t ]
     locs:=Variable [ Name=$locs ]
+    t:=Variable [ Name=$t ]
   )
 
 Let Variable [ Name=$revenue ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q11_important_stock/q11_important_stock.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q11_important_stock/q11_important_stock.3.ast
index 14caa44..8de0c01 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q11_important_stock/q11_important_stock.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q11_important_stock/q11_important_stock.3.ast
@@ -192,9 +192,8 @@
       ]
       GROUP AS Variable [ Name=#1 ]
       (
-        sn:=Variable [ Name=$sn ]
         ps:=Variable [ Name=$ps ]
-        sum:=Variable [ Name=$sum ]
+        sn:=Variable [ Name=$sn ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
index 3da470a..edd1cd8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q12_shipping/q12_shipping.3.ast
@@ -188,8 +188,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    o:=Variable [ Name=$o ]
     l:=Variable [ Name=$l ]
+    o:=Variable [ Name=$o ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
index 1bd404d..ed68ae8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q14_promotion_effect/q14_promotion_effect.3.ast
@@ -146,10 +146,8 @@
   Variable [ Name=$t ]
   :=
   LiteralExpr [LONG] [1]
-  GROUP AS Variable [ Name=#1 ]
+  GROUP AS Variable [ Name=$g ]
   (
     lp:=Variable [ Name=$lp ]
-    p:=Variable [ Name=$p ]
-    l:=Variable [ Name=$l ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q18_large_volume_customer/q18_large_volume_customer.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q18_large_volume_customer/q18_large_volume_customer.3.ast
index 8f4559e..1e4ac7b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q18_large_volume_customer/q18_large_volume_customer.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q18_large_volume_customer/q18_large_volume_customer.3.ast
@@ -98,8 +98,6 @@
       GROUP AS Variable [ Name=#1 ]
       (
         l:=Variable [ Name=$l ]
-        o:=Variable [ Name=$o ]
-        c:=Variable [ Name=$c ]
       )
 
   )
@@ -192,10 +190,10 @@
   ]
   GROUP AS Variable [ Name=#2 ]
   (
-    l:=Variable [ Name=$l ]
-    t:=Variable [ Name=$t ]
-    o:=Variable [ Name=$o ]
     c:=Variable [ Name=$c ]
+    o:=Variable [ Name=$o ]
+    t:=Variable [ Name=$t ]
+    l:=Variable [ Name=$l ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q21_suppliers_who_kept_orders_waiting/q21_suppliers_who_kept_orders_waiting.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q21_suppliers_who_kept_orders_waiting/q21_suppliers_who_kept_orders_waiting.3.ast
index 6d09b11..0d5ca25 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q21_suppliers_who_kept_orders_waiting/q21_suppliers_who_kept_orders_waiting.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q21_suppliers_who_kept_orders_waiting/q21_suppliers_who_kept_orders_waiting.3.ast
@@ -442,17 +442,7 @@
 Let Variable [ Name=$numwait ]
   :=
   FunctionCall tpch.count@1[
-    (
-      SELECT ELEMENT [
-      FieldAccessor [
-        Variable [ Name=#2 ]
-        Field=t4
-      ]
-      ]
-      FROM [        Variable [ Name=#1 ]
-        AS Variable [ Name=#2 ]
-      ]
-    )
+    Variable [ Name=$t4 ]
   ]
 Orderby
   Variable [ Name=$numwait ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q22_global_sales_opportunity/q22_global_sales_opportunity.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q22_global_sales_opportunity/q22_global_sales_opportunity.3.ast
index f6eaeaf..cab2a8f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q22_global_sales_opportunity/q22_global_sales_opportunity.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/q22_global_sales_opportunity/q22_global_sales_opportunity.3.ast
@@ -132,7 +132,6 @@
   GROUP AS Variable [ Name=#1 ]
   (
     ct:=Variable [ Name=$ct ]
-    avg:=Variable [ Name=$avg ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue601/query-issue601.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue601/query-issue601.3.ast
index b0c1038..758fd5a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue601/query-issue601.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue601/query-issue601.3.ast
@@ -11,17 +11,7 @@
     LiteralExpr [STRING] [count_order]
     :
     FunctionCall tpch.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=l
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$l ]
     ]
   )
 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue785-2/query-issue785-2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue785-2/query-issue785-2.3.ast
index 97006bf..991c38a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue785-2/query-issue785-2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue785-2/query-issue785-2.3.ast
@@ -122,10 +122,9 @@
       ]
       GROUP AS Variable [ Name=#1 ]
       (
-        orders:=Variable [ Name=$orders ]
-        customer:=Variable [ Name=$customer ]
         n:=Variable [ Name=$n ]
-        t:=Variable [ Name=$t ]
+        customer:=Variable [ Name=$customer ]
+        orders:=Variable [ Name=$orders ]
       )
 
     Let Variable [ Name=$sum ]
@@ -204,7 +203,5 @@
   GROUP AS Variable [ Name=#2 ]
   (
     x:=Variable [ Name=$x ]
-    X:=Variable [ Name=$X ]
-    t:=Variable [ Name=$t ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue785/query-issue785.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue785/query-issue785.3.ast
index 602feb1..61e0ca4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue785/query-issue785.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue785/query-issue785.3.ast
@@ -38,9 +38,6 @@
         GROUP AS Variable [ Name=#3 ]
         (
           i:=Variable [ Name=$i ]
-          x:=Variable [ Name=$x ]
-          nation_key:=Variable [ Name=$nation_key ]
-          #2:=Variable [ Name=#2 ]
         )
 
       Let Variable [ Name=$sum ]
@@ -156,9 +153,9 @@
       ]
       GROUP AS Variable [ Name=#1 ]
       (
-        orders:=Variable [ Name=$orders ]
-        customer:=Variable [ Name=$customer ]
         n:=Variable [ Name=$n ]
+        customer:=Variable [ Name=$customer ]
+        orders:=Variable [ Name=$orders ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue786/query-issue786.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue786/query-issue786.3.ast
index 2c51fb4..5908531 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue786/query-issue786.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch-sql-like/query-issue786/query-issue786.3.ast
@@ -81,10 +81,8 @@
         ]
         GROUP AS Variable [ Name=#1 ]
         (
-          customer:=Variable [ Name=$customer ]
           orders:=Variable [ Name=$orders ]
-          sn:=Variable [ Name=$sn ]
-          nation:=Variable [ Name=$nation ]
+          customer:=Variable [ Name=$customer ]
         )
 
       Let Variable [ Name=$sum ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/nest_aggregate/nest_aggregate.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/nest_aggregate/nest_aggregate.3.ast
index 2c323ea..0207a57 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/nest_aggregate/nest_aggregate.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/nest_aggregate/nest_aggregate.3.ast
@@ -81,10 +81,8 @@
         ]
         GROUP AS Variable [ Name=#1 ]
         (
-          customer:=Variable [ Name=$customer ]
           orders:=Variable [ Name=$orders ]
-          sn:=Variable [ Name=$sn ]
-          nation:=Variable [ Name=$nation ]
+          customer:=Variable [ Name=$customer ]
         )
 
       Let Variable [ Name=$sum ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q01_pricing_summary_report_nt/q01_pricing_summary_report_nt.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q01_pricing_summary_report_nt/q01_pricing_summary_report_nt.3.ast
index ae8f04d..815615d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q01_pricing_summary_report_nt/q01_pricing_summary_report_nt.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q01_pricing_summary_report_nt/q01_pricing_summary_report_nt.3.ast
@@ -167,17 +167,7 @@
     LiteralExpr [STRING] [count_order]
     :
     FunctionCall tpch.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=l
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$l ]
     ]
   )
 ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q03_shipping_priority_nt/q03_shipping_priority_nt.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q03_shipping_priority_nt/q03_shipping_priority_nt.3.ast
index 4b04e3a..47d5a97 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q03_shipping_priority_nt/q03_shipping_priority_nt.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q03_shipping_priority_nt/q03_shipping_priority_nt.3.ast
@@ -117,9 +117,9 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    l:=Variable [ Name=$l ]
-    o:=Variable [ Name=$o ]
     c:=Variable [ Name=$c ]
+    o:=Variable [ Name=$o ]
+    l:=Variable [ Name=$l ]
   )
 
 Let Variable [ Name=$revenue ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q04_order_priority/q04_order_priority.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q04_order_priority/q04_order_priority.3.ast
index 30df063..14ee9fc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q04_order_priority/q04_order_priority.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q04_order_priority/q04_order_priority.3.ast
@@ -108,8 +108,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    t:=Variable [ Name=$t ]
     o:=Variable [ Name=$o ]
+    t:=Variable [ Name=$t ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q05_local_supplier_volume/q05_local_supplier_volume.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q05_local_supplier_volume/q05_local_supplier_volume.3.ast
index fefccd1..5ee4bfe 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q05_local_supplier_volume/q05_local_supplier_volume.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q05_local_supplier_volume/q05_local_supplier_volume.3.ast
@@ -299,8 +299,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    o1:=Variable [ Name=$o1 ]
     c:=Variable [ Name=$c ]
+    o1:=Variable [ Name=$o1 ]
   )
 
 Let Variable [ Name=$revenue ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q07_volume_shipping/q07_volume_shipping.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q07_volume_shipping/q07_volume_shipping.3.ast
index f7aeb0f..cc99aab 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q07_volume_shipping/q07_volume_shipping.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q07_volume_shipping/q07_volume_shipping.3.ast
@@ -367,9 +367,8 @@
   Variable [ Name=$l_year0 ]
   GROUP AS Variable [ Name=#1 ]
   (
-    l_year0:=Variable [ Name=$l_year0 ]
-    t:=Variable [ Name=$t ]
     locs:=Variable [ Name=$locs ]
+    t:=Variable [ Name=$t ]
   )
 
 Let Variable [ Name=$revenue ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q11_important_stock/q11_important_stock.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q11_important_stock/q11_important_stock.3.ast
index 14caa44..8de0c01 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q11_important_stock/q11_important_stock.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q11_important_stock/q11_important_stock.3.ast
@@ -192,9 +192,8 @@
       ]
       GROUP AS Variable [ Name=#1 ]
       (
-        sn:=Variable [ Name=$sn ]
         ps:=Variable [ Name=$ps ]
-        sum:=Variable [ Name=$sum ]
+        sn:=Variable [ Name=$sn ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
index 6ad3a5b..fa86271 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q12_shipping/q12_shipping.3.ast
@@ -185,8 +185,8 @@
   ]
   GROUP AS Variable [ Name=#1 ]
   (
-    o:=Variable [ Name=$o ]
     l:=Variable [ Name=$l ]
+    o:=Variable [ Name=$o ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
index f619293..e52e659 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q14_promotion_effect/q14_promotion_effect.3.ast
@@ -143,10 +143,8 @@
   Variable [ Name=$t ]
   :=
   LiteralExpr [LONG] [1]
-  GROUP AS Variable [ Name=#1 ]
+  GROUP AS Variable [ Name=$g ]
   (
     lp:=Variable [ Name=$lp ]
-    p:=Variable [ Name=$p ]
-    l:=Variable [ Name=$l ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q17_large_gby_variant/q17_large_gby_variant.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q17_large_gby_variant/q17_large_gby_variant.3.ast
index 4c84266..c5ed1ef 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q17_large_gby_variant/q17_large_gby_variant.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q17_large_gby_variant/q17_large_gby_variant.3.ast
@@ -11,17 +11,7 @@
     LiteralExpr [STRING] [t_count]
     :
     FunctionCall tpch.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=l
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$l ]
     ]
   )
   (
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q18_large_volume_customer/q18_large_volume_customer.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q18_large_volume_customer/q18_large_volume_customer.3.ast
index d220f48..a6eebfd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q18_large_volume_customer/q18_large_volume_customer.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q18_large_volume_customer/q18_large_volume_customer.3.ast
@@ -98,8 +98,6 @@
       GROUP AS Variable [ Name=#1 ]
       (
         l:=Variable [ Name=$l ]
-        o:=Variable [ Name=$o ]
-        c:=Variable [ Name=$c ]
       )
 
   )
@@ -190,10 +188,10 @@
   ]
   GROUP AS Variable [ Name=#2 ]
   (
-    l:=Variable [ Name=$l ]
-    t:=Variable [ Name=$t ]
-    o:=Variable [ Name=$o ]
     c:=Variable [ Name=$c ]
+    o:=Variable [ Name=$o ]
+    t:=Variable [ Name=$t ]
+    l:=Variable [ Name=$l ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q22_global_sales_opportunity/q22_global_sales_opportunity.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q22_global_sales_opportunity/q22_global_sales_opportunity.3.ast
index 5032a49..b7ff109 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q22_global_sales_opportunity/q22_global_sales_opportunity.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/q22_global_sales_opportunity/q22_global_sales_opportunity.3.ast
@@ -77,17 +77,7 @@
     LiteralExpr [STRING] [numcust]
     :
     FunctionCall tpch.count@1[
-      (
-        SELECT ELEMENT [
-        FieldAccessor [
-          Variable [ Name=#2 ]
-          Field=ct
-        ]
-        ]
-        FROM [          Variable [ Name=#1 ]
-          AS Variable [ Name=#2 ]
-        ]
-      )
+      Variable [ Name=$ct ]
     ]
   )
   (
@@ -132,7 +122,6 @@
   GROUP AS Variable [ Name=#1 ]
   (
     ct:=Variable [ Name=$ct ]
-    avg:=Variable [ Name=$avg ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue562/query-issue562.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue562/query-issue562.3.ast
index fd595c3..cac889b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue562/query-issue562.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue562/query-issue562.3.ast
@@ -255,7 +255,6 @@
   GROUP AS Variable [ Name=#1 ]
   (
     ct:=Variable [ Name=$ct ]
-    avg:=Variable [ Name=$avg ]
   )
 
 Orderby
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue785-2/query-issue785-2.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue785-2/query-issue785-2.3.ast
index 97006bf..991c38a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue785-2/query-issue785-2.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue785-2/query-issue785-2.3.ast
@@ -122,10 +122,9 @@
       ]
       GROUP AS Variable [ Name=#1 ]
       (
-        orders:=Variable [ Name=$orders ]
-        customer:=Variable [ Name=$customer ]
         n:=Variable [ Name=$n ]
-        t:=Variable [ Name=$t ]
+        customer:=Variable [ Name=$customer ]
+        orders:=Variable [ Name=$orders ]
       )
 
     Let Variable [ Name=$sum ]
@@ -204,7 +203,5 @@
   GROUP AS Variable [ Name=#2 ]
   (
     x:=Variable [ Name=$x ]
-    X:=Variable [ Name=$X ]
-    t:=Variable [ Name=$t ]
   )
 
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue785/query-issue785.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue785/query-issue785.3.ast
index 602feb1..61e0ca4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue785/query-issue785.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue785/query-issue785.3.ast
@@ -38,9 +38,6 @@
         GROUP AS Variable [ Name=#3 ]
         (
           i:=Variable [ Name=$i ]
-          x:=Variable [ Name=$x ]
-          nation_key:=Variable [ Name=$nation_key ]
-          #2:=Variable [ Name=#2 ]
         )
 
       Let Variable [ Name=$sum ]
@@ -156,9 +153,9 @@
       ]
       GROUP AS Variable [ Name=#1 ]
       (
-        orders:=Variable [ Name=$orders ]
-        customer:=Variable [ Name=$customer ]
         n:=Variable [ Name=$n ]
+        customer:=Variable [ Name=$customer ]
+        orders:=Variable [ Name=$orders ]
       )
 
   )
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue786/query-issue786.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue786/query-issue786.3.ast
index 2c51fb4..5908531 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue786/query-issue786.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/tpch/query-issue786/query-issue786.3.ast
@@ -81,10 +81,8 @@
         ]
         GROUP AS Variable [ Name=#1 ]
         (
-          customer:=Variable [ Name=$customer ]
           orders:=Variable [ Name=$orders ]
-          sn:=Variable [ Name=$sn ]
-          nation:=Variable [ Name=$nation ]
+          customer:=Variable [ Name=$customer ]
         )
 
       Let Variable [ Name=$sum ]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
index 862ca26..cf5bda3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -3257,6 +3257,11 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="misc">
+      <compilation-unit name="query-ASTERIXDB-971">
+        <output-dir compare="Text">query-ASTERIXDB-971-aql</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
       <compilation-unit name="query-ASTERIXDB-1531">
         <output-dir compare="Text">query-ASTERIXDB-1531</output-dir>
       </compilation-unit>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 7d2af51..e0e6e87 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -1364,7 +1364,7 @@
     <test-case FilePath="custord">
       <compilation-unit name="join_q_09">
         <output-dir compare="Text">join_q_01</output-dir>
-        <expected-error>Cannot resolve ambiguous alias (variable) reference for identifier age</expected-error>
+        <expected-error>Cannot resolve ambiguous alias reference for undefined identifier age</expected-error>
       </compilation-unit>
     </test-case>
     <test-case FilePath="custord">
@@ -1420,6 +1420,12 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="dapd">
+      <compilation-unit name="q2-2-negative">
+        <output-dir compare="Text">q2</output-dir>
+        <expected-error>Cannot find dataset e in dataverse test nor an alias with name e</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="dapd">
       <compilation-unit name="q2-3">
         <output-dir compare="Text">q2</output-dir>
       </compilation-unit>
@@ -1439,6 +1445,36 @@
         <output-dir compare="Text">q2</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="dapd">
+      <compilation-unit name="q2-7">
+        <output-dir compare="Text">q2-7</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="dapd">
+      <compilation-unit name="q2-8">
+        <output-dir compare="Text">q2</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="dapd">
+      <compilation-unit name="q2-9">
+        <output-dir compare="Text">q2-9</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="dapd">
+      <compilation-unit name="q2-10">
+        <output-dir compare="Text">q2</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="dapd">
+      <compilation-unit name="q2-11">
+        <output-dir compare="Text">q2</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="dapd">
+      <compilation-unit name="q2-12">
+        <output-dir compare="Text">q2-12</output-dir>
+      </compilation-unit>
+    </test-case>
     <!--
         <test-case FilePath="dapd">
           <compilation-unit name="q3">
@@ -2355,7 +2391,7 @@
     <test-case FilePath="global-aggregate">
       <compilation-unit name="q05_error">
         <output-dir compare="Text">q01</output-dir>
-        <expected-error>The first argument should be a RECORD, but it is [ FacebookUserType: open</expected-error>
+        <expected-error>The first argument of a field access should be a RECORD, but it is [ FacebookUserType: open</expected-error>
       </compilation-unit>
     </test-case>
     <test-case FilePath="global-aggregate">
@@ -2375,6 +2411,16 @@
         <output-dir compare="Text">q08</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="global-aggregate">
+      <compilation-unit name="q09">
+        <output-dir compare="Text">q09</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="global-aggregate">
+      <compilation-unit name="q10">
+        <output-dir compare="Text">q09</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="group-by">
     <test-case FilePath="group-by">
@@ -2408,6 +2454,12 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="group-by">
+      <compilation-unit name="sugar-01-negative">
+        <output-dir compare="Text">core-01</output-dir>
+        <expected-error>The first argument of a field access should be a RECORD, but it is [ EmpType</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="group-by">
       <compilation-unit name="sugar-01-2">
         <output-dir compare="Text">core-01</output-dir>
       </compilation-unit>
@@ -2983,6 +3035,11 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="misc">
+      <compilation-unit name="query-ASTERIXDB-971">
+        <output-dir compare="Text">query-ASTERIXDB-971-sqlpp</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="misc">
       <compilation-unit name="query-ASTERIXDB-1531">
         <output-dir compare="Text">query-ASTERIXDB-1531</output-dir>
       </compilation-unit>
@@ -7650,7 +7707,7 @@
     <test-case FilePath="union">
       <compilation-unit name="union_negative_2">
         <output-dir compare="Text">union</output-dir>
-        <expected-error>Undefined alias (variable) reference for identifier t</expected-error>
+        <expected-error>Cannot find dataset t in dataverse TinySocial nor an alias with name t</expected-error>
       </compilation-unit>
     </test-case>
     <test-case FilePath="union">
diff --git a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLToSQLPPPrintVisitor.java b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLToSQLPPPrintVisitor.java
index 2af2816..0525f80 100644
--- a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLToSQLPPPrintVisitor.java
+++ b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLToSQLPPPrintVisitor.java
@@ -406,7 +406,7 @@
         for (GbyVariableExpressionPair keyPair : gbyClause.getDecorPairList()) {
             producedVars.add(keyPair.getVar());
         }
-        producedVars.addAll(gbyClause.getWithVarList());
+        producedVars.addAll(gbyClause.getWithVarMap().values());
         return producedVars;
     }
 
diff --git a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
index b690f03..9cffda0 100644
--- a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
+++ b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
@@ -2409,7 +2409,7 @@
     // GbyVariableExpressionPair pair = new GbyVariableExpressionPair();
     List<GbyVariableExpressionPair> vePairList = new ArrayList<GbyVariableExpressionPair>();
     List<GbyVariableExpressionPair> decorPairList = new ArrayList<GbyVariableExpressionPair>();
-    List<VariableExpr> withVarList= new ArrayList<VariableExpr>();
+    Map<Expression, VariableExpr> withVarMap = new HashMap<Expression, VariableExpr>();
     VariableExpr var = null;
     VariableExpr withVar = null;
     Expression expr = null;
@@ -2465,20 +2465,20 @@
     {
       if(withVar.getIsNewVar()==true)
           throw new ParseException("can't find variable " + withVar.getVar());
-      withVarList.add(withVar);
+      withVarMap.put(withVar, withVar);
       newScope.addNewVarSymbolToScope(withVar.getVar());
     }
     (<COMMA> withVar = VariableRef()
     {
       if(withVar.getIsNewVar()==true)
           throw new ParseException("can't find variable " + withVar.getVar());
-      withVarList.add(withVar);
+      withVarMap.put(withVar, withVar);
       newScope.addNewVarSymbolToScope(withVar.getVar());
     })*
     {
       gbc.setGbyPairList(vePairList);
       gbc.setDecorPairList(decorPairList);
-      gbc.setWithVarList(withVarList);
+      gbc.setWithVarMap(withVarMap);
       replaceCurrentScope(newScope);
       return gbc;
     }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/clause/GroupbyClause.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/clause/GroupbyClause.java
index 3565c5a..0f75839 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/clause/GroupbyClause.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/clause/GroupbyClause.java
@@ -20,6 +20,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.lang.common.base.Clause;
@@ -35,7 +36,7 @@
 
     private List<GbyVariableExpressionPair> gbyPairList;
     private List<GbyVariableExpressionPair> decorPairList;
-    private List<VariableExpr> withVarList;
+    private Map<Expression, VariableExpr> withVarMap;
     private VariableExpr groupVar;
     private List<Pair<Expression, Identifier>> groupFieldList = new ArrayList<>();
     private boolean hashGroupByHint;
@@ -46,17 +47,17 @@
     }
 
     public GroupbyClause(List<GbyVariableExpressionPair> gbyPairList, List<GbyVariableExpressionPair> decorPairList,
-            List<VariableExpr> withVarList, VariableExpr groupVarExpr,
+            Map<Expression, VariableExpr> withVarList, VariableExpr groupVarExpr,
             List<Pair<Expression, Identifier>> groupFieldList, boolean hashGroupByHint) {
         this(gbyPairList, decorPairList, withVarList, groupVarExpr, groupFieldList, hashGroupByHint, false);
     }
 
     public GroupbyClause(List<GbyVariableExpressionPair> gbyPairList, List<GbyVariableExpressionPair> decorPairList,
-            List<VariableExpr> withVarList, VariableExpr groupVarExpr,
+            Map<Expression, VariableExpr> withVarList, VariableExpr groupVarExpr,
             List<Pair<Expression, Identifier>> groupFieldList, boolean hashGroupByHint, boolean groupAll) {
         this.gbyPairList = gbyPairList;
         this.decorPairList = decorPairList;
-        this.withVarList = withVarList;
+        this.withVarMap = withVarList;
         this.groupVar = groupVarExpr;
         if (groupFieldList != null) {
             this.groupFieldList = groupFieldList;
@@ -73,12 +74,12 @@
         this.gbyPairList = vePairList;
     }
 
-    public List<VariableExpr> getWithVarList() {
-        return withVarList;
+    public Map<Expression, VariableExpr> getWithVarMap() {
+        return withVarMap;
     }
 
-    public void setWithVarList(List<VariableExpr> withVarList) {
-        this.withVarList = withVarList;
+    public void setWithVarMap(Map<Expression, VariableExpr> withVarList) {
+        this.withVarMap = withVarList;
     }
 
     public VariableExpr getGroupVar() {
@@ -127,8 +128,8 @@
         return decorPairList != null && !decorPairList.isEmpty();
     }
 
-    public boolean hasWithList() {
-        return withVarList != null && !withVarList.isEmpty();
+    public boolean hasWithMap() {
+        return withVarMap != null && !withVarMap.isEmpty();
     }
 
     public boolean hasGroupVar() {
@@ -146,7 +147,7 @@
     @Override
     public int hashCode() {
         return ObjectUtils.hashCodeMulti(decorPairList, gbyPairList, groupAll, groupFieldList, groupVar,
-                hashGroupByHint, withVarList);
+                hashGroupByHint, withVarMap);
     }
 
     @Override
@@ -162,6 +163,6 @@
                 && ObjectUtils.equals(gbyPairList, target.gbyPairList) && groupAll == target.groupAll
                 && ObjectUtils.equals(groupFieldList, target.groupFieldList);
         return equals && ObjectUtils.equals(groupVar, target.groupVar) && hashGroupByHint == target.hashGroupByHint
-                && ObjectUtils.equals(withVarList, target.withVarList);
+                && ObjectUtils.equals(withVarMap, target.withVarMap);
     }
 }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/context/Scope.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/context/Scope.java
index 595fb11..97cad5e 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/context/Scope.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/context/Scope.java
@@ -224,4 +224,8 @@
         }
         return vars;
     }
+
+    public Scope getParentScope(){
+        return parent;
+    }
 }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/VariableExpr.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/VariableExpr.java
index 534c74f..dbaea37 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/VariableExpr.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/VariableExpr.java
@@ -27,7 +27,6 @@
 public class VariableExpr implements Expression {
     private VarIdentifier var;
     private boolean isNewVar;
-    private boolean namedValueAccess = false;
 
     public VariableExpr() {
         super();
@@ -66,14 +65,6 @@
         return visitor.visit(this, arg);
     }
 
-    public void setNamedValueAccess(boolean namedValueAccess) {
-        this.namedValueAccess = namedValueAccess;
-    }
-
-    public boolean namedValueAccess() {
-        return namedValueAccess;
-    }
-
     @Override
     public int hashCode() {
         return ObjectUtils.hashCode(var);
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/ExpressionSubstitutionEnvironment.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/ExpressionSubstitutionEnvironment.java
deleted file mode 100644
index 8f5597f..0000000
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/rewrites/ExpressionSubstitutionEnvironment.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.asterix.lang.common.rewrites;
-
-import java.util.ArrayDeque;
-import java.util.Collection;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.ILangExpression;
-import org.apache.asterix.lang.common.expression.VariableExpr;
-
-import com.google.common.collect.HashMultiset;
-import com.google.common.collect.Multiset;
-
-/**
- * This class is in charge of substitute expressions by a given mapping while
- * traversing a given AST. The traversal and expression substitution should
- * be based on the correct variable scoping. In order to support scoping at the
- * caller, this class provides methods like mark, reset and pop.
- */
-public class ExpressionSubstitutionEnvironment {
-
-    @FunctionalInterface
-    public static interface FreeVariableCollector {
-        public Collection<VariableExpr> getFreeVariable(ILangExpression expr) throws AsterixException;
-    }
-
-    @FunctionalInterface
-    public static interface DeepCopier {
-        public ILangExpression deepCopy(ILangExpression expr) throws AsterixException;
-    }
-
-    private Map<Expression, Expression> exprMap = new HashMap<>();
-    private Map<VariableExpr, Expression> freeVarToExprMap = new HashMap<>();
-
-    // We use multiset here because variables can be defined multiple times
-    // in the scope stack.
-    private Multiset<Expression> disabledExpr = HashMultiset.create();
-
-    // Snapshots of variables that should be disabled for replacement,
-    // e.g., if a variable is redefined in a closer scope.
-    private Deque<Multiset<Expression>> disabledExprBackup = new ArrayDeque<>();
-
-    public ExpressionSubstitutionEnvironment() {
-        // Default constructor.
-    }
-
-    public ExpressionSubstitutionEnvironment(Map<Expression, Expression> map, FreeVariableCollector freeVarCollector)
-            throws AsterixException {
-        addMapping(map, freeVarCollector);
-    }
-
-    /**
-     * Finds a substitution expression.
-     *
-     * @param expr
-     *            the original expression.
-     * @return the new, replaced expression.
-     */
-    public Expression findSubstitution(Expression expr, DeepCopier deepCopier) throws AsterixException {
-        Expression replacementExpr = exprMap.get(expr);
-        if (replacementExpr != null && !disabledExpr.contains(replacementExpr)) {
-            return (Expression) deepCopier.deepCopy(replacementExpr);
-        }
-        return expr;
-    }
-
-    /**
-     * Disable a substitution when a free variable in the expression is re-defined.
-     *
-     * @param var
-     *            a re-defined variable.
-     */
-    public void disableVariable(VariableExpr var) {
-        Expression expr = freeVarToExprMap.get(var);
-        if (expr != null) {
-            disabledExpr.add(expr);
-        }
-    }
-
-    /**
-     * Re-enable a substitution when a re-defined variable exits its scope.
-     *
-     * @param var
-     *            a re-defined variable.
-     */
-    public void enableVariable(VariableExpr var) {
-        Expression expr = freeVarToExprMap.get(var);
-        if (expr != null) {
-            disabledExpr.remove(expr);
-        }
-    }
-
-    /**
-     * Tasks a snapshot of the current states.
-     *
-     * @return the snapshot id that can be reset to in the future.
-     */
-    public int mark() {
-        Multiset<Expression> copyOfDisabledExprs = HashMultiset.create();
-        copyOfDisabledExprs.addAll(disabledExpr);
-        disabledExprBackup.push(copyOfDisabledExprs);
-        return disabledExprBackup.size() - 1;
-    }
-
-    /**
-     * Resets the internal states to a snapshot.
-     *
-     * @param depth,
-     *            the snapshot id that the caller wants to recover to.
-     */
-    public void reset(int depth) {
-        while (disabledExprBackup.size() > depth) {
-            disabledExpr = disabledExprBackup.pop();
-        }
-    }
-
-    /**
-     * Restores to the most-recent snapshot.
-     */
-    public void pop() {
-        if (!disabledExprBackup.isEmpty()) {
-            disabledExpr = disabledExprBackup.pop();
-        }
-    }
-
-    @Override
-    public String toString() {
-        return exprMap.toString();
-    }
-
-    private void addMapping(Map<Expression, Expression> map, FreeVariableCollector freeVarCollector)
-            throws AsterixException {
-        exprMap.putAll(map);
-        // Put free variable to target expression map.
-        for (Entry<Expression, Expression> entry : map.entrySet()) {
-            Expression targetExpr = entry.getKey();
-            for (VariableExpr freeVar : freeVarCollector.getFreeVariable(targetExpr)) {
-                freeVarToExprMap.put(freeVar, targetExpr);
-            }
-        }
-    }
-
-}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/struct/VarIdentifier.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/struct/VarIdentifier.java
index a217bea..c2a6f38 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/struct/VarIdentifier.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/struct/VarIdentifier.java
@@ -22,22 +22,32 @@
 
 public final class VarIdentifier extends Identifier {
     private int id = 0;
+    private boolean namedValueAccess = false;
 
     public VarIdentifier() {
         super();
     }
 
+    public VarIdentifier(VarIdentifier v){
+        this(v.getValue(), v.getId(), v.namedValueAccess());
+    }
+
     public VarIdentifier(String value) {
-        super();
-        this.value = value;
+        this(value, 0);
     }
 
     public VarIdentifier(String value, int id) {
+        this(value, id, false);
+    }
+
+    private VarIdentifier(String value, int id, boolean namedValueAccess) {
         super();
         this.value = value;
         this.id = id;
+        this.namedValueAccess = namedValueAccess;
     }
 
+
     public void setId(int id) {
         this.id = id;
     }
@@ -53,6 +63,14 @@
         return vi;
     }
 
+    public void setNamedValueAccess(boolean namedValueAccess) {
+        this.namedValueAccess = namedValueAccess;
+    }
+
+    public boolean namedValueAccess() {
+        return namedValueAccess;
+    }
+
     @Override
     public int hashCode() {
         return ObjectUtils.hashCodeMulti(value);
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
index 9ffcf8d..3fdb141 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
@@ -19,8 +19,10 @@
 package org.apache.asterix.lang.common.visitor;
 
 import java.util.ArrayList;
-import java.util.LinkedList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.lang.common.base.Expression;
@@ -88,15 +90,12 @@
         if (gc.hasGroupVar()) {
             newGroupVar = generateNewVariable(context, gc.getGroupVar());
         }
-        List<VariableExpr> wList = new LinkedList<>();
-        if (gc.hasWithList()) {
-            for (VariableExpr w : gc.getWithVarList()) {
-                VarIdentifier newVar = context.getRewrittenVar(w.getVar().getId());
-                if (newVar == null) {
-                    throw new AsterixException("Could not find a rewritten variable identifier for " + w);
-                }
-                VariableExpr newWithVar = new VariableExpr(newVar);
-                wList.add(newWithVar);
+        Map<Expression, VariableExpr> newWithMap = new HashMap<>();
+        if (gc.hasWithMap()) {
+            for (Entry<Expression, VariableExpr> entry : gc.getWithVarMap().entrySet()) {
+                Expression newKeyVar = (Expression) entry.getKey().accept(this, env).first;
+                VariableExpr newValueVar = generateNewVariable(context, entry.getValue());
+                newWithMap.put(newKeyVar, newValueVar);
             }
         }
         List<Pair<Expression, Identifier>> newGroupFieldList = new ArrayList<>();
@@ -106,7 +105,7 @@
                 newGroupFieldList.add(new Pair<Expression, Identifier>(newExpr, varId.second));
             }
         }
-        GroupbyClause newGroup = new GroupbyClause(newGbyList, newDecorList, wList, newGroupVar, newGroupFieldList,
+        GroupbyClause newGroup = new GroupbyClause(newGbyList, newDecorList, newWithMap, newGroupVar, newGroupFieldList,
                 gc.hasHashGroupByHint(), gc.isGroupAll());
         return new Pair<>(newGroup, newSubs);
     }
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
index 54795bc..5feb61b 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
@@ -25,6 +25,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 import org.apache.asterix.common.config.DatasetConfig.DatasetType;
@@ -327,9 +328,23 @@
             out.print(" decor ");
             printDelimitedGbyExpressions(gc.getDecorPairList(), step + 2);
         }
-        if (gc.hasWithList()) {
+        if (gc.hasWithMap()) {
             out.print(" with ");
-            this.printDelimitedExpressions(gc.getWithVarList(), COMMA, step + 2);
+            Map<Expression, VariableExpr> withVarMap = gc.getWithVarMap();
+            int index = 0;
+            int size = withVarMap.size();
+            for (Entry<Expression, VariableExpr> entry : withVarMap.entrySet()) {
+                Expression key = entry.getKey();
+                VariableExpr value = entry.getValue();
+                key.accept(this, step + 2);
+                if (!key.equals(value)) {
+                    out.print(" as ");
+                    value.accept(this, step + 2);
+                }
+                if (++index < size) {
+                    out.print(COMMA);
+                }
+            }
         }
         out.println();
         return null;
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java
index a32a3c8..a5c9efc 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java
@@ -21,6 +21,7 @@
 import java.io.PrintWriter;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map.Entry;
 
 import org.apache.asterix.common.config.DatasetConfig.DatasetType;
 import org.apache.asterix.common.exceptions.AsterixException;
@@ -251,10 +252,16 @@
                 pair.getExpr().accept(this, step + 1);
             }
         }
-        if (gc.hasWithList()) {
+        if (gc.hasWithMap()) {
             out.println(skip(step + 1) + "With");
-            for (VariableExpr exp : gc.getWithVarList()) {
-                exp.accept(this, step + 1);
+            for (Entry<Expression, VariableExpr> entry : gc.getWithVarMap().entrySet()) {
+                Expression key = entry.getKey();
+                VariableExpr value = entry.getValue();
+                key.accept(this, step + 1);
+                if (!key.equals(value)) {
+                    out.println(skip(step + 1) + "AS");
+                    value.accept(this, step + 1);
+                }
             }
         }
         out.println();
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/SubstituteExpressionVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/SubstituteExpressionVisitor.java
deleted file mode 100644
index 073e413..0000000
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/SubstituteExpressionVisitor.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.asterix.lang.common.visitor;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.clause.LetClause;
-import org.apache.asterix.lang.common.clause.LimitClause;
-import org.apache.asterix.lang.common.clause.OrderbyClause;
-import org.apache.asterix.lang.common.clause.WhereClause;
-import org.apache.asterix.lang.common.expression.CallExpr;
-import org.apache.asterix.lang.common.expression.FieldAccessor;
-import org.apache.asterix.lang.common.expression.FieldBinding;
-import org.apache.asterix.lang.common.expression.IfExpr;
-import org.apache.asterix.lang.common.expression.IndexAccessor;
-import org.apache.asterix.lang.common.expression.ListConstructor;
-import org.apache.asterix.lang.common.expression.LiteralExpr;
-import org.apache.asterix.lang.common.expression.OperatorExpr;
-import org.apache.asterix.lang.common.expression.QuantifiedExpression;
-import org.apache.asterix.lang.common.expression.RecordConstructor;
-import org.apache.asterix.lang.common.expression.UnaryExpr;
-import org.apache.asterix.lang.common.expression.VariableExpr;
-import org.apache.asterix.lang.common.rewrites.ExpressionSubstitutionEnvironment;
-import org.apache.asterix.lang.common.rewrites.ExpressionSubstitutionEnvironment.DeepCopier;
-import org.apache.asterix.lang.common.statement.FunctionDecl;
-import org.apache.asterix.lang.common.statement.Query;
-import org.apache.asterix.lang.common.struct.QuantifiedPair;
-import org.apache.asterix.lang.common.visitor.base.AbstractQueryExpressionVisitor;
-
-public abstract class SubstituteExpressionVisitor
-        extends AbstractQueryExpressionVisitor<Expression, ExpressionSubstitutionEnvironment> {
-    protected final DeepCopier deepCopier;
-
-    public SubstituteExpressionVisitor(DeepCopier deepCopier) {
-        this.deepCopier = deepCopier;
-    }
-
-    @Override
-    public Expression visit(LetClause lc, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        // Marks the binding variable for future visiting until it exists its scope.
-        env.disableVariable(lc.getVarExpr());
-        lc.setBindingExpr(lc.getBindingExpr().accept(this, env));
-        return null;
-    }
-
-    @Override
-    public Expression visit(Query q, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        q.setBody(q.getBody().accept(this, env));
-        return null;
-    }
-
-    @Override
-    public Expression visit(FunctionDecl fd, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        // Do nothing for a function declaration.
-        return null;
-    }
-
-    @Override
-    public Expression visit(LiteralExpr l, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        return env.findSubstitution(l, deepCopier);
-    }
-
-    @Override
-    public Expression visit(VariableExpr v, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        return env.findSubstitution(v, deepCopier);
-    }
-
-    @Override
-    public Expression visit(ListConstructor lc, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newLc = env.findSubstitution(lc, deepCopier);
-        if (newLc == lc) {
-            lc.setExprList(rewriteExpressionList(lc.getExprList(), env));
-            return lc;
-        } else {
-            return newLc.accept(this, env);
-        }
-    }
-
-    @Override
-    public Expression visit(RecordConstructor rc, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newRc = env.findSubstitution(rc, deepCopier);
-        if (newRc == rc) {
-            for (FieldBinding fb : rc.getFbList()) {
-                fb.setLeftExpr(fb.getLeftExpr().accept(this, env));
-                fb.setRightExpr(fb.getRightExpr().accept(this, env));
-            }
-            return rc;
-        } else {
-            return newRc.accept(this, env);
-        }
-    }
-
-    @Override
-    public Expression visit(OperatorExpr operatorExpr, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newOpertorExpr = env.findSubstitution(operatorExpr, deepCopier);
-        if (newOpertorExpr == operatorExpr) {
-            operatorExpr.setExprList(rewriteExpressionList(operatorExpr.getExprList(), env));
-            return operatorExpr;
-        } else {
-            return newOpertorExpr.accept(this, env);
-        }
-    }
-
-    @Override
-    public Expression visit(FieldAccessor fa, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newFa = env.findSubstitution(fa, deepCopier);
-        if (newFa == fa) {
-            fa.setExpr(fa.getExpr().accept(this, env));
-            return fa;
-        } else {
-            return newFa.accept(this, env);
-        }
-    }
-
-    @Override
-    public Expression visit(IndexAccessor ia, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newIa = env.findSubstitution(ia, deepCopier);
-        if (newIa == ia) {
-            ia.setExpr(ia.getExpr().accept(this, env));
-            ia.setIndexExpr(ia.getIndexExpr().accept(this, env));
-            return ia;
-        } else {
-            return newIa.accept(this, env);
-        }
-    }
-
-    @Override
-    public Expression visit(IfExpr ifexpr, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newIfExpr = env.findSubstitution(ifexpr, deepCopier);
-        if (newIfExpr == ifexpr) {
-            ifexpr.setCondExpr(ifexpr.getCondExpr().accept(this, env));
-            ifexpr.setThenExpr(ifexpr.getThenExpr().accept(this, env));
-            ifexpr.setElseExpr(ifexpr.getElseExpr().accept(this, env));
-            return ifexpr;
-        } else {
-            return newIfExpr.accept(this, env);
-        }
-    }
-
-    @Override
-    public Expression visit(QuantifiedExpression qe, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newQe = env.findSubstitution(qe, deepCopier);
-        if (newQe == qe) {
-            // Rewrites the quantifier list.
-            for (QuantifiedPair pair : qe.getQuantifiedList()) {
-                pair.setExpr(pair.getExpr().accept(this, env));
-            }
-
-            // Rewrites the condition.
-            for (QuantifiedPair pair : qe.getQuantifiedList()) {
-                // Marks each binding var.
-                env.disableVariable(pair.getVarExpr());
-            }
-            qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, env));
-            for (QuantifiedPair pair : qe.getQuantifiedList()) {
-                // Let each binding var exit its scope.
-                env.enableVariable(pair.getVarExpr());
-            }
-            return qe;
-        } else {
-            return newQe.accept(this, env);
-        }
-    }
-
-    @Override
-    public Expression visit(WhereClause wc, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        wc.setWhereExpr(wc.getWhereExpr().accept(this, env));
-        return null;
-    }
-
-    @Override
-    public Expression visit(OrderbyClause oc, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        oc.setOrderbyList(rewriteExpressionList(oc.getOrderbyList(), env));
-        return null;
-    }
-
-    @Override
-    public Expression visit(LimitClause lc, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        lc.setLimitExpr(lc.getLimitExpr().accept(this, env));
-        if (lc.hasOffset()) {
-            lc.setOffset(lc.getOffset().accept(this, env));
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(UnaryExpr u, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newU = env.findSubstitution(u, deepCopier);
-        if (newU == u) {
-            u.setExpr(u.getExpr().accept(this, env));
-            return u;
-        } else {
-            return newU.accept(this, env);
-        }
-    }
-
-    @Override
-    public Expression visit(CallExpr callExpr, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newCallExpr = env.findSubstitution(callExpr, deepCopier);
-        if (newCallExpr == callExpr) {
-            callExpr.setExprList(rewriteExpressionList(callExpr.getExprList(), env));
-            return callExpr;
-        } else {
-            return newCallExpr.accept(this, env);
-        }
-    }
-
-    /**
-     * Rewrites the expression list.
-     *
-     * @param exprs,
-     *            list of expressions.
-     * @param env,
-     *            ExpressionSubstitutionEnvironment.
-     * @return a list of rewritten expressions.
-     * @throws AsterixException
-     */
-    protected List<Expression> rewriteExpressionList(List<Expression> exprs, ExpressionSubstitutionEnvironment env)
-            throws AsterixException {
-        List<Expression> newExprs = new ArrayList<>();
-        for (Expression expr : exprs) {
-            newExprs.add(env.findSubstitution(expr, deepCopier));
-        }
-        return newExprs;
-    }
-}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
index 43fa4a2..7a26c6b 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
@@ -43,9 +43,6 @@
         // Substitutes group-by key expressions.
         substituteGroupbyKeyExpression();
 
-        // Inlines WITH expressions.
-        inlineWithExpressions();
-
         // Rewrites SQL-92 global aggregations.
         rewriteGlobalAggregations();
 
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index 3f7cb31..1ce5de7 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -107,9 +107,6 @@
         // Substitutes group-by key expressions.
         substituteGroupbyKeyExpression();
 
-        // Inlines WITH expressions.
-        inlineWithExpressions();
-
         // Rewrites SQL-92 global aggregations.
         rewriteGlobalAggregations();
 
@@ -141,6 +138,10 @@
         // Replace global variable access with the dataset function for inlined expressions.
         variableCheckAndRewrite(true);
 
+        // Inlines WITH expressions after variableCheckAndRewrite(...) so that the variable scoping for WITH
+        // expression is correct.
+        inlineWithExpressions();
+
         // Sets the var counter of the query.
         topExpr.setVarCounter(context.getVarCounter());
     }
@@ -170,7 +171,7 @@
             return;
         }
         // Inlines with expressions.
-        InlineWithExpressionVisitor inlineWithExpressionVisitor = new InlineWithExpressionVisitor();
+        InlineWithExpressionVisitor inlineWithExpressionVisitor = new InlineWithExpressionVisitor(context);
         inlineWithExpressionVisitor.visit(topExpr, null);
     }
 
@@ -189,7 +190,7 @@
         }
         // Substitute group-by key expressions that appear in the select clause.
         SubstituteGroupbyExpressionWithVariableVisitor substituteGbyExprVisitor =
-                new SubstituteGroupbyExpressionWithVariableVisitor();
+                new SubstituteGroupbyExpressionWithVariableVisitor(context);
         substituteGbyExprVisitor.visit(topExpr, null);
     }
 
@@ -216,8 +217,8 @@
             return;
         }
         // Inline column aliases.
-        InlineColumnAliasVisitor inlineColumnAliasVisitor = new InlineColumnAliasVisitor();
-        inlineColumnAliasVisitor.visit(topExpr, false);
+        InlineColumnAliasVisitor inlineColumnAliasVisitor = new InlineColumnAliasVisitor(context);
+        inlineColumnAliasVisitor.visit(topExpr, null);
     }
 
     protected void variableCheckAndRewrite(boolean overwrite) throws AsterixException {
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
index ea0aa86..36786cd 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
@@ -18,204 +18,106 @@
  */
 package org.apache.asterix.lang.sqlpp.rewrites.visitor;
 
-import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.Expression.Kind;
+import org.apache.asterix.lang.common.base.ILangExpression;
 import org.apache.asterix.lang.common.base.Literal;
-import org.apache.asterix.lang.common.clause.GroupbyClause;
+import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.clause.LetClause;
-import org.apache.asterix.lang.common.clause.LimitClause;
-import org.apache.asterix.lang.common.clause.OrderbyClause;
-import org.apache.asterix.lang.common.clause.WhereClause;
-import org.apache.asterix.lang.common.expression.CallExpr;
-import org.apache.asterix.lang.common.expression.FieldAccessor;
 import org.apache.asterix.lang.common.expression.FieldBinding;
-import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
-import org.apache.asterix.lang.common.expression.IfExpr;
-import org.apache.asterix.lang.common.expression.IndexAccessor;
-import org.apache.asterix.lang.common.expression.ListConstructor;
 import org.apache.asterix.lang.common.expression.LiteralExpr;
-import org.apache.asterix.lang.common.expression.OperatorExpr;
-import org.apache.asterix.lang.common.expression.QuantifiedExpression;
 import org.apache.asterix.lang.common.expression.RecordConstructor;
-import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
-import org.apache.asterix.lang.common.parser.ScopeChecker;
-import org.apache.asterix.lang.common.rewrites.VariableSubstitutionEnvironment;
-import org.apache.asterix.lang.common.statement.FunctionDecl;
-import org.apache.asterix.lang.common.statement.Query;
-import org.apache.asterix.lang.common.struct.QuantifiedPair;
-import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
-import org.apache.asterix.lang.sqlpp.clause.FromClause;
-import org.apache.asterix.lang.sqlpp.clause.FromTerm;
-import org.apache.asterix.lang.sqlpp.clause.HavingClause;
-import org.apache.asterix.lang.sqlpp.clause.JoinClause;
-import org.apache.asterix.lang.sqlpp.clause.NestClause;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.sqlpp.clause.Projection;
 import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
 import org.apache.asterix.lang.sqlpp.clause.SelectClause;
 import org.apache.asterix.lang.sqlpp.clause.SelectElement;
 import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
-import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
-import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
-import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
-import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
-import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
-import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
-import org.apache.asterix.lang.sqlpp.util.SqlppVariableSubstitutionUtil;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
-import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppQueryExpressionVisitor;
+import org.apache.asterix.lang.sqlpp.visitor.SqlppSubstituteExpressionVisitor;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;
 
-public class InlineColumnAliasVisitor extends AbstractSqlppQueryExpressionVisitor<Void, Boolean> {
+public class InlineColumnAliasVisitor extends AbstractSqlppExpressionScopingVisitor {
 
-    private final ScopeChecker scopeChecker = new ScopeChecker();
-
-    @Override
-    public Void visit(WhereClause whereClause, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        whereClause.getWhereExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
+    public InlineColumnAliasVisitor(LangRewritingContext context) {
+        super(context);
     }
 
     @Override
-    public Void visit(FromClause fromClause, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        for (FromTerm fromTerm : fromClause.getFromTerms()) {
-            fromTerm.accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        return null;
-    }
+    public Expression visit(SelectBlock selectBlock, ILangExpression arg) throws AsterixException {
+        // Gets the map from select clause.
+        Map<Expression, Expression> map = getMap(selectBlock.getSelectClause());
 
-    @Override
-    public Void visit(FromTerm fromTerm, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        fromTerm.getLeftExpression().accept(this, overwriteWithGbyKeyVarRefs);
-        // A from binding variable will override the alias to substitute.
-        scopeChecker.getCurrentScope().removeSymbolExpressionMapping(fromTerm.getLeftVariable());
-        if (fromTerm.hasPositionalVariable()) {
-            scopeChecker.getCurrentScope().removeSymbolExpressionMapping(fromTerm.getPositionalVariable());
-        }
-
-        for (AbstractBinaryCorrelateClause correlate : fromTerm.getCorrelateClauses()) {
-            correlate.accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        return null;
-    }
-
-    @Override
-    public Void visit(JoinClause joinClause, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        joinClause.getRightExpression().accept(this, overwriteWithGbyKeyVarRefs);
-        removeSubsutitions(joinClause);
-        joinClause.getConditionExpression().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
-    }
-
-    @Override
-    public Void visit(NestClause nestClause, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        nestClause.getRightExpression().accept(this, overwriteWithGbyKeyVarRefs);
-        nestClause.getConditionExpression().accept(this, overwriteWithGbyKeyVarRefs);
-        removeSubsutitions(nestClause);
-        return null;
-    }
-
-    @Override
-    public Void visit(UnnestClause unnestClause, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        unnestClause.getRightExpression().accept(this, overwriteWithGbyKeyVarRefs);
-        removeSubsutitions(unnestClause);
-        return null;
-    }
-
-    @Override
-    public Void visit(Projection projection, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        if (projection.star() || projection.getName() == null) {
-            return null;
-        }
-        projection.getExpression().accept(this, overwriteWithGbyKeyVarRefs);
-        VariableExpr columnAlias =
-                new VariableExpr(SqlppVariableUtil.toInternalVariableIdentifier(projection.getName()));
-        VariableSubstitutionEnvironment env = scopeChecker.getCurrentScope().getVarSubstitutionEnvironment();
-        Expression gbyKey = (Expression) SqlppRewriteUtil.deepCopy(env.findSubstitution(columnAlias));
-        if (overwriteWithGbyKeyVarRefs) {
-            if (gbyKey != null) {
-                projection.setExpression(gbyKey);
-            }
-        } else {
-            scopeChecker.getCurrentScope().addSymbolExpressionMappingToScope(columnAlias, projection.getExpression());
-        }
-        return null;
-    }
-
-    @Override
-    public Void visit(SelectBlock selectBlock, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        // Traverses the select block in the order of "select", "group-by",
-        // "group-by" lets and "having".
-        // The first pass over the select clause will not overwrite projection expressions.
-        selectBlock.getSelectClause().accept(this, false);
-
+        // Removes all FROM/LET binding variables
         if (selectBlock.hasFromClause()) {
-            selectBlock.getFromClause().accept(this, overwriteWithGbyKeyVarRefs);
+            map.keySet().removeAll(SqlppVariableUtil.getBindingVariables(selectBlock.getFromClause()));
         }
         if (selectBlock.hasLetClauses()) {
-            for (LetClause letClause : selectBlock.getLetList()) {
-                letClause.accept(this, overwriteWithGbyKeyVarRefs);
-            }
+            map.keySet().removeAll(SqlppVariableUtil.getBindingVariables(selectBlock.getLetList()));
         }
+
+        // Creates a substitution visitor.
+        SqlppSubstituteExpressionVisitor visitor = new SqlppSubstituteExpressionVisitor(context, map);
+
+        // Rewrites GROUP BY/LET/HAVING clauses.
         if (selectBlock.hasGroupbyClause()) {
-            selectBlock.getGroupbyClause().accept(this, overwriteWithGbyKeyVarRefs);
+            selectBlock.getGroupbyClause().accept(visitor, arg);
         }
         if (selectBlock.hasLetClausesAfterGroupby()) {
-            for (LetClause letClauseAfterGby : selectBlock.getLetListAfterGroupby()) {
-                letClauseAfterGby.accept(this, true);
+            for (LetClause letClause : selectBlock.getLetListAfterGroupby()) {
+                letClause.accept(visitor, arg);
             }
         }
         if (selectBlock.hasHavingClause()) {
-            selectBlock.getHavingClause().accept(this, overwriteWithGbyKeyVarRefs);
+            selectBlock.getHavingClause().accept(visitor, arg);
         }
+        SelectExpression selectExpression = (SelectExpression) arg;
 
-        // Visit select clause again to overwrite projection expressions to group-by
-        // key variable references if any group-by key is the original projection
-        // column alias.
-        selectBlock.getSelectClause().accept(this, true);
-        return null;
+        // For SET operation queries, column aliases will not substitute ORDER BY nor LIMIT expressions.
+        if (!selectExpression.getSelectSetOperation().hasRightInputs()) {
+            if (selectExpression.hasOrderby()) {
+                selectExpression.getOrderbyClause().accept(visitor, arg);
+            }
+            if (selectExpression.hasLimit()) {
+                selectExpression.getLimitClause().accept(visitor, arg);
+            }
+        }
+        return super.visit(selectBlock, arg);
     }
 
-    @Override
-    public Void visit(SelectClause selectClause, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
+    private Map<Expression, Expression> getMap(SelectClause selectClause) throws AsterixException {
         if (selectClause.selectElement()) {
-            selectClause.getSelectElement().accept(this, overwriteWithGbyKeyVarRefs);
+            return getMap(selectClause.getSelectElement());
         }
         if (selectClause.selectRegular()) {
-            selectClause.getSelectRegular().accept(this, overwriteWithGbyKeyVarRefs);
+            return getMap(selectClause.getSelectRegular());
         }
         return null;
     }
 
-    @Override
-    public Void visit(SelectElement selectElement, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
+    private Map<Expression, Expression> getMap(SelectElement selectElement) {
         Expression expr = selectElement.getExpression();
-        expr.accept(this, overwriteWithGbyKeyVarRefs);
         if (expr.getKind() == Kind.RECORD_CONSTRUCTOR_EXPRESSION) {
             // Rewrite top-level field names (aliases), in order to be consistent with SelectRegular.
-            mapForRecordConstructor(overwriteWithGbyKeyVarRefs, (RecordConstructor) expr);
+            return mapRecordConstructor((RecordConstructor) expr);
         }
-        return null;
+        return Collections.emptyMap();
     }
 
-    /**
-     * Map aliases for a record constructor in SELECT ELEMENT.
-     *
-     * @param overwriteWithGbyKeyVarRefs,
-     *            whether we rewrite the record constructor with mapped group-by key variables.
-     * @param rc,
-     *            the RecordConstructor expression.
-     * @throws AsterixException
-     */
-    private void mapForRecordConstructor(Boolean overwriteWithGbyKeyVarRefs, RecordConstructor rc)
-            throws AsterixException {
+    private Map<Expression, Expression> getMap(SelectRegular selectRegular) {
+        return mapProjections(selectRegular.getProjections());
+    }
+
+    private Map<Expression, Expression> mapRecordConstructor(RecordConstructor rc) {
+        Map<Expression, Expression> exprMap = new HashMap<>();
         for (FieldBinding binding : rc.getFbList()) {
             Expression leftExpr = binding.getLeftExpr();
             // We only need to deal with the case that the left expression (for a field name) is
@@ -226,263 +128,20 @@
             }
             LiteralExpr literalExpr = (LiteralExpr) leftExpr;
             if (literalExpr.getValue().getLiteralType() == Literal.Type.STRING) {
-                String fieldName = literalExpr.getValue().getStringValue();
-                VariableExpr columnAlias = new VariableExpr(SqlppVariableUtil.toInternalVariableIdentifier(fieldName));
-                VariableSubstitutionEnvironment env = scopeChecker.getCurrentScope().getVarSubstitutionEnvironment();
-                if (overwriteWithGbyKeyVarRefs) {
-                    // Rewrites the field value expression by the mapped grouping key
-                    // (for the column alias) if there exists such a mapping.
-                    Expression gbyKey = (Expression) SqlppRewriteUtil.deepCopy(env.findSubstitution(columnAlias));
-                    if (gbyKey != null) {
-                        binding.setRightExpr(gbyKey);
-                    }
-                } else {
-                    // If this is the first pass, map a field name (i.e., column alias) to the field expression.
-                    scopeChecker.getCurrentScope().addSymbolExpressionMappingToScope(columnAlias,
-                            binding.getRightExpr());
-                }
+                String fieldName = SqlppVariableUtil.toInternalVariableName(literalExpr.getValue().getStringValue());
+                exprMap.put(new VariableExpr(new VarIdentifier(fieldName)), binding.getRightExpr());
             }
         }
+        return exprMap;
     }
 
-    @Override
-    public Void visit(SelectRegular selectRegular, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        for (Projection projection : selectRegular.getProjections()) {
-            projection.accept(this, overwriteWithGbyKeyVarRefs);
+    private Map<Expression, Expression> mapProjections(List<Projection> projections) {
+        Map<Expression, Expression> exprMap = new HashMap<>();
+        for (Projection projection : projections) {
+            exprMap.put(
+                    new VariableExpr(new VarIdentifier(SqlppVariableUtil.toInternalVariableName(projection.getName()))),
+                    projection.getExpression());
         }
-        return null;
-    }
-
-    @Override
-    public Void visit(SelectSetOperation selectSetOperation, Boolean overwriteWithGbyKeyVarRefs)
-            throws AsterixException {
-        selectSetOperation.getLeftInput().accept(this, overwriteWithGbyKeyVarRefs);
-        for (SetOperationRight right : selectSetOperation.getRightInputs()) {
-            right.getSetOperationRightInput().accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        return null;
-    }
-
-    @Override
-    public Void visit(SelectExpression selectExpression, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        scopeChecker.createNewScope();
-
-        // Visits let bindings.
-        if (selectExpression.hasLetClauses()) {
-            for (LetClause lc : selectExpression.getLetList()) {
-                lc.accept(this, overwriteWithGbyKeyVarRefs);
-            }
-        }
-
-        // Visits selectSetOperation
-        SelectSetOperation selectSetOperation = selectExpression.getSelectSetOperation();
-        selectSetOperation.accept(this, overwriteWithGbyKeyVarRefs);
-
-        // If there is a UNION in the selectSetOperation, we cannot overwrite order by or limit.
-        if (!selectSetOperation.hasRightInputs()) {
-            // Visits order by.
-            if (selectExpression.hasOrderby()) {
-                selectExpression.getOrderbyClause().accept(this, overwriteWithGbyKeyVarRefs);
-            }
-            // Visits limit.
-            if (selectExpression.hasLimit()) {
-                selectExpression.getLimitClause().accept(this, overwriteWithGbyKeyVarRefs);
-            }
-        }
-
-        // Exits the scope that were entered within this select expression
-        scopeChecker.removeCurrentScope();
-        return null;
-    }
-
-    @Override
-    public Void visit(LetClause letClause, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        VariableSubstitutionEnvironment env = scopeChecker.getCurrentScope().getVarSubstitutionEnvironment();
-        if (overwriteWithGbyKeyVarRefs) {
-            Expression newBindExpr = (Expression) SqlppVariableSubstitutionUtil
-                    .substituteVariableWithoutContext(letClause.getBindingExpr(), env);
-            letClause.setBindingExpr(newBindExpr);
-        }
-        letClause.getBindingExpr().accept(this, false);
-        // A let binding variable will override the alias to substitute.
-        scopeChecker.getCurrentScope().removeSymbolExpressionMapping(letClause.getVarExpr());
-        return null;
-    }
-
-    @Override
-    public Void visit(OrderbyClause oc, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        VariableSubstitutionEnvironment env = scopeChecker.getCurrentScope().getVarSubstitutionEnvironment();
-        List<Expression> orderExprs = new ArrayList<>();
-        for (Expression orderExpr : oc.getOrderbyList()) {
-            orderExprs.add((Expression) SqlppVariableSubstitutionUtil.substituteVariableWithoutContext(orderExpr, env));
-            orderExpr.accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        oc.setOrderbyList(orderExprs);
-        return null;
-    }
-
-    @Override
-    public Void visit(GroupbyClause gc, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        VariableSubstitutionEnvironment env = scopeChecker.getCurrentScope().getVarSubstitutionEnvironment();
-        Map<VariableExpr, VariableExpr> oldGbyExprsToNewGbyVarMap = new HashMap<>();
-        for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
-            Expression oldGbyExpr = gbyVarExpr.getExpr();
-            Expression newExpr =
-                    (Expression) SqlppVariableSubstitutionUtil.substituteVariableWithoutContext(oldGbyExpr, env);
-            newExpr.accept(this, overwriteWithGbyKeyVarRefs);
-            gbyVarExpr.setExpr(newExpr);
-            if (oldGbyExpr.getKind() == Kind.VARIABLE_EXPRESSION) {
-                VariableExpr oldGbyVarExpr = (VariableExpr) oldGbyExpr;
-                if (env.findSubstitution(oldGbyVarExpr) != null) {
-                    // Re-mapping that needs to be added.
-                    oldGbyExprsToNewGbyVarMap.put(oldGbyVarExpr, gbyVarExpr.getVar());
-                }
-            }
-        }
-        for (Entry<VariableExpr, VariableExpr> entry : oldGbyExprsToNewGbyVarMap.entrySet()) {
-            // The group-by key variable will override the alias to substitute.
-            scopeChecker.getCurrentScope().removeSymbolExpressionMapping(entry.getKey());
-            scopeChecker.getCurrentScope().addSymbolExpressionMappingToScope(entry.getKey(), entry.getValue());
-        }
-        return null;
-    }
-
-    @Override
-    public Void visit(LimitClause limitClause, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        limitClause.getLimitExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
-    }
-
-    @Override
-    public Void visit(HavingClause havingClause, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        VariableSubstitutionEnvironment env = scopeChecker.getCurrentScope().getVarSubstitutionEnvironment();
-        Expression newFilterExpr = (Expression) SqlppVariableSubstitutionUtil
-                .substituteVariableWithoutContext(havingClause.getFilterExpression(), env);
-        newFilterExpr.accept(this, overwriteWithGbyKeyVarRefs);
-        havingClause.setFilterExpression(newFilterExpr);
-        return null;
-    }
-
-    @Override
-    public Void visit(Query q, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        q.getBody().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
-    }
-
-    @Override
-    public Void visit(FunctionDecl fd, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        scopeChecker.createNewScope();
-        fd.getFuncBody().accept(this, overwriteWithGbyKeyVarRefs);
-        scopeChecker.removeCurrentScope();
-        return null;
-    }
-
-    @Override
-    public Void visit(LiteralExpr l, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        return null;
-    }
-
-    @Override
-    public Void visit(ListConstructor lc, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        for (Expression expr : lc.getExprList()) {
-            expr.accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        return null;
-    }
-
-    @Override
-    public Void visit(RecordConstructor rc, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        for (FieldBinding binding : rc.getFbList()) {
-            binding.getLeftExpr().accept(this, false);
-            binding.getRightExpr().accept(this, false);
-        }
-        return null;
-    }
-
-    @Override
-    public Void visit(OperatorExpr operatorExpr, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        for (Expression expr : operatorExpr.getExprList()) {
-            expr.accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        return null;
-    }
-
-    @Override
-    public Void visit(IfExpr ifExpr, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        ifExpr.getCondExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        ifExpr.getThenExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        ifExpr.getElseExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
-    }
-
-    @Override
-    public Void visit(QuantifiedExpression qe, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        for (QuantifiedPair pair : qe.getQuantifiedList()) {
-            pair.getExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        qe.getSatisfiesExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
-    }
-
-    @Override
-    public Void visit(CallExpr callExpr, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        for (Expression expr : callExpr.getExprList()) {
-            expr.accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        return null;
-    }
-
-    @Override
-    public Void visit(VariableExpr varExpr, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        return null;
-    }
-
-    @Override
-    public Void visit(UnaryExpr u, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        u.getExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
-    }
-
-    @Override
-    public Void visit(FieldAccessor fa, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        fa.getExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
-    }
-
-    @Override
-    public Void visit(IndexAccessor ia, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        ia.getExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        Expression indexExpr = ia.getExpr();
-        if (indexExpr != null) {
-            indexExpr.accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        return null;
-    }
-
-    @Override
-    public Void visit(IndependentSubquery independentSubquery, Boolean overwriteWithGbyKeyVarRefs)
-            throws AsterixException {
-        independentSubquery.getExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
-    }
-
-    @Override
-    public Void visit(CaseExpression caseExpression, Boolean overwriteWithGbyKeyVarRefs) throws AsterixException {
-        caseExpression.getConditionExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        for (Expression expr : caseExpression.getWhenExprs()) {
-            expr.accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        for (Expression expr : caseExpression.getThenExprs()) {
-            expr.accept(this, overwriteWithGbyKeyVarRefs);
-        }
-        caseExpression.getElseExpr().accept(this, overwriteWithGbyKeyVarRefs);
-        return null;
-    }
-
-    private void removeSubsutitions(AbstractBinaryCorrelateClause unnestClause) {
-        scopeChecker.getCurrentScope().removeSymbolExpressionMapping(unnestClause.getRightVariable());
-        if (unnestClause.hasPositionalVariable()) {
-            scopeChecker.getCurrentScope().removeSymbolExpressionMapping(unnestClause.getPositionalVariable());
-        }
+        return exprMap;
     }
 }
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineWithExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineWithExpressionVisitor.java
index a01c09f..7a4f0fe 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineWithExpressionVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineWithExpressionVisitor.java
@@ -18,6 +18,8 @@
  */
 package org.apache.asterix.lang.sqlpp.rewrites.visitor;
 
+import static org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil.substituteExpression;
+
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -27,37 +29,45 @@
 import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.base.ILangExpression;
 import org.apache.asterix.lang.common.clause.LetClause;
-import org.apache.asterix.lang.common.expression.VariableExpr;
-import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
-import org.apache.asterix.lang.sqlpp.util.SqlppVariableSubstitutionUtil;
-import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
+import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;
 
-public class InlineWithExpressionVisitor extends AbstractSqlppSimpleExpressionVisitor {
+public class InlineWithExpressionVisitor extends AbstractSqlppExpressionScopingVisitor {
+
+    public InlineWithExpressionVisitor(LangRewritingContext context) {
+        super(context);
+    }
 
     @Override
     public Expression visit(SelectExpression selectExpression, ILangExpression arg) throws AsterixException {
         if (selectExpression.hasLetClauses()) {
             // Inlines the leading WITH list.
-            Map<VariableExpr, Expression> varExprMap = new HashMap<>();
+            Map<Expression, Expression> varExprMap = new HashMap<>();
             List<LetClause> withs = selectExpression.getLetList();
             Iterator<LetClause> with = withs.iterator();
             while (with.hasNext()) {
                 LetClause letClause = with.next();
                 // Replaces the let binding Expr.
                 Expression expr = letClause.getBindingExpr();
-                letClause.setBindingExpr(
-                        (Expression) SqlppVariableSubstitutionUtil.substituteVariableWithoutContext(expr, varExprMap));
+                Expression newBindingExpr = SqlppRewriteUtil.substituteExpression(expr, varExprMap, context);
+                letClause.setBindingExpr(newBindingExpr);
+
+                // Performs the rewriting recursively in the newBindingExpr itself.
+                super.visit(newBindingExpr, arg);
+
+                // Removes the WITH entry and adds variable-expr mapping into the varExprMap.
                 with.remove();
                 Expression bindingExpr = letClause.getBindingExpr();
                 // Wraps the binding expression with IndependentSubquery, so that free identifier references
                 // in the binding expression will not be resolved use outer-scope variables.
-                varExprMap.put(letClause.getVarExpr(), new IndependentSubquery(bindingExpr));
+                varExprMap.put(letClause.getVarExpr(), bindingExpr);
             }
 
             // Inlines WITH expressions into the select expression.
-            SelectExpression newSelectExpression = (SelectExpression) SqlppVariableSubstitutionUtil
-                    .substituteVariableWithoutContext(selectExpression, varExprMap);
+            SelectExpression newSelectExpression = (SelectExpression) substituteExpression(selectExpression,
+                    varExprMap, context);
 
             // Continues to visit the rewritten select expression.
             return super.visit(newSelectExpression, arg);
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGlobalAggregationSugarVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGlobalAggregationSugarVisitor.java
index 98d18c2..6308d7f 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGlobalAggregationSugarVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGlobalAggregationSugarVisitor.java
@@ -19,6 +19,7 @@
 package org.apache.asterix.lang.sqlpp.rewrites.visitor;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 import org.apache.asterix.common.exceptions.AsterixException;
@@ -27,7 +28,6 @@
 import org.apache.asterix.lang.common.clause.GroupbyClause;
 import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
 import org.apache.asterix.lang.common.expression.LiteralExpr;
-import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.literal.IntegerLiteral;
 import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
 import org.apache.asterix.lang.sqlpp.clause.SelectClause;
@@ -51,9 +51,8 @@
                 List<GbyVariableExpressionPair> gbyPairList = new ArrayList<>();
                 gbyPairList.add(new GbyVariableExpressionPair(null, new LiteralExpr(new IntegerLiteral(1))));
                 List<GbyVariableExpressionPair> decorPairList = new ArrayList<>();
-                List<VariableExpr> withVarList = new ArrayList<>();
-                GroupbyClause gbyClause = new GroupbyClause(gbyPairList, decorPairList, withVarList, null, null, false,
-                        true);
+                GroupbyClause gbyClause = new GroupbyClause(gbyPairList, decorPairList, new HashMap<>(), null, null,
+                        false, true);
                 selectBlock.setGroupbyClause(gbyClause);
             }
         }
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupBySugarVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupBySugarVisitor.java
index 47aa02b..996a2ec 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupBySugarVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupBySugarVisitor.java
@@ -22,7 +22,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -30,7 +29,6 @@
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.base.ILangExpression;
 import org.apache.asterix.lang.common.expression.CallExpr;
 import org.apache.asterix.lang.common.expression.FieldAccessor;
@@ -46,7 +44,6 @@
 import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
 import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
-import org.apache.asterix.lang.sqlpp.util.SqlppVariableSubstitutionUtil;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
 import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;
 
@@ -83,24 +80,20 @@
 public class SqlppGroupBySugarVisitor extends AbstractSqlppExpressionScopingVisitor {
 
     private final Expression groupVar;
-    private final Collection<VariableExpr> targetVars;
-    private final Collection<VariableExpr> allVisableVars;
+    private final Collection<VariableExpr> fieldVars;
 
     public SqlppGroupBySugarVisitor(LangRewritingContext context, Expression groupVar,
-            Collection<VariableExpr> targetVars, Collection<VariableExpr> allVisableVars) {
+            Collection<VariableExpr> fieldVars) {
         super(context);
         this.groupVar = groupVar;
-        this.targetVars = targetVars;
-        this.allVisableVars = allVisableVars;
-        allVisableVars.remove(groupVar);
+        this.fieldVars = fieldVars;
     }
 
     @Override
     public Expression visit(CallExpr callExpr, ILangExpression arg) throws AsterixException {
         List<Expression> newExprList = new ArrayList<>();
         FunctionSignature signature = callExpr.getFunctionSignature();
-        boolean aggregate = FunctionMapUtil.isSql92AggregateFunction(signature)
-                || FunctionMapUtil.isCoreAggregateFunction(signature);
+        boolean aggregate = FunctionMapUtil.isSql92AggregateFunction(signature);
         boolean rewritten = false;
         for (Expression expr : callExpr.getExprList()) {
             Expression newExpr = aggregate ? wrapAggregationArgument(expr) : expr;
@@ -118,54 +111,32 @@
 
     private Expression wrapAggregationArgument(Expression argExpr) throws AsterixException {
         Expression expr = argExpr;
-        if (expr.getKind() == Kind.SELECT_EXPRESSION) {
-            return expr;
-        }
-        Set<VariableExpr> definedVars = scopeChecker.getCurrentScope().getLiveVariables();
-        allVisableVars.addAll(definedVars);
         Set<VariableExpr> freeVars = SqlppRewriteUtil.getFreeVariable(expr);
 
-        // Whether we need to resolve undefined variables.
-        boolean needResolve = !allVisableVars.containsAll(freeVars);
-
-        Set<VariableExpr> vars = new HashSet<>(targetVars);
-        vars.removeAll(definedVars); // Exclude re-defined local variables.
-        if (!needResolve && !vars.containsAll(freeVars)) {
-            return expr;
-        }
-
-        VariableExpr var = new VariableExpr(context.newVariable());
-        FromTerm fromTerm = new FromTerm(groupVar, var, null, null);
+        VariableExpr fromBindingVar = new VariableExpr(context.newVariable());
+        FromTerm fromTerm = new FromTerm(groupVar, fromBindingVar, null, null);
         FromClause fromClause = new FromClause(Collections.singletonList(fromTerm));
 
+        // Maps field variable expressions to field accesses.
+        Map<Expression, Expression> varExprMap = new HashMap<>();
+        for (VariableExpr usedVar : freeVars) {
+            // Reference to a field in the group variable.
+            if (fieldVars.contains(usedVar)) {
+                // Rewrites to a reference to a field in the group variable.
+                varExprMap.put(usedVar,
+                                new FieldAccessor(fromBindingVar, SqlppVariableUtil.toUserDefinedVariableName(usedVar
+                                        .getVar())));
+            }
+        }
+
         // Select clause.
-        SelectElement selectElement = new SelectElement(expr);
+        SelectElement selectElement = new SelectElement(
+                SqlppRewriteUtil.substituteExpression(expr, varExprMap, context));
         SelectClause selectClause = new SelectClause(selectElement, null, false);
 
         // Construct the select expression.
         SelectBlock selectBlock = new SelectBlock(selectClause, fromClause, null, null, null, null, null);
         SelectSetOperation selectSetOperation = new SelectSetOperation(new SetOperationInput(selectBlock, null), null);
-        SelectExpression selectExpression = new SelectExpression(null, selectSetOperation, null, null, true);
-
-        // replace variable expressions with field access
-        Map<VariableExpr, Expression> varExprMap = new HashMap<>();
-        for (VariableExpr usedVar : freeVars) {
-            if (allVisableVars.contains(usedVar)) {
-                // Reference to a defined variable.
-                if (vars.contains(usedVar)) {
-                    // Reference to a variable defined before the group-by,
-                    // i.e., not a variable defined by a LET after the group-by.
-                    varExprMap.put(usedVar,
-                            new FieldAccessor(var, SqlppVariableUtil.toUserDefinedVariableName(usedVar.getVar())));
-                }
-            } else {
-                // Reference to an undefined variable.
-                varExprMap.put(usedVar,
-                        this.wrapWithResolveFunction(usedVar, new HashSet<>(Collections.singleton(var))));
-            }
-        }
-        selectElement.setExpression(
-                (Expression) SqlppVariableSubstitutionUtil.substituteVariableWithoutContext(expr, varExprMap));
-        return selectExpression;
+        return new SelectExpression(null, selectSetOperation, null, null, true);
     }
 }
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
index 6575752..0170709 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
@@ -19,9 +19,11 @@
 package org.apache.asterix.lang.sqlpp.rewrites.visitor;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.asterix.common.exceptions.AsterixException;
@@ -29,13 +31,17 @@
 import org.apache.asterix.lang.common.base.ILangExpression;
 import org.apache.asterix.lang.common.clause.GroupbyClause;
 import org.apache.asterix.lang.common.clause.LetClause;
-import org.apache.asterix.lang.common.context.Scope;
+import org.apache.asterix.lang.common.clause.LimitClause;
+import org.apache.asterix.lang.common.clause.OrderbyClause;
 import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.asterix.lang.sqlpp.clause.FromClause;
+import org.apache.asterix.lang.sqlpp.clause.HavingClause;
 import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
+import org.apache.asterix.lang.sqlpp.clause.SelectClause;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
@@ -88,8 +94,9 @@
     public Expression visit(SelectBlock selectBlock, ILangExpression arg) throws AsterixException {
         // Traverses the select block in the order of "from", "let"s, "where",
         // "group by", "let"s, "having" and "select".
+        FromClause fromClause = selectBlock.getFromClause();
         if (selectBlock.hasFromClause()) {
-            selectBlock.getFromClause().accept(this, arg);
+            fromClause.accept(this, arg);
         }
         if (selectBlock.hasLetClauses()) {
             List<LetClause> letList = selectBlock.getLetList();
@@ -101,48 +108,110 @@
             selectBlock.getWhereClause().accept(this, arg);
         }
         if (selectBlock.hasGroupbyClause()) {
-            selectBlock.getGroupbyClause().accept(this, arg);
-            Set<VariableExpr> withVarSet = new HashSet<>(selectBlock.getGroupbyClause().getWithVarList());
-            withVarSet.remove(selectBlock.getGroupbyClause().getGroupVar());
+            GroupbyClause groupbyClause = selectBlock.getGroupbyClause();
+            groupbyClause.accept(this, fromClause);
+            Collection<VariableExpr> visibleVarsInCurrentScope = SqlppVariableUtil.getBindingVariables(groupbyClause);
 
-            Set<VariableExpr> allVisableVars = SqlppVariableUtil
-                    .getLiveVariables(scopeChecker.getCurrentScope());
+            VariableExpr groupVar = groupbyClause.getGroupVar();
+            Set<VariableExpr> groupFieldVars = getGroupFieldVariables(groupbyClause);
+
+            Collection<VariableExpr> freeVariablesInGbyLets = new HashSet<>();
             if (selectBlock.hasLetClausesAfterGroupby()) {
                 List<LetClause> letListAfterGby = selectBlock.getLetListAfterGroupby();
                 for (LetClause letClauseAfterGby : letListAfterGby) {
                     letClauseAfterGby.accept(this, arg);
                     // Rewrites each let clause after the group-by.
-                    SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
-                            withVarSet, allVisableVars, letClauseAfterGby, context);
-                    // Adds let vars to all visiable vars.
-                    allVisableVars.add(letClauseAfterGby.getVarExpr());
+                    SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, letClauseAfterGby,
+                            context);
+                    Collection<VariableExpr> freeVariablesInLet = SqlppVariableUtil.getFreeVariables(letClauseAfterGby
+                            .getBindingExpr());
+                    freeVariablesInLet.removeAll(visibleVarsInCurrentScope);
+                    freeVariablesInGbyLets.addAll(freeVariablesInLet);
+                    visibleVarsInCurrentScope.add(letClauseAfterGby.getVarExpr());
                 }
             }
 
+            Collection<VariableExpr> freeVariables = new HashSet<>();
             if (selectBlock.hasHavingClause()) {
-                selectBlock.getHavingClause().accept(this, arg);
                 // Rewrites the having clause.
-                SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
-                        withVarSet, allVisableVars, selectBlock.getHavingClause(), context);
+                HavingClause havingClause = selectBlock.getHavingClause();
+                havingClause.accept(this, arg);
+                SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, havingClause, context);
+                freeVariables.addAll(SqlppVariableUtil.getFreeVariables(havingClause));
             }
 
             SelectExpression parentSelectExpression = (SelectExpression) arg;
-            if (parentSelectExpression.hasOrderby()) {
-                // Rewrites the order-by clause.
-                SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
-                        withVarSet, allVisableVars, parentSelectExpression.getOrderbyClause(), context);
-            }
-            if (parentSelectExpression.hasLimit()) {
-                // Rewrites the limit clause.
-                SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
-                        withVarSet, allVisableVars, parentSelectExpression.getLimitClause(), context);
+            // We cannot rewrite ORDER BY and LIMIT if it's a SET operation query.
+            if (!parentSelectExpression.getSelectSetOperation().hasRightInputs()) {
+                if (parentSelectExpression.hasOrderby()) {
+                    // Rewrites the ORDER BY clause.
+                    OrderbyClause orderbyClause = parentSelectExpression.getOrderbyClause();
+                    orderbyClause.accept(this, arg);
+                    SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, orderbyClause,
+                            context);
+                    freeVariables.addAll(SqlppVariableUtil.getFreeVariables(orderbyClause));
+                }
+                if (parentSelectExpression.hasLimit()) {
+                    // Rewrites the LIMIT clause.
+                    LimitClause limitClause = parentSelectExpression.getLimitClause();
+                    limitClause.accept(this, arg);
+                    SqlppRewriteUtil
+                            .rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, limitClause, context);
+                    freeVariables.addAll(SqlppVariableUtil.getFreeVariables(limitClause));
+                }
             }
 
             // Visits the select clause.
-            selectBlock.getSelectClause().accept(this, arg);
+            SelectClause selectClause = selectBlock.getSelectClause();
+            selectClause.accept(this, arg);
             // Rewrites the select clause.
-            SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
-                    withVarSet, allVisableVars, selectBlock.getSelectClause(), context);
+            SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, selectClause, context);
+            freeVariables.addAll(SqlppVariableUtil.getFreeVariables(selectClause));
+            freeVariables.removeAll(visibleVarsInCurrentScope);
+
+            // Gets the final free variables.
+            freeVariables.addAll(freeVariablesInGbyLets);
+
+            // Gets outer scope variables.
+            Collection<VariableExpr> decorVars = SqlppVariableUtil.getLiveVariables(
+                    scopeChecker.getCurrentScope(), true);
+            decorVars.removeAll(visibleVarsInCurrentScope);
+
+            // Need path resolution or not?
+            boolean needResolution = !decorVars.containsAll(freeVariables);
+            // If path resolution is needed, we need to include all outer scope variables in the decoration list.
+            // Otherwise, we only need to retain used free variables.
+            if (needResolution) {
+                // Tracks used variables, including WITH variables.
+                decorVars.retainAll(freeVariables);
+                // Adds all non-WITH outer scope variables, for path resolution.
+                Collection<VariableExpr> visibleOuterScopeNonWithVars = SqlppVariableUtil.getLiveVariables(
+                        scopeChecker.getCurrentScope(), false);
+                visibleOuterScopeNonWithVars.removeAll(visibleVarsInCurrentScope);
+                decorVars.addAll(visibleOuterScopeNonWithVars);
+            } else {
+                // Only retains used free variables.
+                decorVars.retainAll(freeVariables);
+            }
+            if (!decorVars.isEmpty()) {
+                // Adds used WITH variables.
+                Collection<VariableExpr> visibleOuterScopeNonWithVars = SqlppVariableUtil.getLiveVariables(
+                        scopeChecker.getCurrentScope(), false);
+                visibleOuterScopeNonWithVars.retainAll(freeVariables);
+                decorVars.addAll(visibleOuterScopeNonWithVars);
+
+                // Adds necessary decoration variables for the GROUP BY.
+                // NOTE: we need to include WITH binding variables so as they can be evaluated before
+                // the GROUP BY instead of being inlined as part of nested pipepline. The current optimzier
+                // is not able to optimize the latter case. The following query is such an example:
+                // asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11
+                List<GbyVariableExpressionPair> decorList = new ArrayList<>();
+                for (VariableExpr var : decorVars) {
+                    decorList.add(new GbyVariableExpressionPair((VariableExpr) SqlppRewriteUtil.deepCopy(var),
+                            (Expression) SqlppRewriteUtil.deepCopy(var)));
+                }
+                groupbyClause.getDecorPairList().addAll(decorList);
+            }
         } else {
             selectBlock.getSelectClause().accept(this, arg);
         }
@@ -151,43 +220,35 @@
 
     @Override
     public Expression visit(GroupbyClause gc, ILangExpression arg) throws AsterixException {
-        Scope newScope = scopeChecker.extendCurrentScopeNoPush(true);
-        // Puts all group-by variables into the symbol set of the new scope.
-        for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
-            gbyVarExpr.setExpr(gbyVarExpr.getExpr().accept(this, arg));
-            VariableExpr gbyVar = gbyVarExpr.getVar();
-            if (gbyVar != null) {
-                newScope.addNewVarSymbolToScope(gbyVarExpr.getVar().getVar());
-            }
-        }
-        // Puts all live variables into withVarList.
-        List<VariableExpr> withVarList = new ArrayList<>();
-        Iterator<Identifier> varIterator = scopeChecker.getCurrentScope().liveSymbols();
-        while (varIterator.hasNext()) {
-            Identifier ident = varIterator.next();
+        // Puts all FROM binding variables into withVarList.
+        FromClause fromClause = (FromClause) arg;
+        Collection<VariableExpr> fromBindingVars =
+                fromClause == null ? new ArrayList<>() : SqlppVariableUtil.getBindingVariables(fromClause);
+        Map<Expression, VariableExpr> withVarMap = new HashMap<>();
+        for (VariableExpr fromBindingVar : fromBindingVars) {
             VariableExpr varExpr = new VariableExpr();
-            if (ident instanceof VarIdentifier) {
-                varExpr.setIsNewVar(false);
-                varExpr.setVar((VarIdentifier) ident);
-                withVarList.add(varExpr);
-                newScope.addNewVarSymbolToScope((VarIdentifier) ident);
-            }
+            varExpr.setIsNewVar(false);
+            varExpr.setVar(fromBindingVar.getVar());
+            VariableExpr newVarExpr = (VariableExpr) SqlppRewriteUtil.deepCopy(varExpr);
+            withVarMap.put(varExpr, newVarExpr);
         }
-
         // Sets the field list for the group variable.
         List<Pair<Expression, Identifier>> groupFieldList = new ArrayList<>();
         if (!gc.hasGroupFieldList()) {
-            for (VariableExpr varExpr : withVarList) {
+            for (VariableExpr varExpr : fromBindingVars) {
                 Pair<Expression, Identifier> varIdPair = new Pair<>(new VariableExpr(varExpr.getVar()),
                         SqlppVariableUtil.toUserDefinedVariableName(varExpr.getVar()));
                 groupFieldList.add(varIdPair);
             }
             gc.setGroupFieldList(groupFieldList);
         } else {
-            // Check the scopes of group field variables.
             for (Pair<Expression, Identifier> groupField : gc.getGroupFieldList()) {
-                Expression newVar = groupField.first.accept(this, arg);
-                groupFieldList.add(new Pair<>(newVar, groupField.second));
+                Expression newFieldExpr = groupField.first.accept(this, arg);
+                groupFieldList.add(new Pair<>(newFieldExpr, groupField.second));
+                // Adds a field binding variable into withVarList.
+                VariableExpr bindingVar = new VariableExpr(
+                        new VarIdentifier(SqlppVariableUtil.toInternalVariableName(groupField.second.getValue())));
+                withVarMap.put(newFieldExpr, bindingVar);
             }
         }
         gc.setGroupFieldList(groupFieldList);
@@ -197,15 +258,25 @@
             VariableExpr groupVar = new VariableExpr(context.newVariable());
             gc.setGroupVar(groupVar);
         }
-        newScope.addNewVarSymbolToScope(gc.getGroupVar().getVar());
 
         // Adds the group variable into the "with" (i.e., re-binding) variable list.
         VariableExpr gbyVarRef = new VariableExpr(gc.getGroupVar().getVar());
         gbyVarRef.setIsNewVar(false);
-        withVarList.add(gbyVarRef);
-        gc.setWithVarList(withVarList);
+        withVarMap.put(gbyVarRef, (VariableExpr) SqlppRewriteUtil.deepCopy(gbyVarRef));
+        gc.setWithVarMap(withVarMap);
 
-        scopeChecker.replaceCurrentScope(newScope);
-        return null;
+        // Call super.visit(...) to scope variables.
+        return super.visit(gc, arg);
+    }
+
+    private Set<VariableExpr> getGroupFieldVariables(GroupbyClause groupbyClause) {
+        Set<VariableExpr> fieldVars = new HashSet<>();
+        if (groupbyClause.hasGroupFieldList()) {
+            for (Pair<Expression, Identifier> groupField : groupbyClause.getGroupFieldList()) {
+                fieldVars.add(new VariableExpr(new VarIdentifier(SqlppVariableUtil
+                        .toInternalVariableName(groupField.second.getValue()))));
+            }
+        }
+        return fieldVars;
     }
 }
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
index d2730ff..c765726 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
@@ -26,7 +26,6 @@
 import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.base.IRewriterFactory;
 import org.apache.asterix.lang.common.clause.LetClause;
-import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.visitor.AbstractInlineUdfsVisitor;
@@ -47,7 +46,7 @@
 import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
-import org.apache.asterix.lang.sqlpp.util.SqlppVariableSubstitutionUtil;
+import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
 import org.apache.asterix.lang.sqlpp.visitor.SqlppCloneAndSubstituteVariablesVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
 import org.apache.asterix.metadata.declared.AqlMetadataProvider;
@@ -75,8 +74,8 @@
     @Override
     protected Expression generateQueryExpression(List<LetClause> letClauses, Expression returnExpr)
             throws AsterixException {
-        Map<VariableExpr, Expression> varExprMap = extractLetBindingVariableExpressionMappings(letClauses);
-        return (Expression) SqlppVariableSubstitutionUtil.substituteVariableWithoutContext(returnExpr, varExprMap);
+        Map<Expression, Expression> varExprMap = extractLetBindingVariableExpressionMappings(letClauses);
+        return (Expression) SqlppRewriteUtil.substituteExpression(returnExpr, varExprMap, context);
     }
 
     @Override
@@ -249,13 +248,13 @@
         return inlined || result.first;
     }
 
-    private Map<VariableExpr, Expression> extractLetBindingVariableExpressionMappings(List<LetClause> letClauses)
+    private Map<Expression, Expression> extractLetBindingVariableExpressionMappings(List<LetClause> letClauses)
             throws AsterixException {
-        Map<VariableExpr, Expression> varExprMap = new HashMap<>();
+        Map<Expression, Expression> varExprMap = new HashMap<>();
         for (LetClause lc : letClauses) {
             // inline let variables one by one iteratively.
-            lc.setBindingExpr((Expression) SqlppVariableSubstitutionUtil
-                    .substituteVariableWithoutContext(lc.getBindingExpr(), varExprMap));
+            lc.setBindingExpr((Expression) SqlppRewriteUtil.substituteExpression(lc.getBindingExpr(),
+                    varExprMap, context));
             varExprMap.put(lc.getVarExpr(), lc.getBindingExpr());
         }
         return varExprMap;
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SubstituteGroupbyExpressionWithVariableVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SubstituteGroupbyExpressionWithVariableVisitor.java
index c5cd60e..eb2f463 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SubstituteGroupbyExpressionWithVariableVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SubstituteGroupbyExpressionWithVariableVisitor.java
@@ -25,21 +25,25 @@
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.base.Expression.Kind;
+import org.apache.asterix.lang.common.clause.LetClause;
 import org.apache.asterix.lang.common.expression.CallExpr;
 import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
-import org.apache.asterix.lang.common.rewrites.ExpressionSubstitutionEnvironment;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
-import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
-import org.apache.asterix.lang.sqlpp.visitor.SqlppSubstituteExpressionsVisitor;
-import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
+import org.apache.asterix.lang.sqlpp.visitor.SqlppSubstituteExpressionVisitor;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;
 
 // Replaces expressions that appear in having/select/order-by/limit clause and are identical to some
 // group by key expression with the group by key expression.
-public class SubstituteGroupbyExpressionWithVariableVisitor extends AbstractSqlppSimpleExpressionVisitor {
+public class SubstituteGroupbyExpressionWithVariableVisitor extends AbstractSqlppExpressionScopingVisitor {
+
+    public SubstituteGroupbyExpressionWithVariableVisitor(LangRewritingContext context) {
+        super(context);
+    }
 
     @Override
     public Expression visit(SelectBlock selectBlock, ILangExpression arg) throws AsterixException {
@@ -53,21 +57,28 @@
             }
 
             // Creates a substitution visitor.
-            ExpressionSubstitutionEnvironment env =
-                    new ExpressionSubstitutionEnvironment(map, SqlppVariableUtil::getFreeVariables);
-            SubstituteGroupbyExpressionVisitor visitor = new SubstituteGroupbyExpressionVisitor();
+            SubstituteGroupbyExpressionVisitor visitor = new SubstituteGroupbyExpressionVisitor(context, map);
 
-            // Rewrites having/select/order-by/limit clauses.
+            // Rewrites LET/HAVING/SELECT clauses.
+            if(selectBlock.hasLetClausesAfterGroupby()){
+                for(LetClause letClause : selectBlock.getLetListAfterGroupby()){
+                    letClause.accept(this, arg);
+                }
+            }
             if (selectBlock.hasHavingClause()) {
-                selectBlock.getHavingClause().accept(visitor, env);
+                selectBlock.getHavingClause().accept(visitor, arg);
             }
-            selectBlock.getSelectClause().accept(visitor, env);
+            selectBlock.getSelectClause().accept(visitor, arg);
             SelectExpression selectExpression = (SelectExpression) arg;
-            if (selectExpression.hasOrderby()) {
-                selectExpression.getOrderbyClause().accept(visitor, env);
-            }
-            if (selectExpression.hasLimit()) {
-                selectExpression.getLimitClause().accept(visitor, env);
+
+            // For SET operation queries, the GROUP BY key variables will not substitute ORDER BY nor LIMIT expressions.
+            if (!selectExpression.getSelectSetOperation().hasRightInputs()) {
+                if (selectExpression.hasOrderby()) {
+                    selectExpression.getOrderbyClause().accept(visitor, arg);
+                }
+                if (selectExpression.hasLimit()) {
+                    selectExpression.getLimitClause().accept(visitor, arg);
+                }
             }
         }
         return super.visit(selectBlock, arg);
@@ -75,15 +86,19 @@
 
 }
 
-class SubstituteGroupbyExpressionVisitor extends SqlppSubstituteExpressionsVisitor {
+class SubstituteGroupbyExpressionVisitor extends SqlppSubstituteExpressionVisitor {
+
+    public SubstituteGroupbyExpressionVisitor(LangRewritingContext context, Map<Expression, Expression> exprMap) {
+        super(context, exprMap);
+    }
 
     @Override
-    public Expression visit(CallExpr callExpr, ExpressionSubstitutionEnvironment env) throws AsterixException {
+    public Expression visit(CallExpr callExpr, ILangExpression arg) throws AsterixException {
         FunctionSignature signature = callExpr.getFunctionSignature();
         if (FunctionMapUtil.isSql92AggregateFunction(signature)) {
             return callExpr;
         } else {
-            return super.visit(callExpr, env);
+            return super.visit(callExpr, arg);
         }
     }
 }
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
index 79c99b8..9769d4f 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
@@ -26,8 +26,8 @@
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.base.Expression.Kind;
 import org.apache.asterix.lang.common.expression.CallExpr;
 import org.apache.asterix.lang.common.expression.FieldAccessor;
 import org.apache.asterix.lang.common.expression.LiteralExpr;
@@ -102,7 +102,12 @@
         if (!rewriteNeeded(varExpr)) {
             return varExpr;
         }
-        Set<VariableExpr> liveVars = SqlppVariableUtil.getLiveVariables(scopeChecker.getCurrentScope());
+        // Note: WITH variables are not used for path resolution. The reason is that
+        // the accurate typing for ordered list with an UNION item type is not implemented.
+        // We currently type it as [ANY]. If we include WITH variables for path resolution,
+        // it will lead to ambiguities and the plan is going to be very complex.  An example query is:
+        // asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/subquery/exists
+        Set<VariableExpr> liveVars = SqlppVariableUtil.getLiveVariables(scopeChecker.getCurrentScope(), false);
         boolean resolveAsDataset = resolveDatasetFirst(arg) && datasetExists(dataverseName, datasetName);
         if (resolveAsDataset) {
             return wrapWithDatasetFunction(dataverseName, datasetName);
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
index 9bc1813..519963a 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
@@ -20,6 +20,7 @@
 
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.asterix.common.exceptions.AsterixException;
@@ -27,10 +28,12 @@
 import org.apache.asterix.lang.common.base.ILangExpression;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.statement.Query;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupBySugarVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.CheckSubqueryVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.DeepCopyVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.FreeVariableVisitor;
+import org.apache.asterix.lang.sqlpp.visitor.SqlppSubstituteExpressionVisitor;
 
 public class SqlppRewriteUtil {
 
@@ -39,10 +42,9 @@
 
     // Applying sugar rewriting for group-by.
     public static Expression rewriteExpressionUsingGroupVariable(VariableExpr groupVar,
-            Collection<VariableExpr> targetVarList, Collection<VariableExpr> allVisableVars, ILangExpression expr,
+            Collection<VariableExpr> fieldVars, ILangExpression expr,
             LangRewritingContext context) throws AsterixException {
-        SqlppGroupBySugarVisitor visitor =
-                new SqlppGroupBySugarVisitor(context, groupVar, targetVarList, allVisableVars);
+        SqlppGroupBySugarVisitor visitor = new SqlppGroupBySugarVisitor(context, groupVar, fieldVars);
         return expr.accept(visitor, null);
     }
 
@@ -70,4 +72,31 @@
         return expr.accept(visitor, null);
     }
 
+    /**
+     * Substitutes expression with replacement expressions according to the exprMap.
+     *
+     * @param expression
+     *            ,
+     *            an input expression.
+     * @param exprMap
+     *            a map that maps expressions to their corresponding replacement expressions.
+     * @return an expression, where sub-expressions of the input expression (including the input expression itself)
+     *         are replaced with deep copies with their mapped replacements in the exprMap if there exists such a
+     *         replacement expression.
+     * @throws AsterixException
+     */
+    public static Expression substituteExpression(Expression expression, Map<Expression, Expression> exprMap,
+            LangRewritingContext context) throws AsterixException {
+        if (exprMap.isEmpty()) {
+            return expression;
+        }
+        // Creates a wrapper query for the expression so that if the expression itself
+        // is the key, it can also be replaced.
+        Query wrapper = new Query(false);
+        wrapper.setBody(expression);
+        // Creates a substitution visitor.
+        SqlppSubstituteExpressionVisitor visitor = new SqlppSubstituteExpressionVisitor(context, exprMap);
+        wrapper.accept(visitor, wrapper);
+        return wrapper.getBody();
+    }
 }
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableSubstitutionUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableSubstitutionUtil.java
deleted file mode 100644
index 322b5b6..0000000
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableSubstitutionUtil.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.asterix.lang.sqlpp.util;
-
-import java.util.Map;
-
-import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.ILangExpression;
-import org.apache.asterix.lang.common.expression.VariableExpr;
-import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
-import org.apache.asterix.lang.common.rewrites.VariableSubstitutionEnvironment;
-import org.apache.asterix.lang.sqlpp.visitor.SqlppCloneAndSubstituteVariablesVisitor;
-import org.apache.asterix.lang.sqlpp.visitor.SqlppSubstituteVariablesVisitor;
-
-public class SqlppVariableSubstitutionUtil {
-
-    /**
-     * Substitute variables with corresponding expressions according to the varExprMap.
-     * The substitution should be done BEFORE unique ids are assigned to variables.
-     * In other words, when we call this method, ids of all variables are zero.
-     *
-     * @param expression,
-     *            the expression for substituting variables.
-     * @param varExprMap
-     *            a map that maps variables to their corresponding expressions.
-     * @return a new expression in which variables are substituted.
-     * @throws AsterixException
-     */
-    public static ILangExpression substituteVariableWithoutContext(ILangExpression expression,
-            Map<VariableExpr, Expression> varExprMap) throws AsterixException {
-        if (varExprMap.isEmpty()) {
-            return expression;
-        }
-        VariableSubstitutionEnvironment env = new VariableSubstitutionEnvironment(varExprMap);
-        return substituteVariableWithoutContext(expression, env);
-    }
-
-    /**
-     * Substitute variables with corresponding expressions according to the varExprMap.
-     * The substitution should be done BEFORE unique ids are assigned to variables.
-     * In other words, when we call this method, ids of all variables are zero.
-     *
-     * @param expression,
-     *            the expression for substituting variables.
-     * @param env,
-     *            internally contains a map that maps variables to their corresponding expressions.
-     * @return a new expression in which variables are substituted.
-     * @throws AsterixException
-     */
-    public static ILangExpression substituteVariableWithoutContext(ILangExpression expression,
-            VariableSubstitutionEnvironment env) throws AsterixException {
-        SqlppSubstituteVariablesVisitor visitor = new SqlppSubstituteVariablesVisitor();
-        return expression.accept(visitor, env).first;
-    }
-
-    /**
-     * Substitute variables with corresponding expressions according to the varExprMap.
-     * The substitution should be done AFTER unique ids are assigned to different variables.
-     *
-     * @param expression,
-     *            the expression for substituting variables.
-     * @param varExprMap,
-     *            a map that maps variables to their corresponding expressions.
-     * @param context,
-     *            manages the ids of variables so as to guarantee the uniqueness of ids for different variables (even with the same name).
-     * @return a cloned new expression in which variables are substituted, and its bounded variables have new unique ids.
-     * @throws AsterixException
-     */
-    public static ILangExpression cloneAndSubstituteVariable(ILangExpression expression,
-            Map<VariableExpr, Expression> varExprMap, LangRewritingContext context) throws AsterixException {
-        SqlppCloneAndSubstituteVariablesVisitor visitor = new SqlppCloneAndSubstituteVariablesVisitor(context);
-        VariableSubstitutionEnvironment env = new VariableSubstitutionEnvironment(varExprMap);
-        return expression.accept(visitor, env).first;
-    }
-}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
index b2a07e1..5352804 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
@@ -77,12 +77,18 @@
         return varName;
     }
 
-    public static Set<VariableExpr> getLiveVariables(Scope scope) {
+    public static Set<VariableExpr> getLiveVariables(Scope scope, boolean includeWithVariables) {
         Set<VariableExpr> results = new HashSet<>();
         Set<VariableExpr> liveVars = scope.getLiveVariables();
         Iterator<VariableExpr> liveVarIter = liveVars.iterator();
         while (liveVarIter.hasNext()) {
-            results.add(liveVarIter.next());
+            VariableExpr liveVar = liveVarIter.next();
+            // Variables defined in WITH clauses are named value access.
+            // TODO(buyingi): remove this if block once we can accurately type
+            // ordered lists with UNION item type. Currently it is typed as [ANY].
+            if (includeWithVariables || !liveVar.getVar().namedValueAccess()) {
+                results.add(liveVar);
+            }
         }
         return results;
     }
@@ -148,7 +154,9 @@
                 bindingVars.add(var);
             }
         }
-        bindingVars.addAll(gbyClause.getWithVarList());
+        if (gbyClause.hasWithMap()) {
+            bindingVars.addAll(gbyClause.getWithVarMap().values());
+        }
         bindingVars.add(gbyClause.getGroupVar());
         return bindingVars;
     }
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
index d752396..75c5307 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
@@ -19,7 +19,10 @@
 package org.apache.asterix.lang.sqlpp.visitor;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.lang.common.base.Expression;
@@ -256,7 +259,7 @@
     public GroupbyClause visit(GroupbyClause gc, Void arg) throws AsterixException {
         List<GbyVariableExpressionPair> gbyPairList = new ArrayList<>();
         List<GbyVariableExpressionPair> decorPairList = new ArrayList<>();
-        List<VariableExpr> withVarList = new ArrayList<>();
+        Map<Expression, VariableExpr> withVarMap = new HashMap<>();
         VariableExpr groupVarExpr = null;
         List<Pair<Expression, Identifier>> groupFieldList = new ArrayList<>();
         for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
@@ -269,8 +272,9 @@
             decorPairList.add(new GbyVariableExpressionPair(var == null ? null : (VariableExpr) var.accept(this, arg),
                     (Expression) gbyVarExpr.getExpr().accept(this, arg)));
         }
-        for (VariableExpr withVar : gc.getWithVarList()) {
-            withVarList.add((VariableExpr) withVar.accept(this, arg));
+        for (Entry<Expression, VariableExpr> entry : gc.getWithVarMap().entrySet()) {
+            withVarMap.put((Expression) entry.getKey().accept(this, arg),
+                    (VariableExpr) entry.getValue().accept(this, arg));
         }
         if (gc.hasGroupVar()) {
             groupVarExpr = (VariableExpr) gc.getGroupVar().accept(this, arg);
@@ -278,7 +282,7 @@
         for (Pair<Expression, Identifier> field : gc.getGroupFieldList()) {
             groupFieldList.add(new Pair<>((Expression) field.first.accept(this, arg), field.second));
         }
-        return new GroupbyClause(gbyPairList, decorPairList, withVarList, groupVarExpr, groupFieldList,
+        return new GroupbyClause(gbyPairList, decorPairList, withVarMap, groupVarExpr, groupFieldList,
                 gc.hasHashGroupByHint(), gc.isGroupAll());
     }
 
@@ -386,10 +390,8 @@
 
     @Override
     public VariableExpr visit(VariableExpr varExpr, Void arg) throws AsterixException {
-        VariableExpr clonedVar =
-                new VariableExpr(new VarIdentifier(varExpr.getVar().getValue(), varExpr.getVar().getId()));
+        VariableExpr clonedVar = new VariableExpr(new VarIdentifier(varExpr.getVar()));
         clonedVar.setIsNewVar(varExpr.getIsNewVar());
-        clonedVar.setNamedValueAccess(varExpr.namedValueAccess());
         return clonedVar;
     }
 
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
index 20b144c..3a9bebf 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
@@ -23,8 +23,8 @@
 import java.util.List;
 
 import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.lang.common.base.Clause.ClauseType;
 import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.Clause.ClauseType;
 import org.apache.asterix.lang.common.clause.GroupbyClause;
 import org.apache.asterix.lang.common.clause.LetClause;
 import org.apache.asterix.lang.common.clause.LimitClause;
@@ -144,7 +144,9 @@
 
     @Override
     public Void visit(Projection projection, Collection<VariableExpr> freeVars) throws AsterixException {
-        projection.getExpression().accept(this, freeVars);
+        if (!projection.star()) {
+            projection.getExpression().accept(this, freeVars);
+        }
         return null;
     }
 
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java
index 23181e4..81aba54 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java
@@ -22,9 +22,9 @@
 import java.util.List;
 
 import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.lang.common.base.Clause.ClauseType;
 import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.base.Clause.ClauseType;
 import org.apache.asterix.lang.common.clause.GroupbyClause;
 import org.apache.asterix.lang.common.clause.LetClause;
 import org.apache.asterix.lang.common.clause.LimitClause;
@@ -86,8 +86,8 @@
             VariableSubstitutionEnvironment env) throws AsterixException {
         VariableExpr leftVar = fromTerm.getLeftVariable();
         VariableExpr newLeftVar = generateNewVariable(context, leftVar);
-        VariableExpr newLeftPosVar = fromTerm.hasPositionalVariable()
-                ? generateNewVariable(context, fromTerm.getPositionalVariable()) : null;
+        VariableExpr newLeftPosVar = fromTerm.hasPositionalVariable() ? generateNewVariable(context,
+                fromTerm.getPositionalVariable()) : null;
         Expression newLeftExpr = (Expression) visitUnnesBindingExpression(fromTerm.getLeftExpression(), env).first;
         List<AbstractBinaryCorrelateClause> newCorrelateClauses = new ArrayList<>();
 
@@ -108,6 +108,11 @@
                 // The right-hand-side of join and nest could not be correlated with the left side,
                 // therefore we propagate the original substitution environment.
                 newCorrelateClauses.add((AbstractBinaryCorrelateClause) correlateClause.accept(this, env).first);
+                // Join binding variables should be removed for further traversal.
+                currentEnv.removeSubstitution(correlateClause.getRightVariable());
+                if (correlateClause.hasPositionalVariable()) {
+                    currentEnv.removeSubstitution(correlateClause.getPositionalVariable());
+                }
             }
         }
         return new Pair<>(new FromTerm(newLeftExpr, newLeftVar, newLeftPosVar, newCorrelateClauses), currentEnv);
@@ -118,8 +123,8 @@
             VariableSubstitutionEnvironment env) throws AsterixException {
         VariableExpr rightVar = joinClause.getRightVariable();
         VariableExpr newRightVar = generateNewVariable(context, rightVar);
-        VariableExpr newRightPosVar = joinClause.hasPositionalVariable()
-                ? generateNewVariable(context, joinClause.getPositionalVariable()) : null;
+        VariableExpr newRightPosVar = joinClause.hasPositionalVariable() ? generateNewVariable(context,
+                joinClause.getPositionalVariable()) : null;
 
         // Visits the right expression.
         Expression newRightExpr = (Expression) visitUnnesBindingExpression(joinClause.getRightExpression(), env).first;
@@ -133,8 +138,8 @@
         // The condition can refer to the newRightVar and newRightPosVar.
         Expression conditionExpr = (Expression) joinClause.getConditionExpression().accept(this, currentEnv).first;
 
-        JoinClause newJoinClause =
-                new JoinClause(joinClause.getJoinType(), newRightExpr, newRightVar, newRightPosVar, conditionExpr);
+        JoinClause newJoinClause = new JoinClause(joinClause.getJoinType(), newRightExpr, newRightVar, newRightPosVar,
+                conditionExpr);
         return new Pair<>(newJoinClause, currentEnv);
     }
 
@@ -143,8 +148,8 @@
             VariableSubstitutionEnvironment env) throws AsterixException {
         VariableExpr rightVar = nestClause.getRightVariable();
         VariableExpr newRightVar = generateNewVariable(context, rightVar);
-        VariableExpr newRightPosVar = nestClause.hasPositionalVariable()
-                ? generateNewVariable(context, nestClause.getPositionalVariable()) : null;
+        VariableExpr newRightPosVar = nestClause.hasPositionalVariable() ? generateNewVariable(context,
+                nestClause.getPositionalVariable()) : null;
 
         // Visits the right expression.
         Expression rightExpr = (Expression) nestClause.getRightExpression().accept(this, env).first;
@@ -158,8 +163,8 @@
         // The condition can refer to the newRightVar and newRightPosVar.
         Expression conditionExpr = (Expression) nestClause.getConditionExpression().accept(this, currentEnv).first;
 
-        NestClause newJoinClause =
-                new NestClause(nestClause.getJoinType(), rightExpr, newRightVar, newRightPosVar, conditionExpr);
+        NestClause newJoinClause = new NestClause(nestClause.getJoinType(), rightExpr, newRightVar, newRightPosVar,
+                conditionExpr);
         return new Pair<>(newJoinClause, currentEnv);
     }
 
@@ -168,8 +173,8 @@
             VariableSubstitutionEnvironment env) throws AsterixException {
         VariableExpr rightVar = unnestClause.getRightVariable();
         VariableExpr newRightVar = generateNewVariable(context, rightVar);
-        VariableExpr newRightPosVar = unnestClause.hasPositionalVariable()
-                ? generateNewVariable(context, unnestClause.getPositionalVariable()) : null;
+        VariableExpr newRightPosVar = unnestClause.hasPositionalVariable() ? generateNewVariable(context,
+                unnestClause.getPositionalVariable()) : null;
 
         // Visits the right expression.
         Expression rightExpr = (Expression) visitUnnesBindingExpression(unnestClause.getRightExpression(), env).first;
@@ -181,8 +186,8 @@
             currentEnv.removeSubstitution(newRightPosVar);
         }
         // The condition can refer to the newRightVar and newRightPosVar.
-        UnnestClause newJoinClause =
-                new UnnestClause(unnestClause.getJoinType(), rightExpr, newRightVar, newRightPosVar);
+        UnnestClause newJoinClause = new UnnestClause(unnestClause.getJoinType(), rightExpr, newRightVar,
+                newRightPosVar);
         return new Pair<>(newJoinClause, currentEnv);
     }
 
@@ -217,7 +222,7 @@
 
         if (selectBlock.hasLetClauses()) {
             for (LetClause letClause : selectBlock.getLetList()) {
-                newLet = letClause.accept(this, env);
+                newLet = letClause.accept(this, currentEnv);
                 currentEnv = newLet.second;
                 newLetClauses.add(letClause);
             }
@@ -233,7 +238,7 @@
             currentEnv = newGroupby.second;
             if (selectBlock.hasLetClausesAfterGroupby()) {
                 for (LetClause letClauseAfterGby : selectBlock.getLetListAfterGroupby()) {
-                    newLet = letClauseAfterGby.accept(this, env);
+                    newLet = letClauseAfterGby.accept(this, currentEnv);
                     currentEnv = newLet.second;
                     newLetClausesAfterGby.add(letClauseAfterGby);
                 }
@@ -260,13 +265,13 @@
             VariableSubstitutionEnvironment env) throws AsterixException {
         boolean distinct = selectClause.distinct();
         if (selectClause.selectElement()) {
-            Pair<ILangExpression, VariableSubstitutionEnvironment> newSelectElement =
-                    selectClause.getSelectElement().accept(this, env);
+            Pair<ILangExpression, VariableSubstitutionEnvironment> newSelectElement = selectClause.getSelectElement()
+                    .accept(this, env);
             return new Pair<>(new SelectClause((SelectElement) newSelectElement.first, null, distinct),
                     newSelectElement.second);
         } else {
-            Pair<ILangExpression, VariableSubstitutionEnvironment> newSelectRegular =
-                    selectClause.getSelectRegular().accept(this, env);
+            Pair<ILangExpression, VariableSubstitutionEnvironment> newSelectRegular = selectClause.getSelectRegular()
+                    .accept(this, env);
             return new Pair<>(new SelectClause(null, (SelectRegular) newSelectRegular.first, distinct),
                     newSelectRegular.second);
         }
@@ -275,8 +280,8 @@
     @Override
     public Pair<ILangExpression, VariableSubstitutionEnvironment> visit(SelectElement selectElement,
             VariableSubstitutionEnvironment env) throws AsterixException {
-        Pair<ILangExpression, VariableSubstitutionEnvironment> newExpr =
-                selectElement.getExpression().accept(this, env);
+        Pair<ILangExpression, VariableSubstitutionEnvironment> newExpr = selectElement.getExpression()
+                .accept(this, env);
         return new Pair<>(new SelectElement((Expression) newExpr.first), newExpr.second);
     }
 
@@ -296,32 +301,36 @@
         SetOperationInput leftInput = selectSetOperation.getLeftInput();
         SetOperationInput newLeftInput;
 
+        Pair<ILangExpression, VariableSubstitutionEnvironment> leftResult;
         // Sets the left input.
         if (leftInput.selectBlock()) {
-            Pair<ILangExpression, VariableSubstitutionEnvironment> p = leftInput.getSelectBlock().accept(this, env);
-            newLeftInput = new SetOperationInput((SelectBlock) p.first, null);
+            leftResult = leftInput.getSelectBlock().accept(this, env);
+            newLeftInput = new SetOperationInput((SelectBlock) leftResult.first, null);
         } else {
-            Pair<ILangExpression, VariableSubstitutionEnvironment> p = leftInput.getSubquery().accept(this, env);
-            newLeftInput = new SetOperationInput(null, (SelectExpression) p.first);
+            leftResult = leftInput.getSubquery().accept(this, env);
+            newLeftInput = new SetOperationInput(null, (SelectExpression) leftResult.first);
         }
 
         // Sets the right input
         List<SetOperationRight> newRightInputs = new ArrayList<>();
-        for (SetOperationRight right : selectSetOperation.getRightInputs()) {
-            SetOperationInput newRightInput;
-            SetOperationInput rightInput = right.getSetOperationRightInput();
-            if (rightInput.selectBlock()) {
-                Pair<ILangExpression, VariableSubstitutionEnvironment> p =
-                        rightInput.getSelectBlock().accept(this, env);
-                newRightInput = new SetOperationInput((SelectBlock) p.first, null);
-            } else {
-                Pair<ILangExpression, VariableSubstitutionEnvironment> p = rightInput.getSubquery().accept(this, env);
-                newRightInput = new SetOperationInput(null, (SelectExpression) p.first);
+        if (selectSetOperation.hasRightInputs()) {
+            for (SetOperationRight right : selectSetOperation.getRightInputs()) {
+                SetOperationInput newRightInput;
+                SetOperationInput rightInput = right.getSetOperationRightInput();
+                if (rightInput.selectBlock()) {
+                    Pair<ILangExpression, VariableSubstitutionEnvironment> rightResult = rightInput.getSelectBlock()
+                            .accept(this, env);
+                    newRightInput = new SetOperationInput((SelectBlock) rightResult.first, null);
+                } else {
+                    Pair<ILangExpression, VariableSubstitutionEnvironment> rightResult = rightInput.getSubquery()
+                            .accept(this, env);
+                    newRightInput = new SetOperationInput(null, (SelectExpression) rightResult.first);
+                }
+                newRightInputs.add(new SetOperationRight(right.getSetOpType(), right.isSetSemantics(), newRightInput));
             }
-            newRightInputs.add(new SetOperationRight(right.getSetOpType(), right.isSetSemantics(), newRightInput));
         }
         SelectSetOperation newSelectSetOperation = new SelectSetOperation(newLeftInput, newRightInputs);
-        return new Pair<>(newSelectSetOperation, env);
+        return new Pair<>(newSelectSetOperation, selectSetOperation.hasRightInputs() ? env : leftResult.second);
     }
 
     @Override
@@ -348,13 +357,13 @@
         currentEnv = p.second;
 
         if (selectExpression.hasOrderby()) {
-            p = selectExpression.getOrderbyClause().accept(this, env);
+            p = selectExpression.getOrderbyClause().accept(this, currentEnv);
             newOrderbyClause = (OrderbyClause) p.first;
             currentEnv = p.second;
         }
 
         if (selectExpression.hasLimit()) {
-            p = selectExpression.getLimitClause().accept(this, env);
+            p = selectExpression.getLimitClause().accept(this, currentEnv);
             newLimitClause = (LimitClause) p.first;
             currentEnv = p.second;
         }
@@ -383,10 +392,10 @@
     public Pair<ILangExpression, VariableSubstitutionEnvironment> visit(CaseExpression caseExpr,
             VariableSubstitutionEnvironment env) throws AsterixException {
         Expression conditionExpr = (Expression) caseExpr.getConditionExpr().accept(this, env).first;
-        List<Expression> whenExprList =
-                VariableCloneAndSubstitutionUtil.visitAndCloneExprList(caseExpr.getWhenExprs(), env, this);
-        List<Expression> thenExprList =
-                VariableCloneAndSubstitutionUtil.visitAndCloneExprList(caseExpr.getThenExprs(), env, this);
+        List<Expression> whenExprList = VariableCloneAndSubstitutionUtil.visitAndCloneExprList(caseExpr.getWhenExprs(),
+                env, this);
+        List<Expression> thenExprList = VariableCloneAndSubstitutionUtil.visitAndCloneExprList(caseExpr.getThenExprs(),
+                env, this);
         Expression elseExpr = (Expression) caseExpr.getElseExpr().accept(this, env).first;
         CaseExpression newCaseExpr = new CaseExpression(conditionExpr, whenExprList, thenExprList, elseExpr);
         return new Pair<>(newCaseExpr, env);
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionVisitor.java
new file mode 100644
index 0000000..9b19d7c
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionVisitor.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.lang.sqlpp.visitor;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.context.Scope;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
+import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;
+
+/**
+ * This visitor is used to substitute expressions in a visiting language structure
+ * with an given map.
+ */
+public class SqlppSubstituteExpressionVisitor extends AbstractSqlppExpressionScopingVisitor {
+
+    private final Map<Expression, Expression> exprMap = new HashMap<>();
+
+    public SqlppSubstituteExpressionVisitor(LangRewritingContext context, Map<Expression, Expression> exprMap) {
+        super(context);
+        this.exprMap.putAll(exprMap);
+    }
+
+    // Note: we intentionally override preVisit instead of postVisit because we wants larger expressions
+    // get substituted first if some of their child expressions are present as keys in the exprMap.
+    // An example is:
+    // asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/group-by/gby-expr-3/gby-expr-3.3.query.sqlpp
+    @Override
+    protected Expression preVisit(Expression expr) throws AsterixException {
+        Expression mappedExpr = exprMap.get(expr);
+        if (mappedExpr == null) {
+            return expr;
+        }
+        Collection<VariableExpr> freeVars = SqlppVariableUtil.getFreeVariables(expr);
+        for (VariableExpr freeVar : freeVars) {
+            Scope currentScope = scopeChecker.getCurrentScope();
+            if (currentScope.findSymbol(freeVar.getVar().getValue()) != null) {
+                // If the expression to be substituted uses variables defined in the outer-most expresion
+                // that is being visited, we shouldn't perform the substitution.
+                return expr;
+            }
+        }
+        // Makes a deep copy before returning to avoid shared references.
+        return (Expression) SqlppRewriteUtil.deepCopy(mappedExpr);
+    }
+}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionsVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionsVisitor.java
deleted file mode 100644
index d9b2698..0000000
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteExpressionsVisitor.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.asterix.lang.sqlpp.visitor;
-
-import java.util.List;
-
-import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.clause.GroupbyClause;
-import org.apache.asterix.lang.common.clause.LetClause;
-import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
-import org.apache.asterix.lang.common.rewrites.ExpressionSubstitutionEnvironment;
-import org.apache.asterix.lang.common.visitor.SubstituteExpressionVisitor;
-import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
-import org.apache.asterix.lang.sqlpp.clause.FromClause;
-import org.apache.asterix.lang.sqlpp.clause.FromTerm;
-import org.apache.asterix.lang.sqlpp.clause.HavingClause;
-import org.apache.asterix.lang.sqlpp.clause.JoinClause;
-import org.apache.asterix.lang.sqlpp.clause.NestClause;
-import org.apache.asterix.lang.sqlpp.clause.Projection;
-import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
-import org.apache.asterix.lang.sqlpp.clause.SelectClause;
-import org.apache.asterix.lang.sqlpp.clause.SelectElement;
-import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
-import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
-import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
-import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
-import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
-import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
-import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
-import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
-import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
-
-public class SqlppSubstituteExpressionsVisitor extends SubstituteExpressionVisitor
-        implements ISqlppVisitor<Expression, ExpressionSubstitutionEnvironment> {
-
-    public SqlppSubstituteExpressionsVisitor() {
-        super(SqlppRewriteUtil::deepCopy);
-    }
-
-    @Override
-    public Expression visit(GroupbyClause gc, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        for (GbyVariableExpressionPair pair : gc.getGbyPairList()) {
-            pair.setExpr(pair.getExpr().accept(this, env));
-        }
-        // Forces from binding variables to exit their scopes, i.e.,
-        // one can still replace from binding variables.
-        env.pop();
-        for (GbyVariableExpressionPair pair : gc.getGbyPairList()) {
-            env.disableVariable(pair.getVar());
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(FromClause fromClause, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        // Marks the states before the from clause, and a consequent
-        // group-by clause will reset env to the state.
-        env.mark();
-        for (FromTerm fromTerm : fromClause.getFromTerms()) {
-            fromTerm.accept(this, env);
-            // From terms are correlated and thus we mask binding variables after
-            // visiting each individual from term.
-            env.disableVariable(fromTerm.getLeftVariable());
-            if (fromTerm.hasPositionalVariable()) {
-                env.disableVariable(fromTerm.getLeftVariable());
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(FromTerm fromTerm, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        fromTerm.setLeftExpression(fromTerm.getLeftExpression().accept(this, env));
-        if (fromTerm.hasCorrelateClauses()) {
-            for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
-                correlateClause.accept(this, env);
-            }
-            // correlate clauses are independent and thus we mask their binding variables
-            // after visiting them.
-            for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
-                env.disableVariable(correlateClause.getRightVariable());
-                if (correlateClause.hasPositionalVariable()) {
-                    env.disableVariable(correlateClause.getPositionalVariable());
-                }
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(JoinClause joinClause, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        joinClause.setRightExpression(joinClause.getRightExpression().accept(this, env));
-        // Condition expressions can see the join binding variables, thus we have to mask them for replacement.
-        env.disableVariable(joinClause.getRightVariable());
-        if (joinClause.hasPositionalVariable()) {
-            env.disableVariable(joinClause.getPositionalVariable());
-        }
-        joinClause.setConditionExpression(joinClause.getConditionExpression().accept(this, env));
-        // Re-enable them.
-        env.enableVariable(joinClause.getRightVariable());
-        if (joinClause.hasPositionalVariable()) {
-            env.enableVariable(joinClause.getPositionalVariable());
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(NestClause nestClause, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        nestClause.setRightExpression(nestClause.getRightExpression().accept(this, env));
-        // Condition expressions can see the join binding variables, thus we have to mask them for replacement.
-        env.disableVariable(nestClause.getRightVariable());
-        if (nestClause.hasPositionalVariable()) {
-            env.disableVariable(nestClause.getPositionalVariable());
-        }
-        nestClause.setConditionExpression(nestClause.getConditionExpression().accept(this, env));
-        // Re-enable them.
-        env.enableVariable(nestClause.getRightVariable());
-        if (nestClause.hasPositionalVariable()) {
-            env.enableVariable(nestClause.getPositionalVariable());
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(Projection projection, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        if (!projection.star()) {
-            projection.setExpression(projection.getExpression().accept(this, env));
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(SelectBlock selectBlock, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        // Traverses the select block in the order of "from", "let"s, "where",
-        // "group by", "let"s, "having" and "select".
-        if (selectBlock.hasFromClause()) {
-            selectBlock.getFromClause().accept(this, env);
-        }
-        if (selectBlock.hasLetClauses()) {
-            List<LetClause> letList = selectBlock.getLetList();
-            for (LetClause letClause : letList) {
-                letClause.accept(this, env);
-            }
-        }
-        if (selectBlock.hasWhereClause()) {
-            selectBlock.getWhereClause().accept(this, env);
-        }
-        if (selectBlock.hasGroupbyClause()) {
-            selectBlock.getGroupbyClause().accept(this, env);
-        }
-        if (selectBlock.hasLetClausesAfterGroupby()) {
-            List<LetClause> letListAfterGby = selectBlock.getLetListAfterGroupby();
-            for (LetClause letClauseAfterGby : letListAfterGby) {
-                letClauseAfterGby.accept(this, env);
-            }
-        }
-        if (selectBlock.hasHavingClause()) {
-            selectBlock.getHavingClause().accept(this, env);
-        }
-        selectBlock.getSelectClause().accept(this, env);
-        return null;
-    }
-
-    @Override
-    public Expression visit(SelectClause selectClause, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        if (selectClause.selectElement()) {
-            selectClause.getSelectElement().accept(this, env);
-        } else {
-            selectClause.getSelectRegular().accept(this, env);
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(SelectElement selectElement, ExpressionSubstitutionEnvironment env)
-            throws AsterixException {
-        selectElement.setExpression(selectElement.getExpression().accept(this, env));
-        return null;
-    }
-
-    @Override
-    public Expression visit(SelectRegular selectRegular, ExpressionSubstitutionEnvironment env)
-            throws AsterixException {
-        for (Projection projection : selectRegular.getProjections()) {
-            projection.accept(this, env);
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(SelectSetOperation selectSetOperation, ExpressionSubstitutionEnvironment env)
-            throws AsterixException {
-        selectSetOperation.getLeftInput().accept(this, env);
-        for (SetOperationRight right : selectSetOperation.getRightInputs()) {
-            right.getSetOperationRightInput().accept(this, env);
-        }
-        return null;
-    }
-
-    @Override
-    public Expression visit(SelectExpression selectExpression, ExpressionSubstitutionEnvironment env)
-            throws AsterixException {
-        // Backups the current states of env and the end of this method will reset to the returned depth.
-        int depth = env.mark();
-        // visit let list
-        if (selectExpression.hasLetClauses()) {
-            for (LetClause letClause : selectExpression.getLetList()) {
-                letClause.accept(this, env);
-            }
-        }
-
-        // visit the main select.
-        selectExpression.getSelectSetOperation().accept(this, env);
-
-        // visit order by.
-        if (selectExpression.hasOrderby()) {
-            selectExpression.getOrderbyClause().accept(this, env);
-        }
-
-        // visit limit
-        if (selectExpression.hasLimit()) {
-            selectExpression.getLimitClause().accept(this, env);
-        }
-
-        // re-enable the replacements all of all binding variables in the current scope.
-        if (selectExpression.hasLetClauses()) {
-            for (LetClause letClause : selectExpression.getLetList()) {
-                env.enableVariable(letClause.getVarExpr());
-            }
-        }
-        // Restores the states of env to be the same as the beginning .
-        env.reset(depth);
-        return selectExpression;
-    }
-
-    @Override
-    public Expression visit(UnnestClause unnestClause, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        unnestClause.setRightExpression(unnestClause.getRightExpression().accept(this, env));
-        return null;
-    }
-
-    @Override
-    public Expression visit(HavingClause havingClause, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        havingClause.setFilterExpression(havingClause.getFilterExpression().accept(this, env));
-        return null;
-    }
-
-    @Override
-    public Expression visit(IndependentSubquery independentSubquery, ExpressionSubstitutionEnvironment env)
-            throws AsterixException {
-        independentSubquery.setExpr(independentSubquery.getExpr().accept(this, env));
-        return null;
-    }
-
-    @Override
-    public Expression visit(CaseExpression caseExpr, ExpressionSubstitutionEnvironment env) throws AsterixException {
-        Expression newCaseExpr = env.findSubstitution(caseExpr, deepCopier);
-        if (newCaseExpr == caseExpr) {
-            caseExpr.setConditionExpr(caseExpr.getConditionExpr().accept(this, env));
-            caseExpr.setWhenExprs(rewriteExpressionList(caseExpr.getWhenExprs(), env));
-            caseExpr.setThenExprs(rewriteExpressionList(caseExpr.getThenExprs(), env));
-            caseExpr.setElseExpr(caseExpr.getElseExpr().accept(this, env));
-            return caseExpr;
-        } else {
-            return newCaseExpr.accept(this, env);
-        }
-    }
-
-}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteVariablesVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteVariablesVisitor.java
deleted file mode 100644
index 923f86d..0000000
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppSubstituteVariablesVisitor.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.asterix.lang.sqlpp.visitor;
-
-import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.expression.VariableExpr;
-import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
-import org.apache.asterix.lang.common.rewrites.VariableSubstitutionEnvironment;
-import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
-
-public class SqlppSubstituteVariablesVisitor extends SqlppCloneAndSubstituteVariablesVisitor {
-
-    public SqlppSubstituteVariablesVisitor() {
-        super(null);
-    }
-
-    @Override
-    protected Expression rewriteVariableExpr(VariableExpr expr, VariableSubstitutionEnvironment env)
-            throws AsterixException {
-        if (env.constainsOldVar(expr)) {
-            return (Expression) SqlppRewriteUtil.deepCopy(env.findSubstitution(expr));
-        }
-        return expr;
-    }
-
-    @Override
-    public VariableExpr generateNewVariable(LangRewritingContext context, VariableExpr varExpr) {
-        return varExpr;
-    }
-
-}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
index 13ec855..c13f00d 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
@@ -19,7 +19,10 @@
 package org.apache.asterix.lang.sqlpp.visitor.base;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 import org.apache.asterix.common.config.MetadataConstants;
@@ -55,6 +58,7 @@
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
+import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.algebricks.core.algebra.base.Counter;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 
@@ -87,7 +91,7 @@
     public Expression visit(FromTerm fromTerm, ILangExpression arg) throws AsterixException {
         scopeChecker.createNewScope();
         // Visit the left expression of a from term.
-        fromTerm.setLeftExpression(fromTerm.getLeftExpression().accept(this, fromTerm));
+        fromTerm.setLeftExpression(visit(fromTerm.getLeftExpression(), fromTerm));
 
         // Registers the data item variable.
         VariableExpr leftVar = fromTerm.getLeftVariable();
@@ -113,7 +117,7 @@
         // NOTE: the two join branches cannot be correlated, instead of checking
         // the correlation here,
         // we defer the check to the query optimizer.
-        joinClause.setRightExpression(joinClause.getRightExpression().accept(this, joinClause));
+        joinClause.setRightExpression(visit(joinClause.getRightExpression(), joinClause));
 
         // Registers the data item variable.
         VariableExpr rightVar = joinClause.getRightVariable();
@@ -132,7 +136,7 @@
         scopeChecker.pushExistingScope(mergedScope);
         // The condition expression can refer to the just registered variables
         // for the right branch.
-        joinClause.setConditionExpression(joinClause.getConditionExpression().accept(this, joinClause));
+        joinClause.setConditionExpression(visit(joinClause.getConditionExpression(), joinClause));
         return null;
     }
 
@@ -141,7 +145,7 @@
         // NOTE: the two branches of a NEST cannot be correlated, instead of
         // checking the correlation here, we defer the check to the query
         // optimizer.
-        nestClause.setRightExpression(nestClause.getRightExpression().accept(this, nestClause));
+        nestClause.setRightExpression(visit(nestClause.getRightExpression(), nestClause));
 
         // Registers the data item variable.
         VariableExpr rightVar = nestClause.getRightVariable();
@@ -155,13 +159,13 @@
 
         // The condition expression can refer to the just registered variables
         // for the right branch.
-        nestClause.setConditionExpression(nestClause.getConditionExpression().accept(this, nestClause));
+        nestClause.setConditionExpression(visit(nestClause.getConditionExpression(), nestClause));
         return null;
     }
 
     @Override
     public Expression visit(UnnestClause unnestClause, ILangExpression arg) throws AsterixException {
-        unnestClause.setRightExpression(unnestClause.getRightExpression().accept(this, unnestClause));
+        unnestClause.setRightExpression(visit(unnestClause.getRightExpression(), unnestClause));
 
         // register the data item variable
         VariableExpr rightVar = unnestClause.getRightVariable();
@@ -199,7 +203,7 @@
 
     @Override
     public Expression visit(Query q, ILangExpression arg) throws AsterixException {
-        q.setBody(q.getBody().accept(this, q));
+        q.setBody(visit(q.getBody(), q));
         q.setVarCounter(scopeChecker.getVarCounter());
         context.setVarCounter(scopeChecker.getVarCounter());
         return null;
@@ -208,25 +212,53 @@
     @Override
     public Expression visit(FunctionDecl fd, ILangExpression arg) throws AsterixException {
         scopeChecker.createNewScope();
-        fd.setFuncBody(fd.getFuncBody().accept(this, fd));
+        fd.setFuncBody(visit(fd.getFuncBody(), fd));
         scopeChecker.removeCurrentScope();
         return null;
     }
 
     @Override
     public Expression visit(GroupbyClause gc, ILangExpression arg) throws AsterixException {
-        Scope newScope = scopeChecker.extendCurrentScopeNoPush(true);
+        // After a GROUP BY, variables defined before the current SELECT BLOCK (e.g., in a WITH clause
+        // or an outer scope query) should still be visible.
+        Scope newScope = new Scope(scopeChecker, scopeChecker.getCurrentScope().getParentScope());
         // Puts all group-by variables into the symbol set of the new scope.
-        for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
-            gbyVarExpr.setExpr(gbyVarExpr.getExpr().accept(this, gc));
-            VariableExpr gbyVar = gbyVarExpr.getVar();
-            if (gbyVar != null) {
-                newScope.addNewVarSymbolToScope(gbyVarExpr.getVar().getVar());
+        for (GbyVariableExpressionPair gbyKeyVarExpr : gc.getGbyPairList()) {
+            gbyKeyVarExpr.setExpr(visit(gbyKeyVarExpr.getExpr(), gc));
+            VariableExpr gbyKeyVar = gbyKeyVarExpr.getVar();
+            if (gbyKeyVar != null) {
+                newScope.addNewVarSymbolToScope(gbyKeyVar.getVar());
             }
         }
-        for (VariableExpr withVar : gc.getWithVarList()) {
-            newScope.addNewVarSymbolToScope(withVar.getVar());
+        if (gc.hasGroupFieldList()) {
+            for (Pair<Expression, Identifier> gbyField : gc.getGroupFieldList()) {
+                gbyField.first = visit(gbyField.first, arg);
+            }
         }
+        if (gc.hasDecorList()) {
+            for (GbyVariableExpressionPair decorVarExpr : gc.getDecorPairList()) {
+                decorVarExpr.setExpr(visit(decorVarExpr.getExpr(), gc));
+                VariableExpr decorVar = decorVarExpr.getVar();
+                if (decorVar != null) {
+                    newScope.addNewVarSymbolToScope(decorVar.getVar());
+                }
+            }
+        }
+        if (gc.hasGroupVar()) {
+            scopeChecker.getCurrentScope().addNewVarSymbolToScope(gc.getGroupVar().getVar());
+        }
+        if (gc.hasWithMap()) {
+            Map<Expression, VariableExpr> newWithMap = new HashMap<>();
+            for (Entry<Expression, VariableExpr> entry : gc.getWithVarMap().entrySet()) {
+                Expression expr = visit(entry.getKey(), arg);
+                Expression newKey = expr;
+                VariableExpr value = entry.getValue();
+                newScope.addNewVarSymbolToScope(value.getVar());
+                newWithMap.put(newKey, value);
+            }
+            gc.setWithVarMap(newWithMap);
+        }
+        // Replaces the current scope with the new scope.
         scopeChecker.replaceCurrentScope(newScope);
         return null;
     }
@@ -234,7 +266,10 @@
     @Override
     public Expression visit(LimitClause limitClause, ILangExpression arg) throws AsterixException {
         scopeChecker.pushForbiddenScope(scopeChecker.getCurrentScope());
-        limitClause.setLimitExpr(limitClause.getLimitExpr().accept(this, limitClause));
+        limitClause.setLimitExpr(visit(limitClause.getLimitExpr(), limitClause));
+        if(limitClause.hasOffset()) {
+            limitClause.setOffset(visit(limitClause.getOffset(), limitClause));
+        }
         scopeChecker.popForbiddenScope();
         return null;
     }
@@ -242,7 +277,7 @@
     @Override
     public Expression visit(LetClause letClause, ILangExpression arg) throws AsterixException {
         scopeChecker.extendCurrentScope();
-        letClause.setBindingExpr(letClause.getBindingExpr().accept(this, letClause));
+        letClause.setBindingExpr(visit(letClause.getBindingExpr(), letClause));
         scopeChecker.getCurrentScope().addNewVarSymbolToScope(letClause.getVarExpr().getVar());
         return null;
     }
@@ -255,8 +290,11 @@
         // visit let list
         if (selectExpression.hasLetClauses()) {
             for (LetClause letClause : selectExpression.getLetList()) {
+                // Variables defined in WITH clauses are considered as named access instead of real variables.
+                letClause.getVarExpr().getVar().setNamedValueAccess(true);
                 letClause.accept(this, selectExpression);
             }
+            scopeChecker.createNewScope();
         }
 
         // visit the main select.
@@ -286,7 +324,7 @@
         // variables defined in the parent scope.
         Scope scope = new Scope(scopeChecker, scopeChecker.getCurrentScope(), true);
         scopeChecker.pushExistingScope(scope);
-        independentSubquery.setExpr(independentSubquery.getExpr().accept(this, independentSubquery));
+        independentSubquery.setExpr(visit(independentSubquery.getExpr(), independentSubquery));
         scopeChecker.removeCurrentScope();
         return independentSubquery;
     }
@@ -295,10 +333,10 @@
     public Expression visit(QuantifiedExpression qe, ILangExpression arg) throws AsterixException {
         scopeChecker.createNewScope();
         for (QuantifiedPair pair : qe.getQuantifiedList()) {
-            pair.setExpr(pair.getExpr().accept(this, qe));
+            pair.setExpr(visit(pair.getExpr(), qe));
             scopeChecker.getCurrentScope().addNewVarSymbolToScope(pair.getVarExpr().getVar());
         }
-        qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, qe));
+        qe.setSatisfiesExpr(visit(qe.getSatisfiesExpr(), qe));
         scopeChecker.removeCurrentScope();
         return qe;
     }
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
index 423eb40..21883f7 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
@@ -21,6 +21,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.antlr.stringtemplate.language.Expr;
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.base.ILangExpression;
@@ -69,7 +70,7 @@
     @Override
     public Expression visit(FromClause fromClause, ILangExpression arg) throws AsterixException {
         for (FromTerm fromTerm : fromClause.getFromTerms()) {
-            fromTerm.accept(this, arg);
+            visit(fromTerm, arg);
         }
         return null;
     }
@@ -77,7 +78,7 @@
     @Override
     public Expression visit(FromTerm fromTerm, ILangExpression arg) throws AsterixException {
         // Visit the left expression of a from term.
-        fromTerm.setLeftExpression(fromTerm.getLeftExpression().accept(this, arg));
+        fromTerm.setLeftExpression(visit(fromTerm.getLeftExpression(), arg));
 
         // Visits join/unnest/nest clauses.
         for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
@@ -88,28 +89,28 @@
 
     @Override
     public Expression visit(JoinClause joinClause, ILangExpression arg) throws AsterixException {
-        joinClause.setRightExpression(joinClause.getRightExpression().accept(this, arg));
-        joinClause.setConditionExpression(joinClause.getConditionExpression().accept(this, arg));
+        joinClause.setRightExpression(visit(joinClause.getRightExpression(), arg));
+        joinClause.setConditionExpression(visit(joinClause.getConditionExpression(), arg));
         return null;
     }
 
     @Override
     public Expression visit(NestClause nestClause, ILangExpression arg) throws AsterixException {
-        nestClause.setRightExpression(nestClause.getRightExpression().accept(this, arg));
-        nestClause.setConditionExpression(nestClause.getConditionExpression().accept(this, arg));
+        nestClause.setRightExpression(visit(nestClause.getRightExpression(), arg));
+        nestClause.setConditionExpression(visit(nestClause.getConditionExpression(), arg));
         return null;
     }
 
     @Override
     public Expression visit(UnnestClause unnestClause, ILangExpression arg) throws AsterixException {
-        unnestClause.setRightExpression(unnestClause.getRightExpression().accept(this, arg));
+        unnestClause.setRightExpression(visit(unnestClause.getRightExpression(), arg));
         return null;
     }
 
     @Override
     public Expression visit(Projection projection, ILangExpression arg) throws AsterixException {
         if (!projection.star()) {
-            projection.setExpression(projection.getExpression().accept(this, arg));
+            projection.setExpression(visit(projection.getExpression(), arg));
         }
         return null;
     }
@@ -159,7 +160,7 @@
 
     @Override
     public Expression visit(SelectElement selectElement, ILangExpression arg) throws AsterixException {
-        selectElement.setExpression(selectElement.getExpression().accept(this, selectElement));
+        selectElement.setExpression(visit(selectElement.getExpression(), selectElement));
         return null;
     }
 
@@ -182,58 +183,54 @@
 
     @Override
     public Expression visit(HavingClause havingClause, ILangExpression arg) throws AsterixException {
-        havingClause.setFilterExpression(havingClause.getFilterExpression().accept(this, havingClause));
+        havingClause.setFilterExpression(visit(havingClause.getFilterExpression(), havingClause));
         return null;
     }
 
     @Override
     public Expression visit(Query q, ILangExpression arg) throws AsterixException {
-        q.setBody(q.getBody().accept(this, q));
+        q.setBody(visit(q.getBody(), q));
         return null;
     }
 
     @Override
     public Expression visit(FunctionDecl fd, ILangExpression arg) throws AsterixException {
-        fd.setFuncBody(fd.getFuncBody().accept(this, fd));
+        fd.setFuncBody(visit(fd.getFuncBody(), fd));
         return null;
     }
 
     @Override
     public Expression visit(WhereClause whereClause, ILangExpression arg) throws AsterixException {
-        whereClause.setWhereExpr(whereClause.getWhereExpr().accept(this, whereClause));
+        whereClause.setWhereExpr(visit(whereClause.getWhereExpr(), whereClause));
         return null;
     }
 
     @Override
     public Expression visit(OrderbyClause oc, ILangExpression arg) throws AsterixException {
-        List<Expression> newOrderbyList = new ArrayList<>();
-        for (Expression orderExpr : oc.getOrderbyList()) {
-            newOrderbyList.add(orderExpr.accept(this, oc));
-        }
-        oc.setOrderbyList(newOrderbyList);
+        oc.setOrderbyList(visit(oc.getOrderbyList(), arg));
         return null;
     }
 
     @Override
     public Expression visit(GroupbyClause gc, ILangExpression arg) throws AsterixException {
         for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
-            gbyVarExpr.setExpr(gbyVarExpr.getExpr().accept(this, gc));
+            gbyVarExpr.setExpr(visit(gbyVarExpr.getExpr(), gc));
         }
         return null;
     }
 
     @Override
     public Expression visit(LimitClause limitClause, ILangExpression arg) throws AsterixException {
-        limitClause.setLimitExpr(limitClause.getLimitExpr().accept(this, limitClause));
+        limitClause.setLimitExpr(visit(limitClause.getLimitExpr(), limitClause));
         if (limitClause.hasOffset()) {
-            limitClause.setOffset(limitClause.getOffset().accept(this, limitClause));
+            limitClause.setOffset(visit(limitClause.getOffset(), limitClause));
         }
         return null;
     }
 
     @Override
     public Expression visit(LetClause letClause, ILangExpression arg) throws AsterixException {
-        letClause.setBindingExpr(letClause.getBindingExpr().accept(this, letClause));
+        letClause.setBindingExpr(visit(letClause.getBindingExpr(), letClause));
         return null;
     }
 
@@ -275,8 +272,8 @@
     @Override
     public Expression visit(RecordConstructor rc, ILangExpression arg) throws AsterixException {
         for (FieldBinding binding : rc.getFbList()) {
-            binding.setLeftExpr(binding.getLeftExpr().accept(this, rc));
-            binding.setRightExpr(binding.getRightExpr().accept(this, rc));
+            binding.setLeftExpr(visit(binding.getLeftExpr(), rc));
+            binding.setRightExpr(visit(binding.getRightExpr(), rc));
         }
         return rc;
     }
@@ -289,28 +286,24 @@
 
     @Override
     public Expression visit(IfExpr ifExpr, ILangExpression arg) throws AsterixException {
-        ifExpr.setCondExpr(ifExpr.getCondExpr().accept(this, ifExpr));
-        ifExpr.setThenExpr(ifExpr.getThenExpr().accept(this, ifExpr));
-        ifExpr.setElseExpr(ifExpr.getElseExpr().accept(this, ifExpr));
+        ifExpr.setCondExpr(visit(ifExpr.getCondExpr(), ifExpr));
+        ifExpr.setThenExpr(visit(ifExpr.getThenExpr(), ifExpr));
+        ifExpr.setElseExpr(visit(ifExpr.getElseExpr(), ifExpr));
         return ifExpr;
     }
 
     @Override
     public Expression visit(QuantifiedExpression qe, ILangExpression arg) throws AsterixException {
         for (QuantifiedPair pair : qe.getQuantifiedList()) {
-            pair.setExpr(pair.getExpr().accept(this, qe));
+            pair.setExpr(visit(pair.getExpr(), qe));
         }
-        qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, qe));
+        qe.setSatisfiesExpr(visit(qe.getSatisfiesExpr(), qe));
         return qe;
     }
 
     @Override
     public Expression visit(CallExpr callExpr, ILangExpression arg) throws AsterixException {
-        List<Expression> newExprList = new ArrayList<>();
-        for (Expression expr : callExpr.getExprList()) {
-            newExprList.add(expr.accept(this, callExpr));
-        }
-        callExpr.setExprList(newExprList);
+        callExpr.setExprList(visit(callExpr.getExprList(), arg));
         return callExpr;
     }
 
@@ -321,46 +314,57 @@
 
     @Override
     public Expression visit(UnaryExpr u, ILangExpression arg) throws AsterixException {
-        u.setExpr(u.getExpr().accept(this, u));
+        u.setExpr(visit(u.getExpr(), u));
         return u;
     }
 
     @Override
     public Expression visit(FieldAccessor fa, ILangExpression arg) throws AsterixException {
-        fa.setExpr(fa.getExpr().accept(this, fa));
+        fa.setExpr(visit(fa.getExpr(), fa));
         return fa;
     }
 
     @Override
     public Expression visit(IndexAccessor ia, ILangExpression arg) throws AsterixException {
-        ia.setExpr(ia.getExpr().accept(this, ia));
+        ia.setExpr(visit(ia.getExpr(), ia));
         if (ia.getIndexExpr() != null) {
-            ia.setIndexExpr(ia.getIndexExpr());
+            ia.setIndexExpr(visit(ia.getIndexExpr(), arg));
         }
         return ia;
     }
 
     @Override
     public Expression visit(IndependentSubquery independentSubquery, ILangExpression arg) throws AsterixException {
-        independentSubquery.setExpr(independentSubquery.getExpr().accept(this, arg));
+        independentSubquery.setExpr(visit(independentSubquery.getExpr(), arg));
         return independentSubquery;
     }
 
     @Override
     public Expression visit(CaseExpression caseExpr, ILangExpression arg) throws AsterixException {
-        caseExpr.setConditionExpr(caseExpr.getConditionExpr().accept(this, arg));
+        caseExpr.setConditionExpr(visit(caseExpr.getConditionExpr(), arg));
         caseExpr.setWhenExprs(visit(caseExpr.getWhenExprs(), arg));
         caseExpr.setThenExprs(visit(caseExpr.getThenExprs(), arg));
-        caseExpr.setElseExpr(caseExpr.getElseExpr().accept(this, arg));
+        caseExpr.setElseExpr(visit(caseExpr.getElseExpr(), arg));
         return caseExpr;
     }
 
+    protected Expression visit(Expression expr, ILangExpression arg) throws AsterixException{
+        return postVisit(preVisit(expr).accept(this, arg));
+    }
+
+    protected Expression preVisit(Expression expr) throws AsterixException{
+        return expr;
+    }
+
+    protected Expression postVisit(Expression expr) throws AsterixException {
+        return expr;
+    }
+
     private List<Expression> visit(List<Expression> exprs, ILangExpression arg) throws AsterixException {
         List<Expression> newExprList = new ArrayList<>();
         for (Expression expr : exprs) {
-            newExprList.add(expr.accept(this, arg));
+            newExprList.add(visit(expr, arg));
         }
         return newExprList;
     }
-
 }
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index a0a9742..95f09f5 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -2649,7 +2649,6 @@
     GroupbyClause gbc = new GroupbyClause();
     List<GbyVariableExpressionPair> vePairList = new ArrayList<GbyVariableExpressionPair>();
     VariableExpr var = null;
-    VariableExpr withVar = null;
     Expression expr = null;
     VariableExpr decorVar = null;
     Expression decorExpr = null;
@@ -2721,7 +2720,7 @@
     {
       gbc.setGbyPairList(vePairList);
       gbc.setDecorPairList(new ArrayList<GbyVariableExpressionPair>());
-      gbc.setWithVarList(new ArrayList<VariableExpr>());
+      gbc.setWithVarMap(new HashMap<Expression, VariableExpr>());
       gbc.setGroupVar(groupVar);
       gbc.setGroupFieldList(groupFieldList);
       replaceCurrentScope(newScope);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
index e303d97..97f0ace 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/AsterixBuiltinFunctions.java
@@ -83,6 +83,7 @@
 import org.apache.asterix.om.typecomputer.impl.OrderedListOfAPointTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.OrderedListOfAStringTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.OrderedListOfAnyTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.PropagateTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.RecordAddFieldsTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.RecordMergeTypeComputer;
 import org.apache.asterix.om.typecomputer.impl.RecordRemoveFieldsTypeComputer;
@@ -301,6 +302,10 @@
             "agg-intermediate-avg", 1);
     public static final FunctionIdentifier LOCAL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "agg-local-avg", 1);
+    public static final FunctionIdentifier FIRST_ELEMENT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-first-element", 1);
+    public static final FunctionIdentifier LOCAL_FIRST_ELEMENT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-local-first-element", 1);
 
     public static final FunctionIdentifier SCALAR_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "avg", 1);
     public static final FunctionIdentifier SCALAR_COUNT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "count",
@@ -312,6 +317,8 @@
             "global-avg", 1);
     public static final FunctionIdentifier SCALAR_LOCAL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "local-avg", 1);
+    public static final FunctionIdentifier SCALAR_FIRST_ELEMENT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "first-element", 1);
 
     // serializable aggregate functions
     public static final FunctionIdentifier SERIAL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
@@ -864,6 +871,9 @@
         addFunction(SUM, NumericAggTypeComputer.INSTANCE, true);
         addPrivateFunction(LOCAL_SUM, NumericAggTypeComputer.INSTANCE, true);
         addPrivateFunction(GLOBAL_AVG, NullableDoubleTypeComputer.INSTANCE, true);
+        addPrivateFunction(SCALAR_FIRST_ELEMENT, CollectionMemberResultType.INSTANCE, true);
+        addPrivateFunction(FIRST_ELEMENT, PropagateTypeComputer.INSTANCE, true);
+        addPrivateFunction(LOCAL_FIRST_ELEMENT, PropagateTypeComputer.INSTANCE, true);
 
         addPrivateFunction(SERIAL_SQL_AVG, NullableDoubleTypeComputer.INSTANCE, true);
         addPrivateFunction(SERIAL_SQL_COUNT, AInt64TypeComputer.INSTANCE, true);
@@ -1067,6 +1077,8 @@
         scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_MAX), getAsterixFunctionInfo(MAX));
         scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_MIN), getAsterixFunctionInfo(MIN));
         scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_SUM), getAsterixFunctionInfo(SUM));
+        scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_FIRST_ELEMENT),
+                getAsterixFunctionInfo(FIRST_ELEMENT));
         // SQL Aggregate Functions
         scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_SQL_AVG), getAsterixFunctionInfo(SQL_AVG));
         scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_SQL_COUNT), getAsterixFunctionInfo(SQL_COUNT));
@@ -1101,6 +1113,13 @@
         addIntermediateAgg(MAX, MAX);
         addGlobalAgg(MAX, MAX);
 
+        addAgg(SCALAR_FIRST_ELEMENT);
+        addAgg(LOCAL_FIRST_ELEMENT);
+        addLocalAgg(FIRST_ELEMENT, LOCAL_FIRST_ELEMENT);
+        addIntermediateAgg(LOCAL_FIRST_ELEMENT, FIRST_ELEMENT);
+        addIntermediateAgg(FIRST_ELEMENT, FIRST_ELEMENT);
+        addGlobalAgg(FIRST_ELEMENT, FIRST_ELEMENT);
+
         addAgg(MIN);
         addLocalAgg(MIN, LOCAL_MIN);
         addIntermediateAgg(LOCAL_MIN, MIN);
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FieldAccessByNameResultType.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FieldAccessByNameResultType.java
index 4332bb1..2931d7e 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FieldAccessByNameResultType.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/FieldAccessByNameResultType.java
@@ -42,10 +42,12 @@
     @Override
     protected void checkArgType(int argIndex, IAType type) throws AlgebricksException {
         if (argIndex == 0 && type.getTypeTag() != ATypeTag.RECORD) {
-            throw new AlgebricksException("The first argument should be a RECORD, but it is " + type + ".");
+            throw new AlgebricksException("The first argument of a field access should be a RECORD, but it is " + type
+                    + ".");
         }
         if (argIndex == 1 && type.getTypeTag() != ATypeTag.STRING) {
-            throw new AlgebricksException("The second argument should be an STRING, but it is found " + type + ".");
+            throw new AlgebricksException("The second argument of a field access should be an STRING, but it is "
+                    + type + ".");
         }
     }
 
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/PropagateTypeComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/PropagateTypeComputer.java
new file mode 100644
index 0000000..df4524f
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/PropagateTypeComputer.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.om.typecomputer.impl;
+
+import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+
+/**
+ * This type computer just populates whatever input type as the output type.
+ */
+public class PropagateTypeComputer extends AbstractResultTypeComputer {
+
+    public static final PropagateTypeComputer INSTANCE = new PropagateTypeComputer();
+
+    @Override
+    public IAType getResultType(ILogicalExpression expr, IAType... knownTypes) throws AlgebricksException {
+        return knownTypes[0];
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeHelper.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeHelper.java
index 4839c41..588b7d0 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeHelper.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeHelper.java
@@ -50,10 +50,7 @@
             case ANY:
                 return false;
             case UNION:
-                if (!isClosed(((AUnionType) t).getActualType())) {
-                    return false;
-                }
-                return true;
+                return isClosed(((AUnionType) t).getActualType());
             default:
                 return true;
         }
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/collections/FirstElementAggregateDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/collections/FirstElementAggregateDescriptor.java
new file mode 100644
index 0000000..2a94418
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/collections/FirstElementAggregateDescriptor.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.runtime.aggregates.collections;
+
+import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IAggregateEvaluatorFactory;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+
+// This aggregate function simply returns the first item in an input stream.
+public class FirstElementAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = () -> new FirstElementAggregateDescriptor();
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.FIRST_ELEMENT;
+    }
+
+    @Override
+    public IAggregateEvaluatorFactory createAggregateEvaluatorFactory(final IScalarEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new FirstElementEvalFactory(args, false);
+    }
+
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/collections/FirstElementEvalFactory.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/collections/FirstElementEvalFactory.java
new file mode 100644
index 0000000..fe3a7ec
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/collections/FirstElementEvalFactory.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.runtime.aggregates.collections;
+
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.runtime.base.IAggregateEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IAggregateEvaluatorFactory;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.context.IHyracksTaskContext;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
+import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+class FirstElementEvalFactory implements IAggregateEvaluatorFactory {
+
+    private static final long serialVersionUID = 1L;
+    private final IScalarEvaluatorFactory[] args;
+    private final boolean isLocal;
+
+    FirstElementEvalFactory(IScalarEvaluatorFactory[] args, boolean isLocal) {
+        this.args = args;
+        this.isLocal = isLocal;
+    }
+
+    @Override
+    public IAggregateEvaluator createAggregateEvaluator(final IHyracksTaskContext ctx) throws AlgebricksException {
+
+        return new IAggregateEvaluator() {
+
+            private boolean first = true;
+            // Needs to copy the bytes from inputVal to outputVal because the byte space of inputVal could be re-used
+            // by consequent tuples.
+            private ArrayBackedValueStorage outputVal = new ArrayBackedValueStorage();
+            private IPointable inputVal = new VoidPointable();
+            private IScalarEvaluator eval = args[0].createScalarEvaluator(ctx);
+            private final byte[] nullBytes = new byte[] { ATypeTag.SERIALIZED_NULL_TYPE_TAG };
+            private final byte[] systemNullBytes = new byte[] { ATypeTag.SERIALIZED_SYSTEM_NULL_TYPE_TAG };
+
+            @Override
+            public void init() throws AlgebricksException {
+                first = true;
+            }
+
+            @Override
+            public void step(IFrameTupleReference tuple) throws AlgebricksException {
+                if (!first) {
+                    return;
+                }
+                eval.evaluate(tuple, inputVal);
+                byte typeTagByte = inputVal.getByteArray()[inputVal.getStartOffset()];
+                if(typeTagByte == ATypeTag.SERIALIZED_SYSTEM_NULL_TYPE_TAG){
+                    // Ignores SYSTEM_NULLs generated by local-first-element.
+                    return;
+                }
+                outputVal.assign(inputVal);
+                first = false;
+            }
+
+            @Override
+            public void finish(IPointable result) throws AlgebricksException {
+                if (first) {
+                    result.set(isLocal ? systemNullBytes : nullBytes, 0, 1);
+                    return;
+                }
+                result.set(outputVal);
+            }
+
+            @Override
+            public void finishPartial(IPointable result) throws AlgebricksException {
+                finish(result);
+            }
+
+        };
+    }
+
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/collections/LocalFirstElementAggregateDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/collections/LocalFirstElementAggregateDescriptor.java
new file mode 100644
index 0000000..c1465d5
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/aggregates/collections/LocalFirstElementAggregateDescriptor.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.runtime.aggregates.collections;
+
+import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
+import org.apache.asterix.om.functions.IFunctionDescriptorFactory;
+import org.apache.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IAggregateEvaluatorFactory;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+
+public class LocalFirstElementAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = () -> new LocalFirstElementAggregateDescriptor();
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.LOCAL_FIRST_ELEMENT;
+    }
+
+    @Override
+    public IAggregateEvaluatorFactory createAggregateEvaluatorFactory(final IScalarEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new FirstElementEvalFactory(args, true);
+    }
+
+}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/properties/LocalGroupingProperty.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/properties/LocalGroupingProperty.java
index 6f4c296..159ed04 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/properties/LocalGroupingProperty.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/properties/LocalGroupingProperty.java
@@ -100,8 +100,8 @@
             }
         }
         if (!newColumns.isEmpty()) {
-            return new LocalGroupingProperty(newColumns,
-                    preferredOrderEnforcer.subList(groupKeys.size(), newColumns.size()));
+            return new LocalGroupingProperty(newColumns, preferredOrderEnforcer == null ? null
+                    : preferredOrderEnforcer.subList(groupKeys.size(), newColumns.size()));
         } else {
             return null;
         }
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/EliminateGroupByEmptyKeyRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/EliminateGroupByEmptyKeyRule.java
index aab6ce1..8a91cfc 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/EliminateGroupByEmptyKeyRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/EliminateGroupByEmptyKeyRule.java
@@ -21,8 +21,9 @@
 import java.util.List;
 
 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;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
 import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
@@ -41,7 +42,8 @@
 public class EliminateGroupByEmptyKeyRule implements IAlgebraicRewriteRule {
 
     @Override
-    public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
+    public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
+            throws AlgebricksException {
         return false;
     }
 
@@ -54,7 +56,8 @@
         }
         GroupByOperator groupOp = (GroupByOperator) op;
         List<LogicalVariable> groupVars = groupOp.getGbyVarList();
-        if (groupVars.size() > 0) {
+        List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> decorList = groupOp.getDecorList();
+        if (!groupVars.isEmpty() || !decorList.isEmpty()) {
             return false;
         }
         List<ILogicalPlan> nestedPlans = groupOp.getNestedPlans();
@@ -81,7 +84,7 @@
 
     private Mutable<ILogicalOperator> getNestedTupleSourceReference(Mutable<ILogicalOperator> nestedTopOperatorRef) {
         Mutable<ILogicalOperator> currentOpRef = nestedTopOperatorRef;
-        while (currentOpRef.getValue().getInputs() != null && currentOpRef.getValue().getInputs().size() > 0) {
+        while (currentOpRef.getValue().getInputs() != null && !currentOpRef.getValue().getInputs().isEmpty()) {
             currentOpRef = currentOpRef.getValue().getInputs().get(0);
         }
         return currentOpRef;
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractGroupByDecorVariablesRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractGroupByDecorVariablesRule.java
new file mode 100644
index 0000000..a2ad732
--- /dev/null
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractGroupByDecorVariablesRule.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.algebricks.rewriter.rules;
+
+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.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+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.base.LogicalExpressionTag;
+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.VariableReferenceExpression;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator;
+import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+
+/**
+ * This rule normalizes an GroupBy operator. It extracts non-variable-reference decoration expressions
+ * as a separate assign operator before the GroupBy operator.
+ * The reason that we have this rule is that in various rules as well as the code generation for the
+ * GroupBy operator we assumed that decoration expressions can only be variable reference expressions.
+ */
+public class ExtractGroupByDecorVariablesRule implements IAlgebraicRewriteRule {
+
+    @Override
+    public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
+            throws AlgebricksException {
+        ILogicalOperator op = opRef.getValue();
+        if (op.getOperatorTag() != LogicalOperatorTag.GROUP) {
+            return false;
+        }
+        GroupByOperator groupByOperator = (GroupByOperator) op;
+        List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> decorList = groupByOperator.getDecorList();
+
+        // Returns immediately if there is no decoration entry.
+        if (groupByOperator.getDecorList() == null || groupByOperator.getDecorList().isEmpty()) {
+            return false;
+        }
+
+        // Goes over the decoration list and performs the rewrite.
+        boolean changed = false;
+        List<LogicalVariable> vars = new ArrayList<>();
+        List<Mutable<ILogicalExpression>> exprs = new ArrayList<>();
+        for (Pair<LogicalVariable, Mutable<ILogicalExpression>> decorVarExpr : decorList) {
+            Mutable<ILogicalExpression> exprRef = decorVarExpr.second;
+            ILogicalExpression expr = exprRef.getValue();
+            if (expr ==null || expr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
+                continue;
+            }
+            // Rewrites the decoration entry if the decoration expression is not a variable reference expression.
+            changed = true;
+            LogicalVariable newVar = context.newVar();
+            vars.add(newVar);
+            exprs.add(exprRef);
+
+            // Normalizes the decor entry -- expression be a variable reference
+            decorVarExpr.second = new MutableObject<>(new VariableReferenceExpression(newVar));
+        }
+        if (!changed) {
+            return false;
+        }
+
+        // Injects an assign operator to evaluate the decoration expression.
+        AssignOperator assignOperator = new AssignOperator(vars, exprs);
+        assignOperator.getInputs().addAll(op.getInputs());
+        op.getInputs().set(0, new MutableObject<>(assignOperator));
+        return changed;
+    }
+}
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/RemoveCartesianProductWithEmptyBranchRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/RemoveCartesianProductWithEmptyBranchRule.java
index de35fb5..bd5d646 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/RemoveCartesianProductWithEmptyBranchRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/RemoveCartesianProductWithEmptyBranchRule.java
@@ -18,13 +18,18 @@
  */
 package org.apache.hyracks.algebricks.rewriter.rules;
 
+import java.util.HashSet;
+import java.util.Set;
+
 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.base.LogicalOperatorTag;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
 import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
 import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 
 /**
@@ -58,7 +63,12 @@
         return false;
     }
 
-    private boolean emptyBranch(ILogicalOperator op) {
-        return op.getOperatorTag() == LogicalOperatorTag.EMPTYTUPLESOURCE;
+    private boolean emptyBranch(ILogicalOperator op) throws AlgebricksException {
+        if (op.getOperatorTag() == LogicalOperatorTag.EMPTYTUPLESOURCE) {
+            return true;
+        }
+        Set<LogicalVariable> liveVariables = new HashSet<>();
+        VariableUtilities.getLiveVariables(op, liveVariables);
+        return liveVariables.isEmpty();
     }
 }
diff --git a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/RemoveUnusedAssignAndAggregateRule.java b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/RemoveUnusedAssignAndAggregateRule.java
index b25497c..139f1ed 100644
--- a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/RemoveUnusedAssignAndAggregateRule.java
+++ b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/RemoveUnusedAssignAndAggregateRule.java
@@ -26,9 +26,9 @@
 import java.util.Set;
 
 import org.apache.commons.lang3.mutable.Mutable;
-
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.common.utils.ListSet;
+import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.algebricks.common.utils.Triple;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
@@ -40,6 +40,7 @@
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractOperatorWithNestedPlans;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
@@ -119,35 +120,40 @@
     private int removeFromAssigns(AbstractLogicalOperator op, Set<LogicalVariable> toRemove,
             IOptimizationContext context) throws AlgebricksException {
         switch (op.getOperatorTag()) {
-            case ASSIGN: {
+            case ASSIGN:
                 AssignOperator assign = (AssignOperator) op;
                 if (removeUnusedVarsAndExprs(toRemove, assign.getVariables(), assign.getExpressions())) {
                     context.computeAndSetTypeEnvironmentForOperator(assign);
                 }
                 return assign.getVariables().size();
-            }
-            case AGGREGATE: {
+            case AGGREGATE:
                 AggregateOperator agg = (AggregateOperator) op;
                 if (removeUnusedVarsAndExprs(toRemove, agg.getVariables(), agg.getExpressions())) {
                     context.computeAndSetTypeEnvironmentForOperator(agg);
                 }
                 return agg.getVariables().size();
-            }
-            case UNNEST: {
+            case UNNEST:
                 UnnestOperator uOp = (UnnestOperator) op;
                 LogicalVariable pVar = uOp.getPositionalVariable();
                 if (pVar != null && toRemove.contains(pVar)) {
                     uOp.setPositionalVariable(null);
                 }
                 break;
-            }
-            case UNIONALL: {
+            case UNIONALL:
                 UnionAllOperator unionOp = (UnionAllOperator) op;
                 if (removeUnusedVarsFromUnionAll(unionOp, toRemove)) {
                     context.computeAndSetTypeEnvironmentForOperator(unionOp);
                 }
                 return unionOp.getVariableMappings().size();
-            }
+            case GROUP:
+                GroupByOperator groupByOp = (GroupByOperator) op;
+                if (removeUnusedVarsFromGroupBy(groupByOp, toRemove)) {
+                    context.computeAndSetTypeEnvironmentForOperator(groupByOp);
+                }
+                return groupByOp.getGroupByList().size() + groupByOp.getNestedPlans().size()
+                        + groupByOp.getDecorList().size();
+            default:
+                break;
         }
         return -1;
     }
@@ -171,6 +177,20 @@
         return modified;
     }
 
+    private boolean removeUnusedVarsFromGroupBy(GroupByOperator groupByOp, Set<LogicalVariable> toRemove) {
+        Iterator<Pair<LogicalVariable, Mutable<ILogicalExpression>>> iter = groupByOp.getDecorList().iterator();
+        boolean modified = false;
+        while (iter.hasNext()) {
+            Pair<LogicalVariable, Mutable<ILogicalExpression>> varMapping = iter.next();
+            LogicalVariable decorVar = varMapping.first;
+            if (decorVar != null && toRemove.contains(decorVar)) {
+                iter.remove();
+                modified = true;
+            }
+        }
+        return modified;
+    }
+
     private boolean removeUnusedVarsAndExprs(Set<LogicalVariable> toRemove, List<LogicalVariable> varList,
             List<Mutable<ILogicalExpression>> exprList) {
         boolean changed = false;
@@ -206,25 +226,22 @@
         }
         boolean removeUsedVars = true;
         switch (op.getOperatorTag()) {
-            case ASSIGN: {
+            case ASSIGN:
                 AssignOperator assign = (AssignOperator) op;
                 toRemove.addAll(assign.getVariables());
                 break;
-            }
-            case AGGREGATE: {
+            case AGGREGATE:
                 AggregateOperator agg = (AggregateOperator) op;
                 toRemove.addAll(agg.getVariables());
                 break;
-            }
-            case UNNEST: {
+            case UNNEST:
                 UnnestOperator uOp = (UnnestOperator) op;
                 LogicalVariable pVar = uOp.getPositionalVariable();
                 if (pVar != null) {
                     toRemove.add(pVar);
                 }
                 break;
-            }
-            case UNIONALL: {
+            case UNIONALL:
                 UnionAllOperator unionOp = (UnionAllOperator) op;
                 for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> varMapping : unionOp
                         .getVariableMappings()) {
@@ -232,7 +249,17 @@
                 }
                 removeUsedVars = false;
                 break;
-            }
+            case GROUP:
+                GroupByOperator groupByOp = (GroupByOperator) op;
+                for (Pair<LogicalVariable, Mutable<ILogicalExpression>> decorMapping : groupByOp.getDecorList()) {
+                    LogicalVariable decorVar = decorMapping.first;
+                    if (decorVar != null) {
+                        toRemove.add(decorVar);
+                    }
+                }
+                break;
+            default:
+                break;
         }
         if (removeUsedVars) {
             List<LogicalVariable> used = new LinkedList<LogicalVariable>();