asterixdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From buyin...@apache.org
Subject [03/11] asterixdb git commit: Support implicit variable name and column name.
Date Fri, 01 Jul 2016 19:41:11 GMT
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupBySugarVisitor.java
----------------------------------------------------------------------
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 6c88a6a..47aa02b 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
@@ -31,6 +31,7 @@ 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;
 import org.apache.asterix.lang.common.expression.VariableExpr;
@@ -83,17 +84,20 @@ public class SqlppGroupBySugarVisitor extends AbstractSqlppExpressionScopingVisi
 
     private final Expression groupVar;
     private final Collection<VariableExpr> targetVars;
+    private final Collection<VariableExpr> allVisableVars;
 
     public SqlppGroupBySugarVisitor(LangRewritingContext context, Expression groupVar,
-            Collection<VariableExpr> targetVars) {
+            Collection<VariableExpr> targetVars, Collection<VariableExpr> allVisableVars) {
         super(context);
         this.groupVar = groupVar;
         this.targetVars = targetVars;
+        this.allVisableVars = allVisableVars;
+        allVisableVars.remove(groupVar);
     }
 
     @Override
-    public Expression visit(CallExpr callExpr, Expression arg) throws AsterixException {
-        List<Expression> newExprList = new ArrayList<Expression>();
+    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);
@@ -112,15 +116,21 @@ public class SqlppGroupBySugarVisitor extends AbstractSqlppExpressionScopingVisi
         return callExpr;
     }
 
-    private Expression wrapAggregationArgument(Expression expr) throws AsterixException {
+    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.
-        Set<VariableExpr> freeVars = SqlppRewriteUtil.getFreeVariable(expr);
-        if (!vars.containsAll(freeVars)) {
+        if (!needResolve && !vars.containsAll(freeVars)) {
             return expr;
         }
 
@@ -140,8 +150,19 @@ public class SqlppGroupBySugarVisitor extends AbstractSqlppExpressionScopingVisi
         // replace variable expressions with field access
         Map<VariableExpr, Expression> varExprMap = new HashMap<>();
         for (VariableExpr usedVar : freeVars) {
-            varExprMap.put(usedVar,
-                    new FieldAccessor(var, SqlppVariableUtil.toUserDefinedVariableName(usedVar.getVar())));
+            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));

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
----------------------------------------------------------------------
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 16e967c..36463cb 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
@@ -26,6 +26,7 @@ import java.util.Set;
 
 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.clause.GroupbyClause;
 import org.apache.asterix.lang.common.clause.LetClause;
 import org.apache.asterix.lang.common.context.Scope;
@@ -84,7 +85,7 @@ public class SqlppGroupByVisitor extends AbstractSqlppExpressionScopingVisitor {
     }
 
     @Override
-    public Expression visit(SelectBlock selectBlock, Expression arg) throws AsterixException {
+    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".
         if (selectBlock.hasFromClause()) {
@@ -103,43 +104,53 @@ public class SqlppGroupByVisitor extends AbstractSqlppExpressionScopingVisitor {
             selectBlock.getGroupbyClause().accept(this, arg);
             Set<VariableExpr> withVarSet = new HashSet<>(selectBlock.getGroupbyClause().getWithVarList());
             withVarSet.remove(selectBlock.getGroupbyClause().getGroupVar());
+
+            Set<VariableExpr> allVisableVars = SqlppVariableUtil
+                    .getLiveUserDefinedVariables(scopeChecker.getCurrentScope());
             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, letClauseAfterGby, context);
-                    letClauseAfterGby.accept(this, arg);
+                            withVarSet, allVisableVars, letClauseAfterGby, context);
+                    // Adds let vars to all visiable vars.
+                    allVisableVars.add(letClauseAfterGby.getVarExpr());
                 }
             }
+
             if (selectBlock.hasHavingClause()) {
+                selectBlock.getHavingClause().accept(this, arg);
                 // Rewrites the having clause.
                 SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
-                        withVarSet, selectBlock.getHavingClause(), context);
-                selectBlock.getHavingClause().accept(this, arg);
+                        withVarSet, allVisableVars, selectBlock.getHavingClause(), context);
             }
-            // Rewrites the select clause.
-            SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
-                    withVarSet, selectBlock.getSelectClause(), context);
 
             SelectExpression parentSelectExpression = (SelectExpression) arg;
             if (parentSelectExpression.hasOrderby()) {
                 // Rewrites the order-by clause.
                 SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
-                        withVarSet, parentSelectExpression.getOrderbyClause(), context);
+                        withVarSet, allVisableVars, parentSelectExpression.getOrderbyClause(), context);
             }
             if (parentSelectExpression.hasLimit()) {
                 // Rewrites the limit clause.
                 SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
-                        withVarSet, parentSelectExpression.getLimitClause(), context);
+                        withVarSet, allVisableVars, parentSelectExpression.getLimitClause(), context);
             }
+
+            // Visits the select clause.
+            selectBlock.getSelectClause().accept(this, arg);
+            // Rewrites the select clause.
+            SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(selectBlock.getGroupbyClause().getGroupVar(),
+                    withVarSet, allVisableVars, selectBlock.getSelectClause(), context);
+        } else {
+            selectBlock.getSelectClause().accept(this, arg);
         }
-        selectBlock.getSelectClause().accept(this, arg);
         return null;
     }
 
     @Override
-    public Expression visit(GroupbyClause gc, Expression arg) throws AsterixException {
+    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()) {
@@ -150,7 +161,7 @@ public class SqlppGroupByVisitor extends AbstractSqlppExpressionScopingVisitor {
             }
         }
         // Puts all live variables into withVarList.
-        List<VariableExpr> withVarList = new ArrayList<VariableExpr>();
+        List<VariableExpr> withVarList = new ArrayList<>();
         Iterator<Identifier> varIterator = scopeChecker.getCurrentScope().liveSymbols();
         while (varIterator.hasNext()) {
             Identifier ident = varIterator.next();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppInlineUdfsVisitor.java
----------------------------------------------------------------------
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 e7832bb..194c029 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
@@ -43,6 +43,7 @@ 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.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;
@@ -223,6 +224,13 @@ public class SqlppInlineUdfsVisitor extends AbstractInlineUdfsVisitor
         return p.first;
     }
 
+    @Override
+    public Boolean visit(IndependentSubquery independentSubquery, List<FunctionDecl> funcs) throws AsterixException {
+        Pair<Boolean, Expression> p = inlineUdfsInExpr(independentSubquery.getExpr(), funcs);
+        independentSubquery.setExpr(p.second);
+        return p.first;
+    }
+
     private Map<VariableExpr, Expression> extractLetBindingVariableExpressionMappings(List<LetClause> letClauses)
             throws AsterixException {
         Map<VariableExpr, Expression> varExprMap = new HashMap<VariableExpr, Expression>();
@@ -234,4 +242,5 @@ public class SqlppInlineUdfsVisitor extends AbstractInlineUdfsVisitor
         }
         return varExprMap;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
----------------------------------------------------------------------
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 5ca2533..7082c25 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
@@ -20,11 +20,13 @@ package org.apache.asterix.lang.sqlpp.rewrites.visitor;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.asterix.common.config.MetadataConstants;
 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.ILangExpression;
 import org.apache.asterix.lang.common.expression.CallExpr;
 import org.apache.asterix.lang.common.expression.LiteralExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
@@ -35,9 +37,12 @@ import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
 import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;
 import org.apache.asterix.metadata.declared.AqlMetadataProvider;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 
 public class VariableCheckAndRewriteVisitor extends AbstractSqlppExpressionScopingVisitor {
 
+    protected final FunctionSignature datasetFunction = new FunctionSignature(MetadataConstants.METADATA_DATAVERSE_NAME,
+            "dataset", 1);
     protected final boolean overwrite;
     protected final AqlMetadataProvider metadataProvider;
 
@@ -57,17 +62,28 @@ public class VariableCheckAndRewriteVisitor extends AbstractSqlppExpressionScopi
     }
 
     @Override
-    public Expression visit(VariableExpr varExpr, Expression arg) throws AsterixException {
+    public Expression visit(VariableExpr varExpr, ILangExpression arg) throws AsterixException {
         String varName = varExpr.getVar().getValue();
         if (scopeChecker.isInForbiddenScopes(varName)) {
             throw new AsterixException(
-                    "Inside limit clauses, it is disallowed to reference a variable having the same name as any variable bound in the same scope as the limit clause.");
+                    "Inside limit clauses, it is disallowed to reference a variable having the same name"
+                            + " as any variable bound in the same scope as the limit clause.");
         }
-        if (rewriteNeeded(varExpr)) {
-            return datasetRewrite(varExpr);
-        } else {
+        if (!rewriteNeeded(varExpr)) {
             return varExpr;
         }
+        boolean resolveAsDataset = resolveDatasetFirst(arg)
+                && datasetExists(SqlppVariableUtil.toUserDefinedVariableName(varName).getValue());
+        if (resolveAsDataset) {
+            return wrapWithDatasetFunction(varExpr);
+        }
+        Set<VariableExpr> liveVars = SqlppVariableUtil.getLiveUserDefinedVariables(scopeChecker.getCurrentScope());
+        return wrapWithResolveFunction(varExpr, liveVars);
+    }
+
+    // For From/Join/UNNEST/NEST, we resolve the undefined identifier reference as dataset reference first.
+    private boolean resolveDatasetFirst(ILangExpression arg) {
+        return arg != null;
     }
 
     // Whether a rewrite is needed for a variable reference expression.
@@ -81,22 +97,41 @@ public class VariableCheckAndRewriteVisitor extends AbstractSqlppExpressionScopi
             return false;
         } else {
             // Meets a undefined variable
-            return true;
+            return overwrite;
         }
     }
 
-    // Rewrites for global variable (e.g., dataset) references.
-    private Expression datasetRewrite(VariableExpr expr) throws AsterixException {
-        if (!overwrite) {
-            return expr;
-        }
-        String funcName = "dataset";
-        String dataverse = MetadataConstants.METADATA_DATAVERSE_NAME;
-        FunctionSignature signature = new FunctionSignature(dataverse, funcName, 1);
-        List<Expression> argList = new ArrayList<Expression>();
+    private Expression wrapWithDatasetFunction(VariableExpr expr) throws AsterixException {
+        List<Expression> argList = new ArrayList<>();
         //Ignore the parser-generated prefix "$" for a dataset.
-        String dataset = SqlppVariableUtil.toUserDefinedVariableName(expr.getVar()).getValue();
-        argList.add(new LiteralExpr(new StringLiteral(dataset)));
-        return new CallExpr(signature, argList);
+        String varName = SqlppVariableUtil.toUserDefinedVariableName(expr.getVar()).getValue();
+        argList.add(new LiteralExpr(new StringLiteral(varName)));
+        return new CallExpr(datasetFunction, argList);
+    }
+
+    private boolean datasetExists(String name) throws AsterixException {
+        try {
+            if (metadataProvider.findDataset(null, name) != null) {
+                return true;
+            }
+            return pathDatasetExists(name);
+        } catch (AlgebricksException e) {
+            throw new AsterixException(e);
+        }
     }
+
+    private boolean pathDatasetExists(String name) throws AlgebricksException {
+        if (!name.contains(".")) {
+            return false;
+        }
+        String[] path = name.split("\\.");
+        if (path.length != 2) {
+            return false;
+        }
+        if (metadataProvider.findDataset(path[0], path[1]) != null) {
+            return true;
+        }
+        return false;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/ExpressionToVariableUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/ExpressionToVariableUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/ExpressionToVariableUtil.java
new file mode 100644
index 0000000..8817d76
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/ExpressionToVariableUtil.java
@@ -0,0 +1,53 @@
+/*
+ * 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 org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.Expression.Kind;
+import org.apache.asterix.lang.common.expression.FieldAccessor;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.asterix.lang.sqlpp.parser.ParseException;
+
+public class ExpressionToVariableUtil {
+
+    private ExpressionToVariableUtil() {
+    }
+
+    public static String getGeneratedIdentifier(Expression expr) throws ParseException {
+        if (expr.getKind() == Kind.VARIABLE_EXPRESSION) {
+            VariableExpr bindingVarExpr = (VariableExpr) expr;
+            return bindingVarExpr.getVar().getValue();
+        } else if (expr.getKind() == Kind.FIELD_ACCESSOR_EXPRESSION) {
+            FieldAccessor fa = (FieldAccessor) expr;
+            return SqlppVariableUtil.toInternalVariableName(fa.getIdent().getValue());
+        } else {
+            throw new ParseException("Need an alias for the enclosed " + expr.getKind() + " expression.");
+        }
+    }
+
+    public static VariableExpr getGeneratedVariable(Expression expr) throws ParseException {
+        VarIdentifier var = new VarIdentifier(getGeneratedIdentifier(expr));
+        VariableExpr varExpr = new VariableExpr();
+        varExpr.setVar(var);
+        return varExpr;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
----------------------------------------------------------------------
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 6c737d6..122bde3 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
@@ -33,11 +33,15 @@ import org.apache.asterix.lang.sqlpp.visitor.FreeVariableVisitor;
 
 public class SqlppRewriteUtil {
 
+    private SqlppRewriteUtil() {
+    }
+
     // Applying sugar rewriting for group-by.
     public static Expression rewriteExpressionUsingGroupVariable(VariableExpr groupVar,
-            Collection<VariableExpr> targetVarList, ILangExpression expr, LangRewritingContext context)
-                    throws AsterixException {
-        SqlppGroupBySugarVisitor visitor = new SqlppGroupBySugarVisitor(context, groupVar, targetVarList);
+            Collection<VariableExpr> targetVarList, Collection<VariableExpr> allVisableVars, ILangExpression expr,
+            LangRewritingContext context) throws AsterixException {
+        SqlppGroupBySugarVisitor visitor = new SqlppGroupBySugarVisitor(context, groupVar, targetVarList,
+                allVisableVars);
         return expr.accept(visitor, null);
     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableSubstitutionUtil.java
----------------------------------------------------------------------
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
index 6438f07..322b5b6 100644
--- 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
@@ -45,6 +45,9 @@ public class SqlppVariableSubstitutionUtil {
      */
     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);
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
----------------------------------------------------------------------
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 59e9389..12a2d20 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
@@ -20,6 +20,7 @@ package org.apache.asterix.lang.sqlpp.util;
 
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -27,6 +28,7 @@ import org.apache.asterix.common.exceptions.AsterixException;
 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.expression.GbyVariableExpressionPair;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
@@ -37,7 +39,10 @@ import org.apache.asterix.lang.sqlpp.visitor.FreeVariableVisitor;
 
 public class SqlppVariableUtil {
 
-    private static String USER_VAR_PREFIX = "$";
+    private static final String USER_VAR_PREFIX = "$";
+
+    private SqlppVariableUtil() {
+    }
 
     public static VarIdentifier toUserDefinedVariableName(VarIdentifier var) {
         String varName = var.getValue();
@@ -51,6 +56,30 @@ public class SqlppVariableUtil {
         return new VarIdentifier(varName);
     }
 
+    public static String toUserDefinedName(String varName) {
+        if (varName.startsWith(USER_VAR_PREFIX)) {
+            return varName.substring(1);
+        }
+        return varName;
+    }
+
+    public static Set<VariableExpr> getLiveUserDefinedVariables(Scope scope) {
+        Set<VariableExpr> results = new HashSet<>();
+        Set<VariableExpr> liveVars = scope.getLiveVariables();
+        Iterator<VariableExpr> liveVarIter = liveVars.iterator();
+        while (liveVarIter.hasNext()) {
+            VariableExpr var = liveVarIter.next();
+            if (SqlppVariableUtil.isUserDefinedVariable(var)) {
+                results.add(var);
+            }
+        }
+        return results;
+    }
+
+    private static boolean isUserDefinedVariable(VariableExpr varExpr) {
+        return varExpr.getVar().getValue().startsWith(USER_VAR_PREFIX);
+    }
+
     public static String toInternalVariableName(String varName) {
         return USER_VAR_PREFIX + varName;
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
index 1bca7ac..7c46d73 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
@@ -55,6 +55,7 @@ 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.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
 import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppQueryExpressionVisitor;
@@ -262,4 +263,9 @@ public class CheckSql92AggregateVisitor extends AbstractSqlppQueryExpressionVisi
         return false;
     }
 
+    @Override
+    public Boolean visit(IndependentSubquery independentSubquery, ILangExpression arg) throws AsterixException {
+        return false;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
----------------------------------------------------------------------
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 2d891e0..559183e 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
@@ -46,6 +46,7 @@ import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.Query;
 import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.QuantifiedPair;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
 import org.apache.asterix.lang.sqlpp.clause.FromClause;
 import org.apache.asterix.lang.sqlpp.clause.FromTerm;
@@ -59,6 +60,7 @@ 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.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
@@ -389,7 +391,11 @@ public class DeepCopyVisitor extends AbstractSqlppQueryExpressionVisitor<ILangEx
 
     @Override
     public VariableExpr visit(VariableExpr varExpr, Void arg) throws AsterixException {
-        return new VariableExpr(varExpr.getVar());
+        VariableExpr clonedVar = new VariableExpr(
+                new VarIdentifier(varExpr.getVar().getValue(), varExpr.getVar().getId()));
+        clonedVar.setIsNewVar(varExpr.getIsNewVar());
+        clonedVar.setNamedValueAccess(varExpr.namedValueAccess());
+        return clonedVar;
     }
 
     @Override
@@ -412,4 +418,9 @@ public class DeepCopyVisitor extends AbstractSqlppQueryExpressionVisitor<ILangEx
         return new IndexAccessor(expr, indexExpr);
     }
 
+    @Override
+    public ILangExpression visit(IndependentSubquery independentSubquery, Void arg) throws AsterixException {
+        return new IndependentSubquery((Expression) independentSubquery.getExpr().accept(this, arg));
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
----------------------------------------------------------------------
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 6e70455..37c19ab 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
@@ -60,6 +60,7 @@ 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.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
@@ -414,6 +415,12 @@ public class FreeVariableVisitor extends AbstractSqlppQueryExpressionVisitor<Voi
         return null;
     }
 
+    @Override
+    public Void visit(IndependentSubquery independentSubquery, Collection<VariableExpr> arg) throws AsterixException {
+        independentSubquery.getExpr().accept(this, arg);
+        return null;
+    }
+
     private void visitLetClauses(List<LetClause> letClauses, Collection<VariableExpr> freeVars)
             throws AsterixException {
         if (letClauses == null || letClauses.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
index a613e90..589381a 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppAstPrintVisitor.java
@@ -42,6 +42,7 @@ 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.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
@@ -292,4 +293,10 @@ public class SqlppAstPrintVisitor extends QueryPrintVisitor implements ISqlppVis
         return null;
     }
 
+    @Override
+    public Void visit(IndependentSubquery independentSubquery, Integer arg) throws AsterixException {
+        independentSubquery.getExpr().accept(this, arg);
+        return null;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppCloneAndSubstituteVariablesVisitor.java
----------------------------------------------------------------------
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 62581c8..8ec2b04 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
@@ -47,6 +47,7 @@ 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.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
@@ -367,4 +368,12 @@ public class SqlppCloneAndSubstituteVariablesVisitor extends CloneAndSubstituteV
         return new Pair<ILangExpression, VariableSubstitutionEnvironment>(newHavingClause, p.second);
     }
 
+    @Override
+    public Pair<ILangExpression, VariableSubstitutionEnvironment> visit(IndependentSubquery independentSubquery,
+            VariableSubstitutionEnvironment env) throws AsterixException {
+        Pair<ILangExpression, VariableSubstitutionEnvironment> p = independentSubquery.getExpr().accept(this, env);
+        IndependentSubquery newSubquery = new IndependentSubquery((Expression) p.first);
+        return new Pair<>(newSubquery, p.second);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java
index a449402..e03d711 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppFormatPrintVisitor.java
@@ -41,6 +41,7 @@ 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.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
 import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
@@ -297,4 +298,10 @@ public class SqlppFormatPrintVisitor extends FormatPrintVisitor implements ISqlp
         }
     }
 
+    @Override
+    public Void visit(IndependentSubquery independentSubquery, Integer step) throws AsterixException {
+        independentSubquery.getExpr().accept(this, step);
+        return null;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java
index 9907999..e5bf513 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppAstVisitor.java
@@ -32,6 +32,7 @@ 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.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 
 /**
@@ -104,4 +105,9 @@ public abstract class AbstractSqlppAstVisitor<R, T> extends AbstractAstVisitor<R
         return null;
     }
 
+    @Override
+    public R visit(IndependentSubquery independentSubquery, T arg) throws AsterixException {
+        return null;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
----------------------------------------------------------------------
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 14e80d9..599654b 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
@@ -18,15 +18,25 @@
  */
 package org.apache.asterix.lang.sqlpp.visitor.base;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.asterix.common.config.MetadataConstants;
 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.ILangExpression;
 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.context.Scope;
+import org.apache.asterix.lang.common.expression.CallExpr;
 import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
 import org.apache.asterix.lang.common.expression.QuantifiedExpression;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.literal.StringLiteral;
 import org.apache.asterix.lang.common.parser.ScopeChecker;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
@@ -41,12 +51,17 @@ import org.apache.asterix.lang.sqlpp.clause.JoinClause;
 import org.apache.asterix.lang.sqlpp.clause.NestClause;
 import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+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.SqlppVariableUtil;
 import org.apache.hyracks.algebricks.core.algebra.base.Counter;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 
 public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleExpressionVisitor {
 
+    protected final FunctionSignature resolveFunction = new FunctionSignature(MetadataConstants.METADATA_DATAVERSE_NAME,
+            "resolve", FunctionIdentifier.VARARGS);
     protected final ScopeChecker scopeChecker = new ScopeChecker();
     protected final LangRewritingContext context;
 
@@ -60,19 +75,19 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
     }
 
     @Override
-    public Expression visit(FromClause fromClause, Expression arg) throws AsterixException {
+    public Expression visit(FromClause fromClause, ILangExpression arg) throws AsterixException {
         scopeChecker.extendCurrentScope();
         for (FromTerm fromTerm : fromClause.getFromTerms()) {
-            fromTerm.accept(this, arg);
+            fromTerm.accept(this, fromClause);
         }
         return null;
     }
 
     @Override
-    public Expression visit(FromTerm fromTerm, Expression arg) throws AsterixException {
+    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, arg));
+        fromTerm.setLeftExpression(fromTerm.getLeftExpression().accept(this, fromTerm));
 
         // Registers the data item variable.
         VariableExpr leftVar = fromTerm.getLeftVariable();
@@ -85,20 +100,20 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
         }
         // Visits join/unnest/nest clauses.
         for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
-            correlateClause.accept(this, arg);
+            correlateClause.accept(this, fromTerm);
         }
         return null;
     }
 
     @Override
-    public Expression visit(JoinClause joinClause, Expression arg) throws AsterixException {
+    public Expression visit(JoinClause joinClause, ILangExpression arg) throws AsterixException {
         Scope backupScope = scopeChecker.removeCurrentScope();
         Scope parentScope = scopeChecker.getCurrentScope();
         scopeChecker.createNewScope();
         // 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, arg));
+        joinClause.setRightExpression(joinClause.getRightExpression().accept(this, joinClause));
 
         // Registers the data item variable.
         VariableExpr rightVar = joinClause.getRightVariable();
@@ -117,16 +132,16 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
         scopeChecker.pushExistingScope(mergedScope);
         // The condition expression can refer to the just registered variables
         // for the right branch.
-        joinClause.setConditionExpression(joinClause.getConditionExpression().accept(this, arg));
+        joinClause.setConditionExpression(joinClause.getConditionExpression().accept(this, joinClause));
         return null;
     }
 
     @Override
-    public Expression visit(NestClause nestClause, Expression arg) throws AsterixException {
+    public Expression visit(NestClause nestClause, ILangExpression arg) throws AsterixException {
         // 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, arg));
+        nestClause.setRightExpression(nestClause.getRightExpression().accept(this, nestClause));
 
         // Registers the data item variable.
         VariableExpr rightVar = nestClause.getRightVariable();
@@ -140,13 +155,13 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
 
         // The condition expression can refer to the just registered variables
         // for the right branch.
-        nestClause.setConditionExpression(nestClause.getConditionExpression().accept(this, arg));
+        nestClause.setConditionExpression(nestClause.getConditionExpression().accept(this, nestClause));
         return null;
     }
 
     @Override
-    public Expression visit(UnnestClause unnestClause, Expression arg) throws AsterixException {
-        unnestClause.setRightExpression(unnestClause.getRightExpression().accept(this, arg));
+    public Expression visit(UnnestClause unnestClause, ILangExpression arg) throws AsterixException {
+        unnestClause.setRightExpression(unnestClause.getRightExpression().accept(this, unnestClause));
 
         // register the data item variable
         VariableExpr rightVar = unnestClause.getRightVariable();
@@ -161,7 +176,7 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
     }
 
     @Override
-    public Expression visit(SelectSetOperation selectSetOperation, Expression arg) throws AsterixException {
+    public Expression visit(SelectSetOperation selectSetOperation, ILangExpression arg) throws AsterixException {
         selectSetOperation.getLeftInput().accept(this, arg);
         for (SetOperationRight right : selectSetOperation.getRightInputs()) {
             scopeChecker.createNewScope();
@@ -171,27 +186,27 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
     }
 
     @Override
-    public Expression visit(Query q, Expression arg) throws AsterixException {
-        q.setBody(q.getBody().accept(this, arg));
+    public Expression visit(Query q, ILangExpression arg) throws AsterixException {
+        q.setBody(q.getBody().accept(this, q));
         q.setVarCounter(scopeChecker.getVarCounter());
         context.setVarCounter(scopeChecker.getVarCounter());
         return null;
     }
 
     @Override
-    public Expression visit(FunctionDecl fd, Expression arg) throws AsterixException {
+    public Expression visit(FunctionDecl fd, ILangExpression arg) throws AsterixException {
         scopeChecker.createNewScope();
-        fd.setFuncBody(fd.getFuncBody().accept(this, arg));
+        fd.setFuncBody(fd.getFuncBody().accept(this, fd));
         scopeChecker.removeCurrentScope();
         return null;
     }
 
     @Override
-    public Expression visit(GroupbyClause gc, Expression arg) throws AsterixException {
+    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));
+            gbyVarExpr.setExpr(gbyVarExpr.getExpr().accept(this, gc));
             VariableExpr gbyVar = gbyVarExpr.getVar();
             if (gbyVar != null) {
                 newScope.addNewVarSymbolToScope(gbyVarExpr.getVar().getVar());
@@ -205,30 +220,30 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
     }
 
     @Override
-    public Expression visit(LimitClause limitClause, Expression arg) throws AsterixException {
+    public Expression visit(LimitClause limitClause, ILangExpression arg) throws AsterixException {
         scopeChecker.pushForbiddenScope(scopeChecker.getCurrentScope());
-        limitClause.setLimitExpr(limitClause.getLimitExpr().accept(this, arg));
+        limitClause.setLimitExpr(limitClause.getLimitExpr().accept(this, limitClause));
         scopeChecker.popForbiddenScope();
         return null;
     }
 
     @Override
-    public Expression visit(LetClause letClause, Expression arg) throws AsterixException {
+    public Expression visit(LetClause letClause, ILangExpression arg) throws AsterixException {
         scopeChecker.extendCurrentScope();
-        letClause.setBindingExpr(letClause.getBindingExpr().accept(this, arg));
+        letClause.setBindingExpr(letClause.getBindingExpr().accept(this, letClause));
         scopeChecker.getCurrentScope().addNewVarSymbolToScope(letClause.getVarExpr().getVar());
         return null;
     }
 
     @Override
-    public Expression visit(SelectExpression selectExpression, Expression arg) throws AsterixException {
+    public Expression visit(SelectExpression selectExpression, ILangExpression arg) throws AsterixException {
         Scope scopeBeforeSelectExpression = scopeChecker.getCurrentScope();
         scopeChecker.createNewScope();
 
         // visit let list
         if (selectExpression.hasLetClauses()) {
             for (LetClause letClause : selectExpression.getLetList()) {
-                letClause.accept(this, arg);
+                letClause.accept(this, selectExpression);
             }
         }
 
@@ -237,12 +252,12 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
 
         // visit order by
         if (selectExpression.hasOrderby()) {
-            selectExpression.getOrderbyClause().accept(this, arg);
+            selectExpression.getOrderbyClause().accept(this, selectExpression);
         }
 
         // visit limit
         if (selectExpression.hasLimit()) {
-            selectExpression.getLimitClause().accept(this, arg);
+            selectExpression.getLimitClause().accept(this, selectExpression);
         }
 
         // Exit scopes that were entered within this select expression
@@ -253,19 +268,31 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
     }
 
     @Override
-    public Expression visit(QuantifiedExpression qe, Expression arg) throws AsterixException {
+    public Expression visit(IndependentSubquery independentSubquery, ILangExpression arg) throws AsterixException {
+        // Masks parent scopes so as that the subquery is independent of the environment.
+        // In this way, free variables defined in the subquery will not be resolved using
+        // variables defined in the parent scope.
+        Scope scope = new Scope(scopeChecker, scopeChecker.getCurrentScope(), true);
+        scopeChecker.pushExistingScope(scope);
+        independentSubquery.getExpr().accept(this, arg);
+        scopeChecker.removeCurrentScope();
+        return independentSubquery;
+    }
+
+    @Override
+    public Expression visit(QuantifiedExpression qe, ILangExpression arg) throws AsterixException {
         scopeChecker.createNewScope();
         for (QuantifiedPair pair : qe.getQuantifiedList()) {
             scopeChecker.getCurrentScope().addNewVarSymbolToScope(pair.getVarExpr().getVar());
-            pair.setExpr(pair.getExpr().accept(this, arg));
+            pair.setExpr(pair.getExpr().accept(this, qe));
         }
-        qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, arg));
+        qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, qe));
         scopeChecker.removeCurrentScope();
         return qe;
     }
 
     @Override
-    public Expression visit(VariableExpr varExpr, Expression arg) throws AsterixException {
+    public Expression visit(VariableExpr varExpr, ILangExpression arg) throws AsterixException {
         String varName = varExpr.getVar().getValue();
         if (scopeChecker.isInForbiddenScopes(varName)) {
             throw new AsterixException(
@@ -281,4 +308,14 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
         return varExpr;
     }
 
+    // Rewrites for an undefined variable reference, which potentially could be a syntatic sugar.
+    protected Expression wrapWithResolveFunction(VariableExpr expr, Set<VariableExpr> liveVars)
+            throws AsterixException {
+        List<Expression> argList = new ArrayList<>();
+        //Ignore the parser-generated prefix "$" for a dataset.
+        String varName = SqlppVariableUtil.toUserDefinedVariableName(expr.getVar().getValue()).getValue();
+        argList.add(new LiteralExpr(new StringLiteral(varName)));
+        argList.addAll(liveVars);
+        return new CallExpr(resolveFunction, argList);
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
----------------------------------------------------------------------
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 18c2789..262b260 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
@@ -23,6 +23,7 @@ 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.base.ILangExpression;
 import org.apache.asterix.lang.common.clause.GroupbyClause;
 import org.apache.asterix.lang.common.clause.LetClause;
 import org.apache.asterix.lang.common.clause.LimitClause;
@@ -57,13 +58,15 @@ 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.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
 
-public class AbstractSqlppSimpleExpressionVisitor extends AbstractSqlppQueryExpressionVisitor<Expression, Expression> {
+public class AbstractSqlppSimpleExpressionVisitor
+        extends AbstractSqlppQueryExpressionVisitor<Expression, ILangExpression> {
 
     @Override
-    public Expression visit(FromClause fromClause, Expression arg) throws AsterixException {
+    public Expression visit(FromClause fromClause, ILangExpression arg) throws AsterixException {
         for (FromTerm fromTerm : fromClause.getFromTerms()) {
             fromTerm.accept(this, arg);
         }
@@ -71,7 +74,7 @@ public class AbstractSqlppSimpleExpressionVisitor extends AbstractSqlppQueryExpr
     }
 
     @Override
-    public Expression visit(FromTerm fromTerm, Expression arg) throws AsterixException {
+    public Expression visit(FromTerm fromTerm, ILangExpression arg) throws AsterixException {
         // Visit the left expression of a from term.
         fromTerm.setLeftExpression(fromTerm.getLeftExpression().accept(this, arg));
 
@@ -83,33 +86,33 @@ public class AbstractSqlppSimpleExpressionVisitor extends AbstractSqlppQueryExpr
     }
 
     @Override
-    public Expression visit(JoinClause joinClause, Expression arg) throws AsterixException {
+    public Expression visit(JoinClause joinClause, ILangExpression arg) throws AsterixException {
         joinClause.setRightExpression(joinClause.getRightExpression().accept(this, arg));
         joinClause.setConditionExpression(joinClause.getConditionExpression().accept(this, arg));
         return null;
     }
 
     @Override
-    public Expression visit(NestClause nestClause, Expression arg) throws AsterixException {
+    public Expression visit(NestClause nestClause, ILangExpression arg) throws AsterixException {
         nestClause.setRightExpression(nestClause.getRightExpression().accept(this, arg));
         nestClause.setConditionExpression(nestClause.getConditionExpression().accept(this, arg));
         return null;
     }
 
     @Override
-    public Expression visit(UnnestClause unnestClause, Expression arg) throws AsterixException {
+    public Expression visit(UnnestClause unnestClause, ILangExpression arg) throws AsterixException {
         unnestClause.setRightExpression(unnestClause.getRightExpression().accept(this, arg));
         return null;
     }
 
     @Override
-    public Expression visit(Projection projection, Expression arg) throws AsterixException {
+    public Expression visit(Projection projection, ILangExpression arg) throws AsterixException {
         projection.setExpression(projection.getExpression().accept(this, arg));
         return null;
     }
 
     @Override
-    public Expression visit(SelectBlock selectBlock, Expression arg) throws AsterixException {
+    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".
         if (selectBlock.hasFromClause()) {
@@ -141,24 +144,24 @@ public class AbstractSqlppSimpleExpressionVisitor extends AbstractSqlppQueryExpr
     }
 
     @Override
-    public Expression visit(SelectClause selectClause, Expression arg) throws AsterixException {
+    public Expression visit(SelectClause selectClause, ILangExpression arg) throws AsterixException {
         if (selectClause.selectElement()) {
-            selectClause.getSelectElement().accept(this, arg);
+            selectClause.getSelectElement().accept(this, selectClause);
         }
         if (selectClause.selectRegular()) {
-            selectClause.getSelectRegular().accept(this, arg);
+            selectClause.getSelectRegular().accept(this, selectClause);
         }
         return null;
     }
 
     @Override
-    public Expression visit(SelectElement selectElement, Expression arg) throws AsterixException {
-        selectElement.setExpression(selectElement.getExpression().accept(this, arg));
+    public Expression visit(SelectElement selectElement, ILangExpression arg) throws AsterixException {
+        selectElement.setExpression(selectElement.getExpression().accept(this, selectElement));
         return null;
     }
 
     @Override
-    public Expression visit(SelectRegular selectRegular, Expression arg) throws AsterixException {
+    public Expression visit(SelectRegular selectRegular, ILangExpression arg) throws AsterixException {
         for (Projection projection : selectRegular.getProjections()) {
             projection.accept(this, arg);
         }
@@ -166,7 +169,7 @@ public class AbstractSqlppSimpleExpressionVisitor extends AbstractSqlppQueryExpr
     }
 
     @Override
-    public Expression visit(SelectSetOperation selectSetOperation, Expression arg) throws AsterixException {
+    public Expression visit(SelectSetOperation selectSetOperation, ILangExpression arg) throws AsterixException {
         selectSetOperation.getLeftInput().accept(this, arg);
         for (SetOperationRight right : selectSetOperation.getRightInputs()) {
             right.getSetOperationRightInput().accept(this, arg);
@@ -175,173 +178,179 @@ public class AbstractSqlppSimpleExpressionVisitor extends AbstractSqlppQueryExpr
     }
 
     @Override
-    public Expression visit(HavingClause havingClause, Expression arg) throws AsterixException {
-        havingClause.setFilterExpression(havingClause.getFilterExpression().accept(this, arg));
+    public Expression visit(HavingClause havingClause, ILangExpression arg) throws AsterixException {
+        havingClause.setFilterExpression(havingClause.getFilterExpression().accept(this, havingClause));
         return null;
     }
 
     @Override
-    public Expression visit(Query q, Expression arg) throws AsterixException {
-        q.setBody(q.getBody().accept(this, arg));
+    public Expression visit(Query q, ILangExpression arg) throws AsterixException {
+        q.setBody(q.getBody().accept(this, q));
         return null;
     }
 
     @Override
-    public Expression visit(FunctionDecl fd, Expression arg) throws AsterixException {
-        fd.setFuncBody(fd.getFuncBody().accept(this, arg));
+    public Expression visit(FunctionDecl fd, ILangExpression arg) throws AsterixException {
+        fd.setFuncBody(fd.getFuncBody().accept(this, fd));
         return null;
     }
 
     @Override
-    public Expression visit(WhereClause whereClause, Expression arg) throws AsterixException {
-        whereClause.setWhereExpr(whereClause.getWhereExpr().accept(this, arg));
+    public Expression visit(WhereClause whereClause, ILangExpression arg) throws AsterixException {
+        whereClause.setWhereExpr(whereClause.getWhereExpr().accept(this, whereClause));
         return null;
     }
 
     @Override
-    public Expression visit(OrderbyClause oc, Expression arg) throws AsterixException {
-        List<Expression> newOrderbyList = new ArrayList<Expression>();
+    public Expression visit(OrderbyClause oc, ILangExpression arg) throws AsterixException {
+        List<Expression> newOrderbyList = new ArrayList<>();
         for (Expression orderExpr : oc.getOrderbyList()) {
-            newOrderbyList.add(orderExpr.accept(this, arg));
+            newOrderbyList.add(orderExpr.accept(this, oc));
         }
         oc.setOrderbyList(newOrderbyList);
         return null;
     }
 
     @Override
-    public Expression visit(GroupbyClause gc, Expression arg) throws AsterixException {
+    public Expression visit(GroupbyClause gc, ILangExpression arg) throws AsterixException {
         for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
-            gbyVarExpr.setExpr(gbyVarExpr.getExpr().accept(this, arg));
+            gbyVarExpr.setExpr(gbyVarExpr.getExpr().accept(this, gc));
         }
         return null;
     }
 
     @Override
-    public Expression visit(LimitClause limitClause, Expression arg) throws AsterixException {
-        limitClause.setLimitExpr(limitClause.getLimitExpr().accept(this, arg));
+    public Expression visit(LimitClause limitClause, ILangExpression arg) throws AsterixException {
+        limitClause.setLimitExpr(limitClause.getLimitExpr().accept(this, limitClause));
         if (limitClause.hasOffset()) {
-            limitClause.setOffset(limitClause.getOffset().accept(this, arg));
+            limitClause.setOffset(limitClause.getOffset().accept(this, limitClause));
         }
         return null;
     }
 
     @Override
-    public Expression visit(LetClause letClause, Expression arg) throws AsterixException {
-        letClause.setBindingExpr(letClause.getBindingExpr().accept(this, arg));
+    public Expression visit(LetClause letClause, ILangExpression arg) throws AsterixException {
+        letClause.setBindingExpr(letClause.getBindingExpr().accept(this, letClause));
         return null;
     }
 
     @Override
-    public Expression visit(SelectExpression selectExpression, Expression arg) throws AsterixException {
+    public Expression visit(SelectExpression selectExpression, ILangExpression arg) throws AsterixException {
         // visit let list
         if (selectExpression.hasLetClauses()) {
             for (LetClause letClause : selectExpression.getLetList()) {
-                letClause.accept(this, arg);
+                letClause.accept(this, selectExpression);
             }
         }
 
         // visit the main select.
-        selectExpression.getSelectSetOperation().accept(this, arg);
+        selectExpression.getSelectSetOperation().accept(this, selectExpression);
 
         // visit order by
         if (selectExpression.hasOrderby()) {
             for (Expression orderExpr : selectExpression.getOrderbyClause().getOrderbyList()) {
-                orderExpr.accept(this, arg);
+                orderExpr.accept(this, selectExpression);
             }
         }
 
         // visit limit
         if (selectExpression.hasLimit()) {
-            selectExpression.getLimitClause().accept(this, arg);
+            selectExpression.getLimitClause().accept(this, selectExpression);
         }
         return selectExpression;
     }
 
     @Override
-    public Expression visit(LiteralExpr l, Expression arg) throws AsterixException {
+    public Expression visit(LiteralExpr l, ILangExpression arg) throws AsterixException {
         return l;
     }
 
     @Override
-    public Expression visit(ListConstructor lc, Expression arg) throws AsterixException {
-        List<Expression> newExprList = new ArrayList<Expression>();
+    public Expression visit(ListConstructor lc, ILangExpression arg) throws AsterixException {
+        List<Expression> newExprList = new ArrayList<>();
         for (Expression expr : lc.getExprList()) {
-            newExprList.add(expr.accept(this, arg));
+            newExprList.add(expr.accept(this, lc));
         }
         lc.setExprList(newExprList);
         return lc;
     }
 
     @Override
-    public Expression visit(RecordConstructor rc, Expression arg) throws AsterixException {
+    public Expression visit(RecordConstructor rc, ILangExpression arg) throws AsterixException {
         for (FieldBinding binding : rc.getFbList()) {
-            binding.setLeftExpr(binding.getLeftExpr().accept(this, arg));
-            binding.setRightExpr(binding.getRightExpr().accept(this, arg));
+            binding.setLeftExpr(binding.getLeftExpr().accept(this, rc));
+            binding.setRightExpr(binding.getRightExpr().accept(this, rc));
         }
         return rc;
     }
 
     @Override
-    public Expression visit(OperatorExpr operatorExpr, Expression arg) throws AsterixException {
-        List<Expression> newExprList = new ArrayList<Expression>();
+    public Expression visit(OperatorExpr operatorExpr, ILangExpression arg) throws AsterixException {
+        List<Expression> newExprList = new ArrayList<>();
         for (Expression expr : operatorExpr.getExprList()) {
-            newExprList.add(expr.accept(this, arg));
+            newExprList.add(expr.accept(this, operatorExpr));
         }
         operatorExpr.setExprList(newExprList);
         return operatorExpr;
     }
 
     @Override
-    public Expression visit(IfExpr ifExpr, Expression arg) throws AsterixException {
-        ifExpr.setCondExpr(ifExpr.getCondExpr().accept(this, arg));
-        ifExpr.setThenExpr(ifExpr.getThenExpr().accept(this, arg));
-        ifExpr.setElseExpr(ifExpr.getElseExpr().accept(this, arg));
+    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));
         return ifExpr;
     }
 
     @Override
-    public Expression visit(QuantifiedExpression qe, Expression arg) throws AsterixException {
+    public Expression visit(QuantifiedExpression qe, ILangExpression arg) throws AsterixException {
         for (QuantifiedPair pair : qe.getQuantifiedList()) {
-            pair.setExpr(pair.getExpr().accept(this, arg));
+            pair.setExpr(pair.getExpr().accept(this, qe));
         }
-        qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, arg));
+        qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, qe));
         return qe;
     }
 
     @Override
-    public Expression visit(CallExpr callExpr, Expression arg) throws AsterixException {
-        List<Expression> newExprList = new ArrayList<Expression>();
+    public Expression visit(CallExpr callExpr, ILangExpression arg) throws AsterixException {
+        List<Expression> newExprList = new ArrayList<>();
         for (Expression expr : callExpr.getExprList()) {
-            newExprList.add(expr.accept(this, arg));
+            newExprList.add(expr.accept(this, callExpr));
         }
         callExpr.setExprList(newExprList);
         return callExpr;
     }
 
     @Override
-    public Expression visit(VariableExpr varExpr, Expression arg) throws AsterixException {
+    public Expression visit(VariableExpr varExpr, ILangExpression arg) throws AsterixException {
         return varExpr;
     }
 
     @Override
-    public Expression visit(UnaryExpr u, Expression arg) throws AsterixException {
-        u.setExpr(u.getExpr().accept(this, arg));
+    public Expression visit(UnaryExpr u, ILangExpression arg) throws AsterixException {
+        u.setExpr(u.getExpr().accept(this, u));
         return u;
     }
 
     @Override
-    public Expression visit(FieldAccessor fa, Expression arg) throws AsterixException {
-        fa.setExpr(fa.getExpr().accept(this, arg));
+    public Expression visit(FieldAccessor fa, ILangExpression arg) throws AsterixException {
+        fa.setExpr(fa.getExpr().accept(this, fa));
         return fa;
     }
 
     @Override
-    public Expression visit(IndexAccessor ia, Expression arg) throws AsterixException {
-        ia.setExpr(ia.getExpr().accept(this, arg));
+    public Expression visit(IndexAccessor ia, ILangExpression arg) throws AsterixException {
+        ia.setExpr(ia.getExpr().accept(this, ia));
         if (ia.getIndexExpr() != null) {
             ia.setIndexExpr(ia.getIndexExpr());
         }
         return ia;
     }
 
+    @Override
+    public Expression visit(IndependentSubquery independentSubquery, ILangExpression arg) throws AsterixException {
+        independentSubquery.setExpr(independentSubquery.getExpr().accept(this, arg));
+        return independentSubquery;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java
index 538d9c3..4e5e58d 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/ISqlppVisitor.java
@@ -32,6 +32,7 @@ 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.IndependentSubquery;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 
 public interface ISqlppVisitor<R, T> extends ILangVisitor<R, T> {
@@ -61,4 +62,6 @@ public interface ISqlppVisitor<R, T> extends ILangVisitor<R, T> {
     R visit(UnnestClause unnestClause, T arg) throws AsterixException;
 
     R visit(HavingClause havingClause, T arg) throws AsterixException;
+
+    R visit(IndependentSubquery independentSubquery, T arg) throws AsterixException;
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html
index 8aecbd9..34f576f 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.html
@@ -833,7 +833,7 @@
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod100">Projection</A></TD>
 <TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
-<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod44">Expression</A> ( &lt;AS&gt; )? <A HREF="#prod18">Identifier</A> | <A HREF="#prod44">Expression</A> &lt;DOT&gt; &lt;MUL&gt; | &lt;MUL&gt; )</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod44">Expression</A> ( ( &lt;AS&gt; )? <A HREF="#prod18">Identifier</A> )? | <A HREF="#prod44">Expression</A> &lt;DOT&gt; &lt;MUL&gt; | &lt;MUL&gt; )</TD>
 </TR>
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod94">FromClause</A></TD>
@@ -843,22 +843,22 @@
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod101">FromTerm</A></TD>
 <TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
-<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod44">Expression</A> ( &lt;AS&gt; )? <A HREF="#prod50">Variable</A> ( &lt;AT&gt; <A HREF="#prod50">Variable</A> )? ( ( <A HREF="#prod102">JoinType</A> )? ( <A HREF="#prod103">JoinClause</A> | <A HREF="#prod104">NestClause</A> | <A HREF="#prod105">UnnestClause</A> ) )*</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod44">Expression</A> ( ( &lt;AS&gt; )? <A HREF="#prod50">Variable</A> )? ( &lt;AT&gt; <A HREF="#prod50">Variable</A> )? ( ( <A HREF="#prod102">JoinType</A> )? ( <A HREF="#prod103">JoinClause</A> | <A HREF="#prod104">NestClause</A> | <A HREF="#prod105">UnnestClause</A> ) )*</TD>
 </TR>
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod103">JoinClause</A></TD>
 <TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
-<TD ALIGN=LEFT VALIGN=BASELINE>&lt;JOIN&gt; <A HREF="#prod44">Expression</A> ( &lt;AS&gt; )? <A HREF="#prod50">Variable</A> ( &lt;AT&gt; <A HREF="#prod50">Variable</A> )? &lt;ON&gt; <A HREF="#prod44">Expression</A></TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;JOIN&gt; <A HREF="#prod44">Expression</A> ( ( &lt;AS&gt; )? <A HREF="#prod50">Variable</A> )? ( &lt;AT&gt; <A HREF="#prod50">Variable</A> )? &lt;ON&gt; <A HREF="#prod44">Expression</A></TD>
 </TR>
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod104">NestClause</A></TD>
 <TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
-<TD ALIGN=LEFT VALIGN=BASELINE>&lt;NEST&gt; <A HREF="#prod44">Expression</A> ( &lt;AS&gt; )? <A HREF="#prod50">Variable</A> ( &lt;AT&gt; <A HREF="#prod50">Variable</A> )? &lt;ON&gt; <A HREF="#prod44">Expression</A></TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>&lt;NEST&gt; <A HREF="#prod44">Expression</A> ( ( &lt;AS&gt; )? <A HREF="#prod50">Variable</A> )? ( &lt;AT&gt; <A HREF="#prod50">Variable</A> )? &lt;ON&gt; <A HREF="#prod44">Expression</A></TD>
 </TR>
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod105">UnnestClause</A></TD>
 <TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
-<TD ALIGN=LEFT VALIGN=BASELINE>( &lt;UNNEST&gt; | &lt;CORRELATE&gt; | &lt;FLATTEN&gt; ) <A HREF="#prod44">Expression</A> ( &lt;AS&gt; )? <A HREF="#prod50">Variable</A> ( &lt;AT&gt; <A HREF="#prod50">Variable</A> )?</TD>
+<TD ALIGN=LEFT VALIGN=BASELINE>( &lt;UNNEST&gt; | &lt;CORRELATE&gt; | &lt;FLATTEN&gt; ) <A HREF="#prod44">Expression</A> ( ( &lt;AS&gt; )? <A HREF="#prod50">Variable</A> ) ( &lt;AT&gt; <A HREF="#prod50">Variable</A> )?</TD>
 </TR>
 <TR>
 <TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod102">JoinType</A></TD>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 05acb1d..f587e50 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -143,6 +143,7 @@ import org.apache.asterix.lang.sqlpp.optype.JoinType;
 import org.apache.asterix.lang.sqlpp.optype.SetOpType;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
+import org.apache.asterix.lang.sqlpp.util.ExpressionToVariableUtil;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.algebricks.common.utils.Triple;
@@ -2352,11 +2353,14 @@ Projection Projection() throws ParseException: {
 {
   (
     LOOKAHEAD(2)
-    expr= Expression() (<AS>)? name = Identifier()
+    expr = Expression() ((<AS>)? name = Identifier())?
     | expr = Expression() <DOT> <MUL> {exprStar = true; }
     | <MUL> {star = true; }
   )
   {
+    if(name == null){
+       name = SqlppVariableUtil.toUserDefinedName(ExpressionToVariableUtil.getGeneratedIdentifier(expr));
+    }
     return new Projection(expr, name, star, exprStar);
   }
 }
@@ -2385,7 +2389,7 @@ FromTerm FromTerm() throws ParseException :
   List<AbstractBinaryCorrelateClause> correlateClauses = new ArrayList<AbstractBinaryCorrelateClause>();
 }
 {
-  leftExpr = Expression() (<AS>)? leftVar = Variable() (<AT> posVar = Variable())?
+  leftExpr = Expression() ((<AS>)? leftVar = Variable())? (<AT> posVar = Variable())?
   (
      {JoinType joinType = JoinType.INNER; }
      (joinType = JoinType())?
@@ -2403,6 +2407,9 @@ FromTerm FromTerm() throws ParseException :
      }
   )*
   {
+    if(leftVar==null){
+        leftVar = ExpressionToVariableUtil.getGeneratedVariable(leftExpr);
+    }
     return new FromTerm(leftExpr, leftVar, posVar, correlateClauses);
   }
 }
@@ -2415,8 +2422,11 @@ JoinClause JoinClause(JoinType joinType) throws ParseException :
     Expression conditionExpr = null;
 }
 {
-  <JOIN> rightExpr = Expression() (<AS>)? rightVar = Variable() (<AT> posVar = Variable())? <ON> conditionExpr = Expression()
+  <JOIN> rightExpr = Expression() ((<AS>)? rightVar = Variable())? (<AT> posVar = Variable())? <ON> conditionExpr = Expression()
   {
+    if(rightVar==null){
+        rightVar = ExpressionToVariableUtil.getGeneratedVariable(rightExpr);
+    }
     return new JoinClause(joinType, rightExpr, rightVar, posVar, conditionExpr);
   }
 }
@@ -2429,8 +2439,11 @@ NestClause NestClause(JoinType joinType) throws ParseException :
     Expression conditionExpr = null;
 }
 {
-  <NEST> rightExpr = Expression() (<AS>)? rightVar = Variable() (<AT> posVar = Variable())?  <ON> conditionExpr = Expression()
+  <NEST> rightExpr = Expression() ((<AS>)? rightVar = Variable())? (<AT> posVar = Variable())?  <ON> conditionExpr = Expression()
   {
+    if(rightVar==null){
+        rightVar = ExpressionToVariableUtil.getGeneratedVariable(rightExpr);
+    }
     return new NestClause(joinType, rightExpr, rightVar, posVar, conditionExpr);
   }
 }
@@ -2442,8 +2455,11 @@ UnnestClause UnnestClause(JoinType joinType) throws ParseException :
     VariableExpr posVar = null;
 }
 {
-  (<UNNEST>|<CORRELATE>|<FLATTEN>) rightExpr = Expression() (<AS>)? rightVar = Variable() (<AT> posVar = Variable())?
+  (<UNNEST>|<CORRELATE>|<FLATTEN>) rightExpr = Expression() ((<AS>)? rightVar = Variable()) (<AT> posVar = Variable())?
   {
+    if(rightVar==null){
+        rightVar = ExpressionToVariableUtil.getGeneratedVariable(rightExpr);
+    }
     return new UnnestClause(joinType, rightExpr, rightVar, posVar);
   }
 }
@@ -2572,15 +2588,24 @@ GroupbyClause GroupbyClause()throws ParseException :
         var = Variable()
         )?
         {
+            if(var==null){
+                var = ExpressionToVariableUtil.getGeneratedVariable(expr);
+            }
             GbyVariableExpressionPair pair1 = new GbyVariableExpressionPair(var, expr);
             vePairList.add(pair1);
         }
        ( LOOKAHEAD(1) <COMMA>
+         {
+            var = null;
+         }
          expr = Expression()
          (LOOKAHEAD(1)  (<AS>)?
          var = Variable()
          )?
          {
+             if(var==null){
+                var = ExpressionToVariableUtil.getGeneratedVariable(expr);
+             }
              GbyVariableExpressionPair pair2 = new GbyVariableExpressionPair(var, expr);
              vePairList.add(pair2);
          }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/9e3f9bef/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/AqlMetadataProvider.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/AqlMetadataProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/AqlMetadataProvider.java
index 7557b79..226ab3c 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/AqlMetadataProvider.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/AqlMetadataProvider.java
@@ -2104,8 +2104,13 @@ public class AqlMetadataProvider implements IMetadataProvider<AqlSourceId, Strin
     }
 
     public Dataset findDataset(String dataverse, String dataset) throws AlgebricksException {
+        String dv = dataverse == null ? (defaultDataverse == null ? null : defaultDataverse.getDataverseName())
+                : dataverse;
+        if (dv == null) {
+            return null;
+        }
         try {
-            return MetadataManager.INSTANCE.getDataset(mdTxnCtx, dataverse, dataset);
+            return MetadataManager.INSTANCE.getDataset(mdTxnCtx, dv, dataset);
         } catch (MetadataException e) {
             throw new AlgebricksException(e);
         }


Mime
View raw message