http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/AbstractSqlppExpressionExtractionVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/AbstractSqlppExpressionExtractionVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/AbstractSqlppExpressionExtractionVisitor.java
new file mode 100644
index 0000000..b78cd9c
--- /dev/null
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/AbstractSqlppExpressionExtractionVisitor.java
@@ -0,0 +1,149 @@
+/*
+ * 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.rewrites.visitor;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
+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.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.asterix.lang.sqlpp.clause.FromClause;
+import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
+import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+
+/**
+ * Base class for visitors that extract expressions into LET clauses.
+ * Subclasses should call {@link #extractExpressions(List, int, 
SourceLocation)} to perform the extraction.
+ */
+abstract class AbstractSqlppExpressionExtractionVisitor extends 
AbstractSqlppSimpleExpressionVisitor {
+
+    protected final LangRewritingContext context;
+
+    private final Deque<List<Pair<Expression, VarIdentifier>>> stack = new 
ArrayDeque<>();
+
+    AbstractSqlppExpressionExtractionVisitor(LangRewritingContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public Expression visit(SelectBlock selectBlock, ILangExpression arg) 
throws CompilationException {
+        List<Pair<Expression, VarIdentifier>> extractionList = new 
ArrayList<>();
+        stack.push(extractionList);
+
+        if (selectBlock.hasFromClause()) {
+            FromClause clause = selectBlock.getFromClause();
+            clause.accept(this, arg);
+            if (!extractionList.isEmpty()) {
+                handleUnsupportedClause(clause, extractionList);
+            }
+        }
+        List<LetClause> letList = selectBlock.getLetList();
+        if (selectBlock.hasLetClauses()) {
+            visitLetClauses(letList, extractionList, arg);
+        }
+        if (selectBlock.hasWhereClause()) {
+            selectBlock.getWhereClause().accept(this, arg);
+            introduceLetClauses(extractionList, letList);
+        }
+        if (selectBlock.hasGroupbyClause()) {
+            selectBlock.getGroupbyClause().accept(this, arg);
+            introduceLetClauses(extractionList, letList);
+        }
+        List<LetClause> letListAfterGby = selectBlock.getLetListAfterGroupby();
+        if (selectBlock.hasLetClausesAfterGroupby()) {
+            visitLetClauses(letListAfterGby, extractionList, arg);
+        }
+        if (selectBlock.hasHavingClause()) {
+            selectBlock.getHavingClause().accept(this, arg);
+            introduceLetClauses(extractionList, letListAfterGby);
+        }
+        selectBlock.getSelectClause().accept(this, arg);
+        introduceLetClauses(extractionList, selectBlock.hasGroupbyClause() ? 
letListAfterGby : letList);
+
+        stack.pop();
+        return null;
+    }
+
+    private void visitLetClauses(List<LetClause> letList, 
List<Pair<Expression, VarIdentifier>> extractionList,
+            ILangExpression arg) throws CompilationException {
+        List<LetClause> newLetList = new ArrayList<>(letList.size());
+        for (LetClause letClause : letList) {
+            letClause.accept(this, arg);
+            introduceLetClauses(extractionList, newLetList);
+            newLetList.add(letClause);
+        }
+        if (newLetList.size() > letList.size()) {
+            letList.clear();
+            letList.addAll(newLetList);
+        }
+    }
+
+    private void introduceLetClauses(List<Pair<Expression, VarIdentifier>> 
fromBindingList, List<LetClause> toLetList) {
+        for (Pair<Expression, VarIdentifier> p : fromBindingList) {
+            Expression bindExpr = p.first;
+            VarIdentifier var = p.second;
+            VariableExpr varExpr = new VariableExpr(var);
+            varExpr.setSourceLocation(bindExpr.getSourceLocation());
+            toLetList.add(new LetClause(varExpr, bindExpr));
+            context.addExcludedForFieldAccessVar(var);
+        }
+        fromBindingList.clear();
+    }
+
+    List<Expression> extractExpressions(List<Expression> exprList, int limit, 
SourceLocation sourceLocation)
+            throws CompilationException {
+        List<Pair<Expression, VarIdentifier>> outLetList = stack.peek();
+        if (outLetList == null) {
+            throw new CompilationException(ErrorCode.COMPILATION_ERROR, 
sourceLocation);
+        }
+        int n = exprList.size();
+        List<Expression> newExprList = new ArrayList<>(n);
+        for (int i = 0; i < n; i++) {
+            Expression expr = exprList.get(i);
+            Expression newExpr;
+            if (i < limit && isExtractableExpression(expr)) {
+                VarIdentifier v = context.newVariable();
+                VariableExpr vExpr = new VariableExpr(v);
+                vExpr.setSourceLocation(expr.getSourceLocation());
+                outLetList.add(new Pair<>(expr, v));
+                newExpr = vExpr;
+            } else {
+                newExpr = expr;
+            }
+            newExprList.add(newExpr);
+        }
+        return newExprList;
+    }
+
+    abstract boolean isExtractableExpression(Expression expr);
+
+    abstract void handleUnsupportedClause(FromClause clause, 
List<Pair<Expression, VarIdentifier>> extractionList)
+            throws CompilationException;
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/Sql92AggregateFunctionVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/Sql92AggregateFunctionVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/Sql92AggregateFunctionVisitor.java
new file mode 100644
index 0000000..2be752d
--- /dev/null
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/Sql92AggregateFunctionVisitor.java
@@ -0,0 +1,176 @@
+/*
+ * 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.rewrites.visitor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
+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.FieldAccessor;
+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.FromTerm;
+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.SelectSetOperation;
+import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
+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.SqlppVariableUtil;
+import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+
+/**
+ * Rewrites SQL-92 aggregate function into a SQL++ core aggregate function. 
<br/>
+ * For example
+ * <code>SUM(e.salary + i.bonus)</code>
+ * is turned into
+ * <code>array_sum( (FROM g AS gi SELECT ELEMENT gi.e.salary + gi.i.bonus) 
)</code>
+ * where <code>g</code> is a 'group as' variable
+ */
+class Sql92AggregateFunctionVisitor extends 
AbstractSqlppSimpleExpressionVisitor {
+
+    private final LangRewritingContext context;
+
+    private final Expression groupVar;
+
+    private final Map<Expression, Identifier> fieldVars;
+
+    private final Collection<VariableExpr> outerVars;
+
+    Sql92AggregateFunctionVisitor(LangRewritingContext context, VariableExpr 
groupVar,
+            Map<Expression, Identifier> fieldVars, Collection<VariableExpr> 
outerVars) {
+        this.context = context;
+        this.groupVar = groupVar;
+        this.fieldVars = fieldVars;
+        this.outerVars = outerVars;
+    }
+
+    @Override
+    public Expression visit(CallExpr callExpr, ILangExpression arg) throws 
CompilationException {
+        List<Expression> newExprList = new ArrayList<>();
+        FunctionSignature signature = callExpr.getFunctionSignature();
+        boolean aggregate = 
FunctionMapUtil.isSql92AggregateFunction(signature);
+        boolean rewritten = false;
+        for (Expression expr : callExpr.getExprList()) {
+            Expression newExpr =
+                    aggregate ? wrapAggregationArgument(expr, groupVar, 
fieldVars, outerVars, context) : expr;
+            rewritten |= newExpr != expr;
+            newExprList.add(newExpr.accept(this, arg));
+        }
+        if (rewritten) {
+            // Rewrites the SQL-92 function name to core functions,
+            // e.g., SUM --> array_sum
+            
callExpr.setFunctionSignature(FunctionMapUtil.sql92ToCoreAggregateFunction(signature));
+        }
+        callExpr.setExprList(newExprList);
+        return callExpr;
+    }
+
+    static Expression wrapAggregationArgument(Expression expr, Expression 
groupVar,
+            Map<Expression, Identifier> fieldVars, Collection<VariableExpr> 
outerVars, LangRewritingContext context)
+            throws CompilationException {
+        SourceLocation sourceLoc = expr.getSourceLocation();
+        Set<VariableExpr> freeVars = SqlppRewriteUtil.getFreeVariable(expr);
+
+        VariableExpr fromBindingVar = new VariableExpr(context.newVariable());
+        fromBindingVar.setSourceLocation(sourceLoc);
+        FromTerm fromTerm = new FromTerm(groupVar, fromBindingVar, null, null);
+        fromTerm.setSourceLocation(sourceLoc);
+        FromClause fromClause = new 
FromClause(Collections.singletonList(fromTerm));
+        fromClause.setSourceLocation(sourceLoc);
+
+        // 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.containsKey(usedVar)) {
+                // Rewrites to a reference to a field in the group variable.
+                FieldAccessor fa =
+                        new FieldAccessor(fromBindingVar, new 
VarIdentifier(fieldVars.get(usedVar).getValue()));
+                fa.setSourceLocation(usedVar.getSourceLocation());
+                varExprMap.put(usedVar, fa);
+            } else if (outerVars.contains(usedVar)) {
+                // Do nothing
+            } else {
+                // Rewrites to a reference to a single field in the group 
variable.
+                Identifier ident = findField(fieldVars, usedVar, context);
+                FieldAccessor faInner = new FieldAccessor(fromBindingVar, 
ident);
+                faInner.setSourceLocation(usedVar.getSourceLocation());
+                FieldAccessor faOuter =
+                        new FieldAccessor(faInner, 
SqlppVariableUtil.toUserDefinedVariableName(usedVar.getVar()));
+                faOuter.setSourceLocation(usedVar.getSourceLocation());
+                varExprMap.put(usedVar, faOuter);
+            }
+        }
+
+        // Select clause.
+        SelectElement selectElement =
+                new SelectElement(SqlppRewriteUtil.substituteExpression(expr, 
varExprMap, context));
+        selectElement.setSourceLocation(sourceLoc);
+        SelectClause selectClause = new SelectClause(selectElement, null, 
false);
+        selectClause.setSourceLocation(sourceLoc);
+
+        // Construct the select expression.
+        SelectBlock selectBlock = new SelectBlock(selectClause, fromClause, 
null, null, null, null, null);
+        selectBlock.setSourceLocation(sourceLoc);
+        SelectSetOperation selectSetOperation = new SelectSetOperation(new 
SetOperationInput(selectBlock, null), null);
+        selectSetOperation.setSourceLocation(sourceLoc);
+        SelectExpression selectExpr = new SelectExpression(null, 
selectSetOperation, null, null, true);
+        selectExpr.setSourceLocation(sourceLoc);
+        return selectExpr;
+    }
+
+    private static Identifier findField(Map<Expression, Identifier> fieldVars, 
VariableExpr usedVar,
+            LangRewritingContext context) throws CompilationException {
+        Identifier ident = null;
+        for (Map.Entry<Expression, Identifier> me : fieldVars.entrySet()) {
+            Expression fieldVarExpr = me.getKey();
+            if (fieldVarExpr.getKind() == Expression.Kind.VARIABLE_EXPRESSION
+                    && context.isExcludedForFieldAccessVar(((VariableExpr) 
fieldVarExpr).getVar())) {
+                continue;
+            }
+            if (ident != null) {
+                throw new CompilationException(ErrorCode.AMBIGUOUS_IDENTIFIER, 
usedVar.getSourceLocation(),
+                        
SqlppVariableUtil.toUserDefinedVariableName(usedVar.getVar().getValue()).getValue());
+            }
+            ident = me.getValue();
+        }
+        if (ident == null) {
+            throw new CompilationException(ErrorCode.COMPILATION_ERROR, 
usedVar.getSourceLocation());
+        }
+        return ident;
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java
index abfa14e..82284f3 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppBuiltinFunctionRewriteVisitor.java
@@ -31,6 +31,7 @@ import org.apache.asterix.lang.common.expression.OperatorExpr;
 import org.apache.asterix.lang.common.literal.TrueLiteral;
 import org.apache.asterix.lang.common.struct.OperatorType;
 import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
+import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
 import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
 import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
@@ -41,15 +42,16 @@ public class SqlppBuiltinFunctionRewriteVisitor extends 
AbstractSqlppSimpleExpre
     @Override
     public Expression visit(CallExpr callExpr, ILangExpression arg) throws 
CompilationException {
         //TODO(buyingyi): rewrite SQL temporal functions
-        FunctionSignature functionSignature = callExpr.getFunctionSignature();
-        
callExpr.setFunctionSignature(FunctionMapUtil.normalizeBuiltinFunctionSignature(functionSignature,
 true,
-                callExpr.getSourceLocation()));
-        List<Expression> newExprList = new ArrayList<>();
-        for (Expression expr : callExpr.getExprList()) {
-            newExprList.add(expr.accept(this, arg));
-        }
-        callExpr.setExprList(newExprList);
-        return callExpr;
+        
callExpr.setFunctionSignature(FunctionMapUtil.normalizeBuiltinFunctionSignature(callExpr.getFunctionSignature(),
+                true, callExpr.getSourceLocation()));
+        return super.visit(callExpr, arg);
+    }
+
+    @Override
+    public Expression visit(WindowExpression winExpr, ILangExpression arg) 
throws CompilationException {
+        
winExpr.setFunctionSignature(FunctionMapUtil.normalizeBuiltinFunctionSignature(winExpr.getFunctionSignature(),
+                true, winExpr.getSourceLocation()));
+        return super.visit(winExpr, arg);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java
index a73d44e..1c55f99 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByAggregationSugarVisitor.java
@@ -19,42 +19,28 @@
 package org.apache.asterix.lang.sqlpp.rewrites.visitor;
 
 import org.apache.asterix.common.exceptions.CompilationException;
-import org.apache.asterix.common.exceptions.ErrorCode;
-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.clause.OrderbyClause;
-import org.apache.asterix.lang.common.expression.CallExpr;
-import org.apache.asterix.lang.common.expression.FieldAccessor;
 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.FromTerm;
 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.clause.SelectElement;
-import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
-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.SqlppVariableUtil;
 import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;
-import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionVisitor;
-import org.apache.hyracks.algebricks.common.utils.Pair;
-import org.apache.hyracks.api.exceptions.SourceLocation;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -198,11 +184,14 @@ public class SqlppGroupByAggregationSugarVisitor extends 
AbstractSqlppExpression
                 // 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<>();
+                if (groupbyClause.hasDecorList()) {
+                    decorList.addAll(groupbyClause.getDecorPairList());
+                }
                 for (VariableExpr var : decorVars) {
                     decorList.add(new GbyVariableExpressionPair((VariableExpr) 
SqlppRewriteUtil.deepCopy(var),
                             (Expression) SqlppRewriteUtil.deepCopy(var)));
                 }
-                groupbyClause.getDecorPairList().addAll(decorList);
+                groupbyClause.setDecorPairList(decorList);
             }
         } else {
             selectBlock.getSelectClause().accept(this, arg);
@@ -211,110 +200,15 @@ public class SqlppGroupByAggregationSugarVisitor extends 
AbstractSqlppExpression
     }
 
     private Map<Expression, Identifier> getGroupFieldVariables(GroupbyClause 
groupbyClause) {
-        Map<Expression, Identifier> fieldVars = new HashMap<>();
-        for (Pair<Expression, Identifier> groupField : 
groupbyClause.getGroupFieldList()) {
-            fieldVars.put(groupField.first, groupField.second);
-        }
-        return fieldVars;
+        return groupbyClause.hasGroupFieldList()
+                ? 
SqlppVariableUtil.createFieldVariableMap(groupbyClause.getGroupFieldList()) : 
Collections.emptyMap();
     }
 
     // Applying sugar rewriting for group-by.
     private void rewriteExpressionUsingGroupVariable(VariableExpr groupVar, 
Map<Expression, Identifier> fieldVars,
             ILangExpression expr, Set<VariableExpr> outerScopeVariables) 
throws CompilationException {
         Sql92AggregateFunctionVisitor visitor =
-                new Sql92AggregateFunctionVisitor(groupVar, fieldVars, 
outerScopeVariables);
+                new Sql92AggregateFunctionVisitor(context, groupVar, 
fieldVars, outerScopeVariables);
         expr.accept(visitor, null);
     }
-
-    private final class Sql92AggregateFunctionVisitor extends 
AbstractSqlppSimpleExpressionVisitor {
-
-        private final Expression groupVar;
-
-        private final Map<Expression, Identifier> fieldVars;
-
-        private final Collection<VariableExpr> outerVars;
-
-        private Sql92AggregateFunctionVisitor(Expression groupVar, 
Map<Expression, Identifier> fieldVars,
-                Collection<VariableExpr> outerVars) {
-            this.groupVar = groupVar;
-            this.fieldVars = fieldVars;
-            this.outerVars = outerVars;
-        }
-
-        @Override
-        public Expression visit(CallExpr callExpr, ILangExpression arg) throws 
CompilationException {
-            List<Expression> newExprList = new ArrayList<>();
-            FunctionSignature signature = callExpr.getFunctionSignature();
-            boolean aggregate = 
FunctionMapUtil.isSql92AggregateFunction(signature);
-            boolean rewritten = false;
-            for (Expression expr : callExpr.getExprList()) {
-                Expression newExpr = aggregate ? wrapAggregationArgument(expr) 
: expr;
-                rewritten |= newExpr != expr;
-                newExprList.add(newExpr.accept(this, arg));
-            }
-            if (rewritten) {
-                // Rewrites the SQL-92 function name to core functions,
-                // e.g., SUM --> array_sum
-                
callExpr.setFunctionSignature(FunctionMapUtil.sql92ToCoreAggregateFunction(signature));
-            }
-            callExpr.setExprList(newExprList);
-            return callExpr;
-        }
-
-        private Expression wrapAggregationArgument(Expression argExpr) throws 
CompilationException {
-            SourceLocation sourceLoc = argExpr.getSourceLocation();
-            Expression expr = argExpr;
-            Set<VariableExpr> freeVars = 
SqlppRewriteUtil.getFreeVariable(expr);
-
-            VariableExpr fromBindingVar = new 
VariableExpr(context.newVariable());
-            fromBindingVar.setSourceLocation(sourceLoc);
-            FromTerm fromTerm = new FromTerm(groupVar, fromBindingVar, null, 
null);
-            fromTerm.setSourceLocation(sourceLoc);
-            FromClause fromClause = new 
FromClause(Collections.singletonList(fromTerm));
-            fromClause.setSourceLocation(sourceLoc);
-
-            // 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.containsKey(usedVar)) {
-                    // Rewrites to a reference to a field in the group 
variable.
-                    FieldAccessor fa =
-                            new FieldAccessor(fromBindingVar, new 
VarIdentifier(fieldVars.get(usedVar).getValue()));
-                    fa.setSourceLocation(usedVar.getSourceLocation());
-                    varExprMap.put(usedVar, fa);
-                } else if (outerVars.contains(usedVar)) {
-                    // Do nothing
-                } else if (fieldVars.size() == 1) {
-                    // Rewrites to a reference to a single field in the group 
variable.
-                    FieldAccessor faInner = new FieldAccessor(fromBindingVar, 
fieldVars.values().iterator().next());
-                    faInner.setSourceLocation(usedVar.getSourceLocation());
-                    FieldAccessor faOuter =
-                            new FieldAccessor(faInner, 
SqlppVariableUtil.toUserDefinedVariableName(usedVar.getVar()));
-                    faOuter.setSourceLocation(usedVar.getSourceLocation());
-                    varExprMap.put(usedVar, faOuter);
-                } else {
-                    throw new 
CompilationException(ErrorCode.AMBIGUOUS_IDENTIFIER, 
usedVar.getSourceLocation(),
-                            
SqlppVariableUtil.toUserDefinedVariableName(usedVar.getVar().getValue()).getValue());
-                }
-            }
-
-            // Select clause.
-            SelectElement selectElement =
-                    new 
SelectElement(SqlppRewriteUtil.substituteExpression(expr, varExprMap, context));
-            selectElement.setSourceLocation(sourceLoc);
-            SelectClause selectClause = new SelectClause(selectElement, null, 
false);
-            selectClause.setSourceLocation(sourceLoc);
-
-            // Construct the select expression.
-            SelectBlock selectBlock = new SelectBlock(selectClause, 
fromClause, null, null, null, null, null);
-            selectBlock.setSourceLocation(sourceLoc);
-            SelectSetOperation selectSetOperation =
-                    new SelectSetOperation(new SetOperationInput(selectBlock, 
null), null);
-            selectSetOperation.setSourceLocation(sourceLoc);
-            SelectExpression selectExpr = new SelectExpression(null, 
selectSetOperation, null, null, true);
-            selectExpr.setSourceLocation(sourceLoc);
-            return selectExpr;
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/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 faca85e..84aee71 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
@@ -34,7 +34,6 @@ import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppSimpleExpressionV
 import org.apache.hyracks.algebricks.common.utils.Pair;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 
@@ -123,19 +122,14 @@ public class SqlppGroupByVisitor extends 
AbstractSqlppSimpleExpressionVisitor {
 
     private List<Pair<Expression, Identifier>> 
createGroupFieldList(SelectBlock selectBlock) {
         List<Pair<Expression, Identifier>> groupFieldList = new ArrayList<>();
-        addToGroupFieldList(groupFieldList, 
SqlppVariableUtil.getBindingVariables(selectBlock.getFromClause()));
-        addToGroupFieldList(groupFieldList, 
SqlppVariableUtil.getBindingVariables(selectBlock.getLetList()));
+        addToFieldList(groupFieldList, 
SqlppVariableUtil.getBindingVariables(selectBlock.getFromClause()));
+        addToFieldList(groupFieldList, 
SqlppVariableUtil.getBindingVariables(selectBlock.getLetList()));
         return groupFieldList;
     }
 
-    private void addToGroupFieldList(List<Pair<Expression, Identifier>> 
groupFieldList,
-            Collection<VariableExpr> fromBindingVars) {
-        for (VariableExpr varExpr : fromBindingVars) {
-            VariableExpr newVarExpr = new VariableExpr(varExpr.getVar());
-            newVarExpr.setSourceLocation(varExpr.getSourceLocation());
-            Pair<Expression, Identifier> varIdPair =
-                    new Pair<>(newVarExpr, 
SqlppVariableUtil.toUserDefinedVariableName(varExpr.getVar()));
-            groupFieldList.add(varIdPair);
+    private void addToFieldList(List<Pair<Expression, Identifier>> 
outFieldList, List<VariableExpr> varList) {
+        for (VariableExpr varExpr : varList) {
+            SqlppVariableUtil.addToFieldVariableList(varExpr, outFieldList);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/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 0ffb590..1fd4ff7 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
@@ -28,6 +28,7 @@ import org.apache.asterix.lang.common.base.IRewriterFactory;
 import org.apache.asterix.lang.common.clause.LetClause;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.visitor.AbstractInlineUdfsVisitor;
 import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
 import org.apache.asterix.lang.sqlpp.clause.FromClause;
@@ -247,16 +248,35 @@ public class SqlppInlineUdfsVisitor extends 
AbstractInlineUdfsVisitor
 
     @Override
     public Boolean visit(WindowExpression winExpr, List<FunctionDecl> funcs) 
throws CompilationException {
-        Pair<Boolean, Expression> result = inlineUdfsInExpr(winExpr.getExpr(), 
funcs);
-        winExpr.setExpr(result.second);
-        boolean inlined = result.first;
+        boolean inlined = false;
         if (winExpr.hasPartitionList()) {
             Pair<Boolean, List<Expression>> inlinedList = 
inlineUdfsInExprList(winExpr.getPartitionList(), funcs);
             winExpr.setPartitionList(inlinedList.second);
+            inlined = inlinedList.first;
+        }
+        if (winExpr.hasOrderByList()) {
+            Pair<Boolean, List<Expression>> inlinedList = 
inlineUdfsInExprList(winExpr.getOrderbyList(), funcs);
+            winExpr.setOrderbyList(inlinedList.second);
+            inlined |= inlinedList.first;
+        }
+        if (winExpr.hasFrameStartExpr()) {
+            Pair<Boolean, Expression> inlinedExpr = 
inlineUdfsInExpr(winExpr.getFrameStartExpr(), funcs);
+            winExpr.setFrameStartExpr(inlinedExpr.second);
+            inlined |= inlinedExpr.first;
+        }
+        if (winExpr.hasFrameEndExpr()) {
+            Pair<Boolean, Expression> inlinedExpr = 
inlineUdfsInExpr(winExpr.getFrameEndExpr(), funcs);
+            winExpr.setFrameEndExpr(inlinedExpr.second);
+            inlined |= inlinedExpr.first;
+        }
+        if (winExpr.hasWindowFieldList()) {
+            Pair<Boolean, List<Pair<Expression, Identifier>>> inlinedList =
+                    inlineUdfsInFieldList(winExpr.getWindowFieldList(), funcs);
+            winExpr.setWindowFieldList(inlinedList.second);
             inlined |= inlinedList.first;
         }
-        Pair<Boolean, List<Expression>> inlinedList = 
inlineUdfsInExprList(winExpr.getOrderbyList(), funcs);
-        winExpr.setOrderbyList(inlinedList.second);
+        Pair<Boolean, List<Expression>> inlinedList = 
inlineUdfsInExprList(winExpr.getExprList(), funcs);
+        winExpr.setExprList(inlinedList.second);
         inlined |= inlinedList.first;
         return inlined;
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowAggregationSugarVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowAggregationSugarVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowAggregationSugarVisitor.java
new file mode 100644
index 0000000..fa40d78
--- /dev/null
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowAggregationSugarVisitor.java
@@ -0,0 +1,138 @@
+/*
+ * 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.rewrites.visitor;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+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.VariableExpr;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.struct.Identifier;
+import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
+import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
+import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
+import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
+import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+/**
+ * A pre-processor that adds a window field list into the AST:
+ *
+ * <pre>
+ * FROM ... AS e, ... AS i
+ * SELECT fn() OVER (...)
+ * ->
+ * FROM ... AS e, ... AS i
+ * SELECT fn() AS w(e AS e, i AS i) OVER (...)
+ * </pre>
+ *
+ * Also rewrites SQL-92 aggregate functions inside window expressions into 
SQL++ core aggregate functions
+ * using the same approach as {@link SqlppGroupByAggregationSugarVisitor}
+ * <br/>
+ * Must be executed after {@link VariableCheckAndRewriteVisitor}
+ */
+public class SqlppWindowAggregationSugarVisitor extends 
AbstractSqlppExpressionScopingVisitor {
+
+    private final Deque<SelectBlock> stack = new ArrayDeque<>();
+
+    public SqlppWindowAggregationSugarVisitor(LangRewritingContext context) {
+        super(context);
+    }
+
+    @Override
+    public Expression visit(SelectBlock selectBlock, ILangExpression arg) 
throws CompilationException {
+        stack.push(selectBlock);
+        Expression expr = super.visit(selectBlock, arg);
+        stack.pop();
+        return expr;
+    }
+
+    @Override
+    public Expression visit(WindowExpression winExpr, ILangExpression arg) 
throws CompilationException {
+        if (!winExpr.hasWindowFieldList()) {
+            SelectBlock selectBlock = stack.peek();
+            List<Pair<Expression, Identifier>> winFieldList = 
createWindowFieldList(selectBlock);
+            winExpr.setWindowFieldList(winFieldList);
+        }
+
+        FunctionSignature signature = winExpr.getFunctionSignature();
+        FunctionIdentifier winfi = 
FunctionMapUtil.getInternalWindowFunction(signature);
+        if (winfi != null) {
+            winExpr.setFunctionSignature(new FunctionSignature(winfi));
+            if (BuiltinFunctions.windowFunctionWithListArg(winfi)) {
+                wrapAggregationArguments(winExpr, 1);
+            }
+        } else if (FunctionMapUtil.isSql92AggregateFunction(signature)) {
+            
winExpr.setFunctionSignature(FunctionMapUtil.sql92ToCoreAggregateFunction(signature));
+            wrapAggregationArguments(winExpr, winExpr.getExprList().size());
+        }
+
+        return super.visit(winExpr, arg);
+    }
+
+    private void wrapAggregationArguments(WindowExpression winExpr, int limit) 
throws CompilationException {
+        Set<VariableExpr> liveVars = 
scopeChecker.getCurrentScope().getLiveVariables();
+
+        VariableExpr winVar = winExpr.getWindowVar();
+        List<Pair<Expression, Identifier>> winFieldList = 
winExpr.getWindowFieldList();
+        Map<Expression, Identifier> fieldMap = 
SqlppVariableUtil.createFieldVariableMap(winFieldList);
+
+        List<Expression> exprList = winExpr.getExprList();
+        int n = exprList.size();
+        List<Expression> newExprList = new ArrayList<>(n);
+        for (int i = 0; i < n; i++) {
+            Expression expr = exprList.get(i);
+            Expression newExpr = i < limit
+                    ? 
Sql92AggregateFunctionVisitor.wrapAggregationArgument(expr, winVar, fieldMap, 
liveVars, context)
+                    : expr;
+            newExprList.add(newExpr);
+        }
+        winExpr.setExprList(newExprList);
+    }
+
+    private List<Pair<Expression, Identifier>> 
createWindowFieldList(SelectBlock selectBlock) {
+        List<Pair<Expression, Identifier>> fieldList = new ArrayList<>();
+        if (selectBlock != null) {
+            addToFieldList(fieldList, 
SqlppVariableUtil.getBindingVariables(selectBlock.getFromClause()));
+            addToFieldList(fieldList, 
SqlppVariableUtil.getBindingVariables(selectBlock.getLetList()));
+            addToFieldList(fieldList, 
SqlppVariableUtil.getBindingVariables(selectBlock.getGroupbyClause()));
+            addToFieldList(fieldList, 
SqlppVariableUtil.getBindingVariables(selectBlock.getLetListAfterGroupby()));
+        }
+        return fieldList;
+    }
+
+    private void addToFieldList(List<Pair<Expression, Identifier>> 
outFieldList, List<VariableExpr> varList) {
+        for (VariableExpr varExpr : varList) {
+            if (scopeChecker.lookupSymbol(varExpr.getVar().getValue()) != 
null) {
+                SqlppVariableUtil.addToFieldVariableList(varExpr, 
outFieldList);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowRewriteVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowRewriteVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowRewriteVisitor.java
new file mode 100644
index 0000000..cd0e151
--- /dev/null
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppWindowRewriteVisitor.java
@@ -0,0 +1,97 @@
+/*
+ * 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.rewrites.visitor;
+
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
+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.VariableExpr;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
+import org.apache.asterix.lang.sqlpp.clause.FromClause;
+import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
+import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+/**
+ * A pre-processor that transforms window expressions as follows:
+ * <ul>
+ * <li>adds window frame variable</li>
+ * <li>extracts list arguments of window functions into separate LET 
clauses</li>
+ * </ul>
+ *
+ * Must be executed before {@link VariableCheckAndRewriteVisitor}
+ */
+public final class SqlppWindowRewriteVisitor extends 
AbstractSqlppExpressionExtractionVisitor {
+
+    public SqlppWindowRewriteVisitor(LangRewritingContext context) {
+        super(context);
+    }
+
+    @Override
+    public Expression visit(WindowExpression winExpr, ILangExpression arg) 
throws CompilationException {
+        super.visit(winExpr, arg);
+
+        if (!winExpr.hasWindowVar()) {
+            VariableExpr winVar = new VariableExpr(context.newVariable());
+            winVar.setSourceLocation(winExpr.getSourceLocation());
+            winExpr.setWindowVar(winVar);
+        }
+
+        FunctionSignature signature = winExpr.getFunctionSignature();
+        FunctionIdentifier winfi = 
FunctionMapUtil.getInternalWindowFunction(signature);
+        if (winfi != null) {
+            if (BuiltinFunctions.windowFunctionWithListArg(winfi)) {
+                List<Expression> newExprList =
+                        extractExpressions(winExpr.getExprList(), 1, 
winExpr.getSourceLocation());
+                winExpr.setExprList(newExprList);
+            }
+        } else if (FunctionMapUtil.isSql92AggregateFunction(signature)) {
+            List<Expression> newExprList = 
extractExpressions(winExpr.getExprList(), winExpr.getExprList().size(),
+                    winExpr.getSourceLocation());
+            winExpr.setExprList(newExprList);
+        }
+
+        return winExpr;
+    }
+
+    @Override
+    protected boolean isExtractableExpression(Expression expr) {
+        switch (expr.getKind()) {
+            case LITERAL_EXPRESSION:
+            case VARIABLE_EXPRESSION:
+                return false;
+            default:
+                return true;
+        }
+    }
+
+    @Override
+    void handleUnsupportedClause(FromClause clause, List<Pair<Expression, 
VarIdentifier>> extractionList)
+            throws CompilationException {
+        throw new 
CompilationException(ErrorCode.COMPILATION_UNEXPECTED_WINDOW_EXPRESSION, 
clause.getSourceLocation());
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/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 8bac4ad..b48e024 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,6 +20,7 @@ package org.apache.asterix.lang.sqlpp.rewrites.visitor;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -37,6 +38,7 @@ import org.apache.asterix.lang.common.literal.StringLiteral;
 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.expression.WindowExpression;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
 import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
 import org.apache.asterix.lang.sqlpp.visitor.CheckDatasetOnlyResolutionVisitor;
@@ -45,6 +47,7 @@ import org.apache.asterix.metadata.declared.MetadataProvider;
 import org.apache.asterix.om.functions.BuiltinFunctions;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import org.apache.hyracks.api.exceptions.SourceLocation;
 
 public class VariableCheckAndRewriteVisitor extends 
AbstractSqlppExpressionScopingVisitor {
@@ -201,7 +204,6 @@ public class VariableCheckAndRewriteVisitor extends 
AbstractSqlppExpressionScopi
         return path.length == 2 && metadataProvider.findDataset(path[0], 
path[1]) != null;
     }
 
-    @Override
     public Expression visit(CallExpr callExpr, ILangExpression arg) throws 
CompilationException {
         // skip variables inside SQL-92 aggregates (they will be resolved by 
SqlppGroupByAggregationSugarVisitor)
         if 
(FunctionMapUtil.isSql92AggregateFunction(callExpr.getFunctionSignature())) {
@@ -209,4 +211,29 @@ public class VariableCheckAndRewriteVisitor extends 
AbstractSqlppExpressionScopi
         }
         return super.visit(callExpr, arg);
     }
+
+    @Override
+    public Expression visit(WindowExpression winExpr, ILangExpression arg) 
throws CompilationException {
+        // skip variables inside list arguments of window functions (will be 
resolved by SqlppWindowExpressionVisitor)
+        FunctionSignature fs = winExpr.getFunctionSignature();
+        FunctionIdentifier winfi = 
FunctionMapUtil.getInternalWindowFunction(fs);
+        if (winfi != null) {
+            if (BuiltinFunctions.windowFunctionWithListArg(winfi)) {
+                visitWindowExpressionExcludingExprList(winExpr, arg);
+                List<Expression> exprList = winExpr.getExprList();
+                List<Expression> newExprList = new 
ArrayList<>(exprList.size());
+                Iterator<Expression> i = exprList.iterator();
+                newExprList.add(i.next()); // don't visit the list arg
+                while (i.hasNext()) {
+                    newExprList.add(visit(i.next(), arg));
+                }
+                winExpr.setExprList(newExprList);
+                return winExpr;
+            }
+        } else if (FunctionMapUtil.isSql92AggregateFunction(fs)) {
+            visitWindowExpressionExcludingExprList(winExpr, arg);
+            return winExpr;
+        }
+        return super.visit(winExpr, arg);
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/FunctionMapUtil.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/FunctionMapUtil.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/FunctionMapUtil.java
index 7773072..a6fa730 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/FunctionMapUtil.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/FunctionMapUtil.java
@@ -63,7 +63,7 @@ public class FunctionMapUtil {
      * @return true if the function signature is a SQL-92 core aggregate,
      *         false otherwise.
      */
-    public static boolean isSql92AggregateFunction(FunctionSignature 
signature) throws CompilationException {
+    public static boolean isSql92AggregateFunction(FunctionSignature 
signature) {
         IFunctionInfo finfo = FunctionUtil.getFunctionInfo(new 
FunctionIdentifier(FunctionConstants.ASTERIX_NS,
                 signature.getName().toLowerCase(), signature.getArity()));
         if (finfo == null) {
@@ -78,9 +78,8 @@ public class FunctionMapUtil {
      * @param fs,
      *            the SQL-92 aggregate function signature.
      * @return the SQL++ aggregate function signature.
-     * @throws CompilationException
      */
-    public static FunctionSignature 
sql92ToCoreAggregateFunction(FunctionSignature fs) throws CompilationException {
+    public static FunctionSignature 
sql92ToCoreAggregateFunction(FunctionSignature fs) {
         if (!isSql92AggregateFunction(fs)) {
             return fs;
         }
@@ -110,11 +109,15 @@ public class FunctionMapUtil {
             if (finfo != null && 
BuiltinFunctions.getAggregateFunction(finfo.getFunctionIdentifier()) != null) {
                 return new FunctionSignature(FunctionConstants.ASTERIX_NS, 
internalName, fs.getArity());
             }
-        } else if (checkSql92Aggregate && isSql92AggregateFunction(fs)) {
-            throw new CompilationException(ErrorCode.COMPILATION_ERROR, 
sourceLoc,
-                    fs.getName() + " is a SQL-92 aggregate function. The SQL++ 
core aggregate function "
-                            + CORE_SQL_AGGREGATE_PREFIX + 
fs.getName().toLowerCase()
-                            + " could potentially express the intent.");
+        } else if (checkSql92Aggregate) {
+            if (isSql92AggregateFunction(fs)) {
+                throw new CompilationException(ErrorCode.COMPILATION_ERROR, 
sourceLoc,
+                        fs.getName() + " is a SQL-92 aggregate function. The 
SQL++ core aggregate function "
+                                + CORE_SQL_AGGREGATE_PREFIX + 
fs.getName().toLowerCase()
+                                + " could potentially express the intent.");
+            } else if (getInternalWindowFunction(fs) != null) {
+                throw new 
CompilationException(ErrorCode.COMPILATION_UNEXPECTED_WINDOW_EXPRESSION, 
sourceLoc);
+            }
         }
         String mappedName = 
CommonFunctionMapUtil.normalizeBuiltinFunctionSignature(fs).getName();
         return new FunctionSignature(fs.getNamespace(), mappedName, 
fs.getArity());
@@ -160,4 +163,16 @@ public class FunctionMapUtil {
             return null;
         }
     }
+
+    /**
+     * Returns an internal implementation function for a public window 
function,
+     * or {@code null} if given function is not a public window function
+     * @param signature function signature
+     * @return said value
+     */
+    public static FunctionIdentifier 
getInternalWindowFunction(FunctionSignature signature) {
+        IFunctionInfo finfo = FunctionUtil.getFunctionInfo(new 
FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+                signature.getName().toLowerCase(), signature.getArity()));
+        return finfo != null ? 
BuiltinFunctions.getWindowFunction(finfo.getFunctionIdentifier()) : null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/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 14dfaeb..8fabf13 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
@@ -21,20 +21,27 @@ package org.apache.asterix.lang.sqlpp.util;
 import java.util.ArrayList;
 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;
 
 import org.apache.asterix.common.exceptions.CompilationException;
+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.expression.GbyVariableExpressionPair;
 import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.struct.Identifier;
 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;
+import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
 import org.apache.asterix.lang.sqlpp.visitor.FreeVariableVisitor;
+import org.apache.hyracks.algebricks.common.utils.Pair;
 
 public class SqlppVariableUtil {
 
@@ -96,14 +103,14 @@ public class SqlppVariableUtil {
         return isExternalVariableIdentifier(varExpr.getVar());
     }
 
-    public static Collection<VariableExpr> getFreeVariables(ILangExpression 
langExpr) throws CompilationException {
-        Collection<VariableExpr> freeVars = new HashSet<>();
+    public static Set<VariableExpr> getFreeVariables(ILangExpression langExpr) 
throws CompilationException {
+        Set<VariableExpr> freeVars = new HashSet<>();
         FreeVariableVisitor visitor = new FreeVariableVisitor();
         langExpr.accept(visitor, freeVars);
         return freeVars;
     }
 
-    public static Collection<VariableExpr> getBindingVariables(FromClause 
fromClause) {
+    public static List<VariableExpr> getBindingVariables(FromClause 
fromClause) {
         if (fromClause == null) {
             return Collections.emptyList();
         }
@@ -114,7 +121,7 @@ public class SqlppVariableUtil {
         return bindingVars;
     }
 
-    public static Collection<VariableExpr> getBindingVariables(FromTerm 
fromTerm) {
+    public static List<VariableExpr> getBindingVariables(FromTerm fromTerm) {
         List<VariableExpr> bindingVars = new ArrayList<>();
         if (fromTerm == null) {
             return bindingVars;
@@ -132,7 +139,7 @@ public class SqlppVariableUtil {
         return bindingVars;
     }
 
-    public static Collection<VariableExpr> getBindingVariables(GroupbyClause 
gbyClause) {
+    public static List<VariableExpr> getBindingVariables(GroupbyClause 
gbyClause) {
         List<VariableExpr> bindingVars = new ArrayList<>();
         if (gbyClause == null) {
             return bindingVars;
@@ -143,10 +150,12 @@ public class SqlppVariableUtil {
                 bindingVars.add(var);
             }
         }
-        for (GbyVariableExpressionPair gbyKey : gbyClause.getDecorPairList()) {
-            VariableExpr var = gbyKey.getVar();
-            if (var != null) {
-                bindingVars.add(var);
+        if (gbyClause.hasDecorList()) {
+            for (GbyVariableExpressionPair gbyKey : 
gbyClause.getDecorPairList()) {
+                VariableExpr var = gbyKey.getVar();
+                if (var != null) {
+                    bindingVars.add(var);
+                }
             }
         }
         if (gbyClause.hasWithMap()) {
@@ -156,7 +165,7 @@ public class SqlppVariableUtil {
         return bindingVars;
     }
 
-    public static Collection<VariableExpr> getBindingVariables(List<LetClause> 
letClauses) {
+    public static List<VariableExpr> getBindingVariables(List<LetClause> 
letClauses) {
         List<VariableExpr> bindingVars = new ArrayList<>();
         if (letClauses == null || letClauses.isEmpty()) {
             return bindingVars;
@@ -167,4 +176,18 @@ public class SqlppVariableUtil {
         return bindingVars;
     }
 
+    public static Map<Expression, Identifier> 
createFieldVariableMap(List<Pair<Expression, Identifier>> fieldList) {
+        Map<Expression, Identifier> fieldVars = new HashMap<>();
+        for (Pair<Expression, Identifier> p : fieldList) {
+            fieldVars.put(p.first, p.second);
+        }
+        return fieldVars;
+    }
+
+    public static void addToFieldVariableList(VariableExpr varExpr, 
List<Pair<Expression, Identifier>> outFieldList) {
+        VarIdentifier var = varExpr.getVar();
+        VariableExpr newVarExpr = new VariableExpr(var);
+        newVarExpr.setSourceLocation(varExpr.getSourceLocation());
+        outFieldList.add(new Pair<>(newVarExpr, 
toUserDefinedVariableName(var)));
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/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 6caf0f6..2caaa0c 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
@@ -44,6 +44,7 @@ import org.apache.asterix.lang.common.expression.UnaryExpr;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 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.sqlpp.clause.FromClause;
 import org.apache.asterix.lang.sqlpp.clause.FromTerm;
 import org.apache.asterix.lang.sqlpp.clause.HavingClause;
@@ -61,12 +62,16 @@ import 
org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
 import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppQueryExpressionVisitor;
+import org.apache.hyracks.algebricks.common.utils.Pair;
 
 /**
  * This visitor checks if a non-subquery language construct contains SQL-92 
aggregates.
  */
 public class CheckSql92AggregateVisitor extends 
AbstractSqlppQueryExpressionVisitor<Boolean, ILangExpression> {
 
+    public CheckSql92AggregateVisitor() {
+    }
+
     @Override
     public Boolean visit(Query q, ILangExpression parentSelectBlock) throws 
CompilationException {
         return false;
@@ -289,7 +294,23 @@ public class CheckSql92AggregateVisitor extends 
AbstractSqlppQueryExpressionVisi
         return false;
     }
 
-    private Boolean visitExprList(List<Expression> exprs, ILangExpression 
parentSelectBlock)
+    @Override
+    public Boolean visit(CaseExpression caseExpr, ILangExpression arg) throws 
CompilationException {
+        return caseExpr.getConditionExpr().accept(this, arg) || 
visitExprList(caseExpr.getWhenExprs(), arg)
+                || visitExprList(caseExpr.getThenExprs(), arg) || 
caseExpr.getElseExpr().accept(this, arg);
+    }
+
+    @Override
+    public Boolean visit(WindowExpression winExpr, ILangExpression arg) throws 
CompilationException {
+        return (winExpr.hasPartitionList() && 
visitExprList(winExpr.getPartitionList(), arg))
+                || (winExpr.hasOrderByList() && 
visitExprList(winExpr.getOrderbyList(), arg))
+                || (winExpr.hasFrameStartExpr() && 
winExpr.getFrameStartExpr().accept(this, arg))
+                || (winExpr.hasFrameEndExpr() && 
winExpr.getFrameEndExpr().accept(this, arg))
+                || (winExpr.hasWindowFieldList() && 
visitFieldList(winExpr.getWindowFieldList(), arg))
+                || visitExprList(winExpr.getExprList(), arg);
+    }
+
+    private boolean visitExprList(List<Expression> exprs, ILangExpression 
parentSelectBlock)
             throws CompilationException {
         for (Expression item : exprs) {
             if (item.accept(this, parentSelectBlock)) {
@@ -299,16 +320,13 @@ public class CheckSql92AggregateVisitor extends 
AbstractSqlppQueryExpressionVisi
         return false;
     }
 
-    @Override
-    public Boolean visit(CaseExpression caseExpr, ILangExpression arg) throws 
CompilationException {
-        return caseExpr.getConditionExpr().accept(this, arg) || 
visitExprList(caseExpr.getWhenExprs(), arg)
-                || visitExprList(caseExpr.getThenExprs(), arg) || 
caseExpr.getElseExpr().accept(this, arg);
-    }
-
-    @Override
-    public Boolean visit(WindowExpression winExpr, ILangExpression arg) throws 
CompilationException {
-        return winExpr.getExpr().accept(this, arg)
-                || (winExpr.hasPartitionList() && 
visitExprList(winExpr.getPartitionList(), arg))
-                || visitExprList(winExpr.getOrderbyList(), arg);
+    private boolean visitFieldList(List<Pair<Expression, Identifier>> 
fieldList, ILangExpression parentSelectBlock)
+            throws CompilationException {
+        for (Pair<Expression, Identifier> p : fieldList) {
+            if (p.first.accept(this, parentSelectBlock)) {
+                return true;
+            }
+        }
+        return false;
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
index e1647ea..c816d05 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSubqueryVisitor.java
@@ -19,6 +19,7 @@
 
 package org.apache.asterix.lang.sqlpp.visitor;
 
+import java.util.Collection;
 import java.util.List;
 
 import org.apache.asterix.common.exceptions.CompilationException;
@@ -117,8 +118,8 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
     public Boolean visit(SelectBlock selectBlock, ILangExpression arg) throws 
CompilationException {
         boolean hasSubquery = visit(selectBlock.getFromClause(), arg) || 
visit(selectBlock.getGroupbyClause(), arg)
                 || visit(selectBlock.getHavingClause(), arg) || 
visit(selectBlock.getWhereClause(), arg);
-        return hasSubquery || visit(selectBlock.getSelectClause(), arg) || 
visit(selectBlock.getLetList(), arg)
-                || visit(selectBlock.getLetListAfterGroupby(), arg);
+        return hasSubquery || visit(selectBlock.getSelectClause(), arg) || 
visitExprList(selectBlock.getLetList(), arg)
+                || visitExprList(selectBlock.getLetListAfterGroupby(), arg);
     }
 
     @Override
@@ -133,7 +134,7 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
 
     @Override
     public Boolean visit(SelectRegular selectRegular, ILangExpression arg) 
throws CompilationException {
-        return visit(selectRegular.getProjections(), arg);
+        return visitExprList(selectRegular.getProjections(), arg);
     }
 
     @Override
@@ -154,7 +155,7 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
         if (selectStatement.isSubquery()) {
             return true;
         }
-        return visit(selectStatement.getLetList(), arg) || 
visit(selectStatement.getSelectSetOperation(), arg)
+        return visitExprList(selectStatement.getLetList(), arg) || 
visit(selectStatement.getSelectSetOperation(), arg)
                 || visit(selectStatement.getOrderbyClause(), arg) || 
visit(selectStatement.getLimitClause(), arg);
 
     }
@@ -171,8 +172,8 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
 
     @Override
     public Boolean visit(CaseExpression caseExpression, ILangExpression arg) 
throws CompilationException {
-        return visit(caseExpression.getConditionExpr(), arg) || 
visit(caseExpression.getWhenExprs(), arg)
-                || visit(caseExpression.getThenExprs(), arg) || 
visit(caseExpression.getElseExpr(), arg);
+        return visit(caseExpression.getConditionExpr(), arg) || 
visitExprList(caseExpression.getWhenExprs(), arg)
+                || visitExprList(caseExpression.getThenExprs(), arg) || 
visit(caseExpression.getElseExpr(), arg);
     }
 
     @Override
@@ -197,7 +198,7 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
 
     @Override
     public Boolean visit(ListConstructor lc, ILangExpression arg) throws 
CompilationException {
-        return visit(lc.getExprList(), arg);
+        return visitExprList(lc.getExprList(), arg);
     }
 
     @Override
@@ -215,7 +216,7 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
 
     @Override
     public Boolean visit(OperatorExpr operatorExpr, ILangExpression arg) 
throws CompilationException {
-        return visit(operatorExpr.getExprList(), arg);
+        return visitExprList(operatorExpr.getExprList(), arg);
     }
 
     @Override
@@ -261,7 +262,7 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
 
     @Override
     public Boolean visit(OrderbyClause oc, ILangExpression arg) throws 
CompilationException {
-        return visit(oc.getOrderbyList(), arg);
+        return visitExprList(oc.getOrderbyList(), arg);
     }
 
     @Override
@@ -271,15 +272,18 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
                 return true;
             }
         }
-        for (GbyVariableExpressionPair key : gc.getDecorPairList()) {
-            if (visit(key.getExpr(), arg)) {
-                return true;
+        if (gc.hasDecorList()) {
+            for (GbyVariableExpressionPair key : gc.getDecorPairList()) {
+                if (visit(key.getExpr(), arg)) {
+                    return true;
+                }
             }
         }
-        for (Pair<Expression, Identifier> field : gc.getGroupFieldList()) {
-            if (visit(field.first, arg)) {
-                return true;
-            }
+        if (gc.hasGroupFieldList() && visitFieldList(gc.getGroupFieldList(), 
arg)) {
+            return true;
+        }
+        if (gc.hasWithMap() && visitExprList(gc.getWithVarMap().keySet(), 
arg)) {
+            return true;
         }
         return false;
     }
@@ -296,29 +300,43 @@ public class CheckSubqueryVisitor extends 
AbstractSqlppQueryExpressionVisitor<Bo
 
     @Override
     public Boolean visit(WindowExpression winExpr, ILangExpression arg) throws 
CompilationException {
-        return visit(winExpr.getExpr(), arg) || (winExpr.hasPartitionList() && 
visit(winExpr.getPartitionList(), arg))
-                || visit(winExpr.getOrderbyList(), arg);
+        return (winExpr.hasPartitionList() && 
visitExprList(winExpr.getPartitionList(), arg))
+                || (winExpr.hasOrderByList() && 
visitExprList(winExpr.getOrderbyList(), arg))
+                || (winExpr.hasFrameStartExpr() && 
visit(winExpr.getFrameStartExpr(), arg))
+                || (winExpr.hasFrameEndExpr() && 
visit(winExpr.getFrameEndExpr(), arg))
+                || (winExpr.hasWindowFieldList() && 
visitFieldList(winExpr.getWindowFieldList(), arg))
+                || visitExprList(winExpr.getExprList(), arg);
     }
 
     @Override
     public Boolean visit(CallExpr callExpr, ILangExpression arg) throws 
CompilationException {
-        return visit(callExpr.getExprList(), arg);
+        return visitExprList(callExpr.getExprList(), arg);
     }
 
-    private boolean visit(List<?> langExprs, ILangExpression arg) throws 
CompilationException {
-        for (Object o : langExprs) {
-            ILangExpression langExpr = (ILangExpression) o;
-            if (langExpr.accept(this, arg)) {
+    private boolean visit(ILangExpression expr, ILangExpression arg) throws 
CompilationException {
+        if (expr == null) {
+            return false;
+        }
+        return expr.accept(this, arg);
+    }
+
+    private <T extends ILangExpression> boolean visitExprList(Collection<T> 
exprList, ILangExpression arg)
+            throws CompilationException {
+        for (T langExpr : exprList) {
+            if (visit(langExpr, arg)) {
                 return true;
             }
         }
         return false;
     }
 
-    private boolean visit(ILangExpression langExpr, ILangExpression arg) 
throws CompilationException {
-        if (langExpr == null) {
-            return false;
+    private <T extends ILangExpression> boolean 
visitFieldList(Collection<Pair<T, Identifier>> fieldList,
+            ILangExpression arg) throws CompilationException {
+        for (Pair<T, Identifier> p : fieldList) {
+            if (visit(p.first, arg)) {
+                return true;
+            }
         }
-        return langExpr.accept(this, arg);
+        return false;
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/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 90cfab9..ed92bfd 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
@@ -293,30 +293,32 @@ public class DeepCopyVisitor extends 
AbstractSqlppQueryExpressionVisitor<ILangEx
     @Override
     public GroupbyClause visit(GroupbyClause gc, Void arg) throws 
CompilationException {
         List<GbyVariableExpressionPair> gbyPairList = new ArrayList<>();
-        List<GbyVariableExpressionPair> decorPairList = new ArrayList<>();
-        Map<Expression, VariableExpr> withVarMap = new HashMap<>();
-        VariableExpr groupVarExpr = null;
-        List<Pair<Expression, Identifier>> groupFieldList = new ArrayList<>();
         for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
             VariableExpr var = gbyVarExpr.getVar();
             gbyPairList.add(new GbyVariableExpressionPair(var == null ? null : 
(VariableExpr) var.accept(this, arg),
                     (Expression) gbyVarExpr.getExpr().accept(this, arg)));
         }
-        for (GbyVariableExpressionPair gbyVarExpr : gc.getDecorPairList()) {
-            VariableExpr var = gbyVarExpr.getVar();
-            decorPairList.add(new GbyVariableExpressionPair(var == null ? null 
: (VariableExpr) var.accept(this, arg),
-                    (Expression) gbyVarExpr.getExpr().accept(this, arg)));
+        List<GbyVariableExpressionPair> decorPairList = new ArrayList<>();
+        if (gc.hasDecorList()) {
+            for (GbyVariableExpressionPair gbyVarExpr : gc.getDecorPairList()) 
{
+                VariableExpr var = gbyVarExpr.getVar();
+                decorPairList
+                        .add(new GbyVariableExpressionPair(var == null ? null 
: (VariableExpr) var.accept(this, arg),
+                                (Expression) gbyVarExpr.getExpr().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));
+        Map<Expression, VariableExpr> withVarMap = new HashMap<>();
+        if (gc.hasWithMap()) {
+            for (Entry<Expression, VariableExpr> entry : 
gc.getWithVarMap().entrySet()) {
+                withVarMap.put((Expression) entry.getKey().accept(this, arg),
+                        (VariableExpr) entry.getValue().accept(this, arg));
+            }
         }
+        VariableExpr groupVarExpr = null;
         if (gc.hasGroupVar()) {
             groupVarExpr = (VariableExpr) gc.getGroupVar().accept(this, arg);
         }
-        for (Pair<Expression, Identifier> field : gc.getGroupFieldList()) {
-            groupFieldList.add(new Pair<>((Expression) 
field.first.accept(this, arg), field.second));
-        }
+        List<Pair<Expression, Identifier>> groupFieldList = 
copyFieldList(gc.getGroupFieldList(), arg);
         GroupbyClause copy = new GroupbyClause(gbyPairList, decorPairList, 
withVarMap, groupVarExpr, groupFieldList,
                 gc.hasHashGroupByHint(), gc.isGroupAll());
         copy.setSourceLocation(gc.getSourceLocation());
@@ -515,12 +517,24 @@ public class DeepCopyVisitor extends 
AbstractSqlppQueryExpressionVisitor<ILangEx
 
     @Override
     public ILangExpression visit(WindowExpression winExpr, Void arg) throws 
CompilationException {
-        Expression newExpr = (Expression) winExpr.getExpr().accept(this, arg);
+        List<Expression> newExprList = copyExprList(winExpr.getExprList(), 
arg);
         List<Expression> newPartitionList =
                 winExpr.hasPartitionList() ? 
copyExprList(winExpr.getPartitionList(), arg) : null;
-        List<Expression> newOrderbyList = 
copyExprList(winExpr.getOrderbyList(), arg);
-        List<OrderbyClause.OrderModifier> newOrderbyModifierList = new 
ArrayList<>(winExpr.getOrderbyModifierList());
-        WindowExpression copy = new WindowExpression(newExpr, 
newPartitionList, newOrderbyList, newOrderbyModifierList);
+        List<Expression> newOrderbyList = winExpr.hasOrderByList() ? 
copyExprList(winExpr.getOrderbyList(), arg) : null;
+        List<OrderbyClause.OrderModifier> newOrderbyModifierList =
+                winExpr.hasOrderByList() ? new 
ArrayList<>(winExpr.getOrderbyModifierList()) : null;
+        Expression newFrameStartExpr =
+                winExpr.hasFrameStartExpr() ? (Expression) 
winExpr.getFrameStartExpr().accept(this, arg) : null;
+        Expression newFrameEndExpr =
+                winExpr.hasFrameEndExpr() ? (Expression) 
winExpr.getFrameEndExpr().accept(this, arg) : null;
+        VariableExpr newWindowVar =
+                winExpr.hasWindowVar() ? (VariableExpr) 
winExpr.getWindowVar().accept(this, arg) : null;
+        List<Pair<Expression, Identifier>> newWindowFieldList =
+                winExpr.hasWindowFieldList() ? 
copyFieldList(winExpr.getWindowFieldList(), arg) : null;
+        WindowExpression copy = new 
WindowExpression(winExpr.getFunctionSignature(), newExprList, newPartitionList,
+                newOrderbyList, newOrderbyModifierList, 
winExpr.getFrameMode(), winExpr.getFrameStartKind(),
+                newFrameStartExpr, winExpr.getFrameEndKind(), newFrameEndExpr, 
winExpr.getFrameExclusionKind(),
+                newWindowVar, newWindowFieldList);
         copy.setSourceLocation(winExpr.getSourceLocation());
         copy.addHints(winExpr.getHints());
         return copy;
@@ -533,4 +547,13 @@ public class DeepCopyVisitor extends 
AbstractSqlppQueryExpressionVisitor<ILangEx
         }
         return newExprList;
     }
+
+    private List<Pair<Expression, Identifier>> 
copyFieldList(List<Pair<Expression, Identifier>> fieldList, Void arg)
+            throws CompilationException {
+        List<Pair<Expression, Identifier>> newFieldList = new 
ArrayList<>(fieldList.size());
+        for (Pair<Expression, Identifier> field : fieldList) {
+            newFieldList.add(new Pair<>((Expression) field.first.accept(this, 
arg), field.second));
+        }
+        return newFieldList;
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/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 dfa1430..b61f4e6 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
@@ -287,14 +287,21 @@ public class FreeVariableVisitor extends 
AbstractSqlppQueryExpressionVisitor<Voi
         for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
             gbyVarExpr.getExpr().accept(this, freeVars);
         }
-        for (GbyVariableExpressionPair decorVarExpr : gc.getDecorPairList()) {
-            decorVarExpr.getExpr().accept(this, freeVars);
+        if (gc.hasDecorList()) {
+            for (GbyVariableExpressionPair decorVarExpr : 
gc.getDecorPairList()) {
+                decorVarExpr.getExpr().accept(this, freeVars);
+            }
         }
         if (gc.hasGroupFieldList()) {
             for (Pair<Expression, Identifier> groupField : 
gc.getGroupFieldList()) {
                 groupField.first.accept(this, freeVars);
             }
         }
+        if (gc.hasWithMap()) {
+            for (Expression expr : gc.getWithVarMap().keySet()) {
+                expr.accept(this, freeVars);
+            }
+        }
         return null;
     }
 
@@ -440,11 +447,27 @@ public class FreeVariableVisitor extends 
AbstractSqlppQueryExpressionVisitor<Voi
 
     @Override
     public Void visit(WindowExpression winExpr, Collection<VariableExpr> 
freeVars) throws CompilationException {
-        winExpr.getExpr().accept(this, freeVars);
         if (winExpr.hasPartitionList()) {
             visit(winExpr.getPartitionList(), freeVars);
         }
-        visit(winExpr.getOrderbyList(), freeVars);
+        if (winExpr.hasOrderByList()) {
+            visit(winExpr.getOrderbyList(), freeVars);
+        }
+        if (winExpr.hasFrameStartExpr()) {
+            winExpr.getFrameStartExpr().accept(this, freeVars);
+        }
+        if (winExpr.hasFrameEndExpr()) {
+            winExpr.getFrameEndExpr().accept(this, freeVars);
+        }
+        if (winExpr.hasWindowFieldList()) {
+            for (Pair<Expression, Identifier> field : 
winExpr.getWindowFieldList()) {
+                field.first.accept(this, freeVars);
+            }
+        }
+        visit(winExpr.getExprList(), freeVars);
+        if (winExpr.hasWindowVar()) {
+            freeVars.remove(winExpr.getWindowVar());
+        }
         return null;
     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/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 c12914d..f1039ff 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
@@ -293,12 +293,7 @@ public class SqlppAstPrintVisitor extends 
QueryPrintVisitor implements ISqlppVis
             out.print(skip(step + 1) + "GROUP AS ");
             gc.getGroupVar().accept(this, 0);
             if (gc.hasGroupFieldList()) {
-                out.println(skip(step + 1) + "(");
-                for (Pair<Expression, Identifier> field : 
gc.getGroupFieldList()) {
-                    out.print(skip(step + 2) + field.second + ":=");
-                    field.first.accept(this, 0);
-                }
-                out.println(skip(step + 1) + ")");
+                printFieldList(step + 1, gc.getGroupFieldList());
             }
         }
         if (gc.hasWithMap()) {
@@ -335,31 +330,6 @@ public class SqlppAstPrintVisitor extends 
QueryPrintVisitor implements ISqlppVis
     }
 
     @Override
-    public Void visit(WindowExpression winExpr, Integer step) throws 
CompilationException {
-        out.print(skip(step) + "WINDOW");
-        winExpr.getExpr().accept(this, step + 1);
-        out.println();
-        out.println(skip(step) + "OVER (");
-        if (winExpr.hasPartitionList()) {
-            out.println(skip(step + 1) + "PARTITION BY");
-            List<Expression> partitionList = winExpr.getPartitionList();
-            for (Expression expr : partitionList) {
-                expr.accept(this, step + 2);
-                out.println();
-            }
-        }
-        out.println(skip(step + 1) + "ORDER BY");
-        List<Expression> orderbyList = winExpr.getOrderbyList();
-        List<OrderbyClause.OrderModifier> orderbyModifierList = 
winExpr.getOrderbyModifierList();
-        for (int i = 0, ln = orderbyList.size(); i < ln; i++) {
-            orderbyList.get(i).accept(this, step + 2);
-            out.println(" " + orderbyModifierList.get(i));
-        }
-        out.println(skip(step) + ")");
-        return null;
-    }
-
-    @Override
     public Void visit(ListSliceExpression expression, Integer step) throws 
CompilationException {
         out.println(skip(step) + "ListSliceExpression [");
         expression.getExpr().accept(this, step + 1);
@@ -376,4 +346,58 @@ public class SqlppAstPrintVisitor extends 
QueryPrintVisitor implements ISqlppVis
         out.println(skip(step) + "]");
         return null;
     }
+
+    @Override
+    public Void visit(WindowExpression winExpr, Integer step) throws 
CompilationException {
+        out.println(skip(step) + "WINDOW " + winExpr.getFunctionSignature() + 
"[");
+        for (Expression expr : winExpr.getExprList()) {
+            expr.accept(this, step + 1);
+        }
+        out.println(skip(step) + "]");
+        if (winExpr.hasWindowVar()) {
+            out.print(skip(step + 1) + "AS ");
+            winExpr.getWindowVar().accept(this, 0);
+            if (winExpr.hasWindowFieldList()) {
+                printFieldList(step + 1, winExpr.getWindowFieldList());
+            }
+        }
+        out.println(skip(step) + "OVER (");
+        if (winExpr.hasPartitionList()) {
+            out.println(skip(step + 1) + "PARTITION BY");
+            List<Expression> partitionList = winExpr.getPartitionList();
+            for (Expression expr : partitionList) {
+                expr.accept(this, step + 2);
+            }
+        }
+        if (winExpr.hasOrderByList()) {
+            out.println(skip(step + 1) + "ORDER BY");
+            List<Expression> orderbyList = winExpr.getOrderbyList();
+            List<OrderbyClause.OrderModifier> orderbyModifierList = 
winExpr.getOrderbyModifierList();
+            for (int i = 0, ln = orderbyList.size(); i < ln; i++) {
+                orderbyList.get(i).accept(this, step + 2);
+                out.println(skip(step + 2) + orderbyModifierList.get(i));
+            }
+        }
+        if (winExpr.hasFrameDefinition()) {
+            out.println(skip(step + 1) + winExpr.getFrameMode() + ' ' + 
winExpr.getFrameStartKind() + ' '
+                    + winExpr.getFrameEndKind() + " EXCLUDE " + 
winExpr.getFrameExclusionKind());
+            if (winExpr.hasFrameStartExpr()) {
+                winExpr.getFrameStartExpr().accept(this, step + 2);
+            }
+            if (winExpr.hasFrameEndExpr()) {
+                winExpr.getFrameEndExpr().accept(this, step + 2);
+            }
+        }
+        out.println(skip(step) + ")");
+        return null;
+    }
+
+    private void printFieldList(int step, List<Pair<Expression, Identifier>> 
fieldList) throws CompilationException {
+        out.println(skip(step) + "(");
+        for (Pair<Expression, Identifier> field : fieldList) {
+            out.print(skip(step + 1) + field.second + ":=");
+            field.first.accept(this, 0);
+        }
+        out.println(skip(step) + ")");
+    }
 }

Reply via email to