You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@quickstep.apache.org by sh...@apache.org on 2016/06/21 20:09:45 UTC

incubator-quickstep git commit: Window Aggregation Function in optimizer::expression added The resolver could understand optional window clause. The resolver could understand window aggregation functions. Only one window aggregation function is allowed

Repository: incubator-quickstep
Updated Branches:
  refs/heads/SQL-window-aggregation [created] ae66fbe46


Window Aggregation Function in optimizer::expression added
The resolver could understand optional window clause.
The resolver could understand window aggregation functions.
Only one window aggregation function is allowed


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

Branch: refs/heads/SQL-window-aggregation
Commit: ae66fbe467cfad0667efe87412f472e673c7cdc7
Parents: 00ca1e4
Author: shixuan <sh...@wisc.edu>
Authored: Tue Jun 21 20:08:52 2016 +0000
Committer: shixuan <sh...@wisc.edu>
Committed: Tue Jun 21 20:08:52 2016 +0000

----------------------------------------------------------------------
 query_optimizer/expressions/CMakeLists.txt      |   1 +
 query_optimizer/expressions/ExpressionType.hpp  |   3 +-
 .../expressions/WindowAggregateFunction.cpp     | 141 +++++++++
 .../expressions/WindowAggregateFunction.hpp     | 254 ++++++++++++++++
 query_optimizer/resolver/Resolver.cpp           | 294 ++++++++++++++++++-
 query_optimizer/resolver/Resolver.hpp           |  41 ++-
 6 files changed, 727 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/ae66fbe4/query_optimizer/expressions/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/CMakeLists.txt b/query_optimizer/expressions/CMakeLists.txt
index 6c40741..e019c8e 100644
--- a/query_optimizer/expressions/CMakeLists.txt
+++ b/query_optimizer/expressions/CMakeLists.txt
@@ -43,6 +43,7 @@ add_library(quickstep_queryoptimizer_expressions_SearchedCase SearchedCase.cpp S
 add_library(quickstep_queryoptimizer_expressions_SimpleCase SimpleCase.cpp SimpleCase.hpp)
 add_library(quickstep_queryoptimizer_expressions_SubqueryExpression SubqueryExpression.cpp SubqueryExpression.hpp)
 add_library(quickstep_queryoptimizer_expressions_UnaryExpression UnaryExpression.cpp UnaryExpression.hpp)
+add_library(quickstep_queryoptimizer_expressions_WindowAggregateFunction WindowAggregateFunction.cpp WindowAggregateFunction.hpp)
 
 # Link dependencies:
 target_link_libraries(quickstep_queryoptimizer_expressions_AggregateFunction

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/ae66fbe4/query_optimizer/expressions/ExpressionType.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/ExpressionType.hpp b/query_optimizer/expressions/ExpressionType.hpp
index 23770e0..77e0874 100644
--- a/query_optimizer/expressions/ExpressionType.hpp
+++ b/query_optimizer/expressions/ExpressionType.hpp
@@ -49,7 +49,8 @@ enum class ExpressionType {
   kSearchedCase,
   kSimpleCase,
   kSubqueryExpression,
-  kUnaryExpression
+  kUnaryExpression,
+  kWindowAggregateFunction
 };
 
 /** @} */

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/ae66fbe4/query_optimizer/expressions/WindowAggregateFunction.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/WindowAggregateFunction.cpp b/query_optimizer/expressions/WindowAggregateFunction.cpp
new file mode 100644
index 0000000..b980c99
--- /dev/null
+++ b/query_optimizer/expressions/WindowAggregateFunction.cpp
@@ -0,0 +1,141 @@
+/**
+ *   Copyright 2015 Pivotal Software, Inc.
+ *   Copyright 2016, Quickstep Research Group, Computer Sciences Department,
+ *     University of Wisconsin\u2014Madison.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License 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.
+ **/
+
+#include "query_optimizer/expressions/WindowAggregateFunction.hpp"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "expressions/aggregation/AggregateFunction.hpp"
+#include "query_optimizer/expressions/AttributeReference.hpp"
+#include "query_optimizer/expressions/Expression.hpp"
+#include "query_optimizer/expressions/PatternMatcher.hpp"
+#include "query_optimizer/expressions/Scalar.hpp"
+#include "types/Type.hpp"
+#include "utility/Cast.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+namespace optimizer {
+namespace expressions {
+
+bool WindowAggregateFunction::isNullable() const {
+  std::vector<const Type*> argument_types;
+  for (const ScalarPtr &argument : arguments_) {
+    argument_types.emplace_back(&argument->getValueType());
+  }
+
+  const Type *return_type = window_aggregate_.resultTypeForArgumentTypes(argument_types);
+  DCHECK(return_type != nullptr);
+  return return_type->isNullable();
+}
+
+const Type& WindowAggregateFunction::getValueType() const {
+  std::vector<const Type*> argument_types;
+  for (const ScalarPtr &argument : arguments_) {
+    argument_types.emplace_back(&argument->getValueType());
+  }
+
+  const Type *return_type = window_aggregate_.resultTypeForArgumentTypes(argument_types);
+  DCHECK(return_type != nullptr);
+  return *return_type;
+}
+
+WindowAggregateFunctionPtr WindowAggregateFunction::Create(
+    const ::quickstep::AggregateFunction &window_aggregate,
+    const std::vector<ScalarPtr> &arguments,
+    const WindowInfo *window_info,
+    const bool is_distinct) {
+#ifdef QUICKSTEP_DEBUG
+  std::vector<const Type*> argument_types;
+  for (const ScalarPtr &argument : arguments) {
+    argument_types.emplace_back(&argument->getValueType());
+  }
+  DCHECK(window_aggregate.canApplyToTypes(argument_types));
+#endif  // QUICKSTEP_DEBUG
+
+  return WindowAggregateFunctionPtr(
+      new WindowAggregateFunction(window_aggregate, arguments, window_info, "", is_distinct));
+}
+
+WindowAggregateFunctionPtr WindowAggregateFunction::Create(
+    const ::quickstep::AggregateFunction &window_aggregate,
+    const std::vector<ScalarPtr> &arguments,
+    const std::string window_name,
+    const bool is_distinct) {
+#ifdef QUICKSTEP_DEBUG
+  std::vector<const Type*> argument_types;
+  for (const ScalarPtr &argument : arguments) {
+    argument_types.emplace_back(&argument->getValueType());
+  }
+  DCHECK(window_aggregate.canApplyToTypes(argument_types));
+#endif  // QUICKSTEP_DEBUG
+
+  return WindowAggregateFunctionPtr(
+      new WindowAggregateFunction(window_aggregate, arguments, nullptr, window_name, is_distinct));
+}
+
+ExpressionPtr WindowAggregateFunction::copyWithNewChildren(
+    const std::vector<ExpressionPtr> &new_children) const {
+  std::vector<ScalarPtr> new_arguments;
+  for (const ExpressionPtr &expression_ptr : new_children) {
+    ScalarPtr expr_as_scalar;
+    CHECK(SomeScalar::MatchesWithConditionalCast(expression_ptr, &expr_as_scalar))
+        << expression_ptr->toString();
+    new_arguments.emplace_back(std::move(expr_as_scalar));
+  }
+
+  return Create(window_aggregate_, new_arguments, window_info_, is_distinct_);
+}
+
+std::vector<AttributeReferencePtr> WindowAggregateFunction::getReferencedAttributes() const {
+  std::vector<AttributeReferencePtr> referenced_attributes;
+  for (const ScalarPtr &argument : arguments_) {
+    const std::vector<AttributeReferencePtr> referenced_attributes_in_argument =
+        argument->getReferencedAttributes();
+    referenced_attributes.insert(referenced_attributes.end(),
+                                 referenced_attributes_in_argument.begin(),
+                                 referenced_attributes_in_argument.end());
+  }
+  return referenced_attributes;
+}
+
+void WindowAggregateFunction::getFieldStringItems(
+    std::vector<std::string> *inline_field_names,
+    std::vector<std::string> *inline_field_values,
+    std::vector<std::string> *non_container_child_field_names,
+    std::vector<OptimizerTreeBaseNodePtr> *non_container_child_fields,
+    std::vector<std::string> *container_child_field_names,
+    std::vector<std::vector<OptimizerTreeBaseNodePtr>> *container_child_fields) const {
+  inline_field_names->push_back("function");
+  inline_field_values->push_back(window_aggregate_.getName());
+
+  if (is_distinct_) {
+    inline_field_names->push_back("is_distinct");
+    inline_field_values->push_back("true");
+  }
+
+  container_child_field_names->push_back("");
+  container_child_fields->emplace_back(CastSharedPtrVector<OptimizerTreeBase>(arguments_));
+}
+
+}  // namespace expressions
+}  // namespace optimizer
+}  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/ae66fbe4/query_optimizer/expressions/WindowAggregateFunction.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/WindowAggregateFunction.hpp b/query_optimizer/expressions/WindowAggregateFunction.hpp
new file mode 100644
index 0000000..ca7e449
--- /dev/null
+++ b/query_optimizer/expressions/WindowAggregateFunction.hpp
@@ -0,0 +1,254 @@
+/**
+ *   Copyright 2011-2015 Quickstep Technologies LLC.
+ *   Copyright 2015 Pivotal Software, Inc.
+ *   Copyright 2016, Quickstep Research Group, Computer Sciences Department,
+ *     University of Wisconsin\u2014Madison.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License 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.
+ **/
+
+#ifndef QUICKSTEP_QUERY_OPTIMIZER_EXPRESSIONS_WINDOW_AGGREGATE_FUNCTION_HPP_
+#define QUICKSTEP_QUERY_OPTIMIZER_EXPRESSIONS_WINDOW_AGGREGATE_FUNCTION_HPP_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "query_optimizer/OptimizerTree.hpp"
+#include "query_optimizer/expressions/AttributeReference.hpp"
+#include "query_optimizer/expressions/Expression.hpp"
+#include "query_optimizer/expressions/ExpressionType.hpp"
+#include "query_optimizer/expressions/Scalar.hpp"
+#include "utility/Macros.hpp"
+
+namespace quickstep {
+
+class AggregateFunction;
+class Type;
+
+namespace optimizer {
+namespace expressions {
+
+/** \addtogroup OptimizerExpressions
+ *  @{
+ */
+
+struct WindowFrameInfo {
+  /**
+   * @brief Cosntructor.
+   *
+   * @param is_row_in True if this window frame is defined by ROWS, false if
+   *                  defined by RANGE.
+   * @param num_preceding_in The number of preceding tuples the window frame
+   *                         will cover, -1 means UNBOUNDED.
+   * @param num_following_in The number of following tuples the window frame
+   *                         will cover, -1 means UNBOUNDED.
+   **/
+  explicit WindowFrameInfo(const bool is_row_in,
+                           const int num_preceding_in,
+                           const int num_following_in)
+      : is_row(is_row_in),
+        num_preceding(num_preceding_in),
+        num_following(num_following_in) {}
+ 
+  const bool is_row;
+  const int num_preceding;
+  const int num_following;
+};
+
+struct WindowInfo {
+  /**
+   * @brief Constructor.
+   *
+   * @param partition_by_attributes_in The partition keys for the window.
+   * @param order_by_attributes_in The order keys for the window.
+   * @param order_by_directions_in The order direction for order key.
+   * @param nulls_first_in The nulls' position for order key.
+   * @param frame_info_in The window frame information for the window. Null
+   *        means there is no explicit window frame definition.
+   **/
+  explicit WindowInfo(const std::vector<AttributeReferencePtr> &partition_by_attributes_in,
+                      const std::vector<AttributeReferencePtr> &order_by_attributes_in,
+                      const std::vector<bool> order_by_directions_in,
+                      const std::vector<bool> nulls_first_in,
+                      const WindowFrameInfo *frame_info_in)
+      : partition_by_attributes(partition_by_attributes_in),
+        order_by_attributes(order_by_attributes_in),
+        frame_info(frame_info_in) {}
+  
+  const std::vector<AttributeReferencePtr> partition_by_attributes;
+  const std::vector<AttributeReferencePtr> order_by_attributes;
+  const std::vector<bool> order_by_directions;
+  const std::vector<bool> nulls_first;
+  const WindowFrameInfo *frame_info;
+};
+
+class WindowAggregateFunction;
+typedef std::shared_ptr<const WindowAggregateFunction> WindowAggregateFunctionPtr;
+
+/**
+ * @brief Represents a window aggregate function and its arguments in the
+ *        optimizer. This class wraps some of the functionality from
+ *        quickstep::AggregateFunction and represents a particular instance
+ *        of an aggregate during query optimization.
+ **/
+class WindowAggregateFunction : public Expression {
+ public:
+  /**
+   * @brief Destructor.
+   */
+  ~WindowAggregateFunction() override {}
+
+  ExpressionType getExpressionType() const override {
+    return ExpressionType::kWindowAggregateFunction;
+  }
+
+  std::string getName() const override {
+    return "WindowAggregateFunction";
+  }
+
+  const Type& getValueType() const override;
+
+  bool isConstant() const override {
+    // Window aggregate function is never considered as a constant expression.
+    return false;
+  }
+
+  ExpressionPtr copyWithNewChildren(
+      const std::vector<ExpressionPtr> &new_children) const override;
+
+  std::vector<AttributeReferencePtr> getReferencedAttributes() const override;
+
+  /**
+   * @return Whether the type of the return value is nullable.
+   **/
+  bool isNullable() const;
+
+  /**
+   * @return The WindowAggregateFunction singleton (from the expression system)
+   *         for this node.
+   **/
+  inline const ::quickstep::AggregateFunction& getWindowAggregate() const {
+    return window_aggregate_;
+  }
+
+  /**
+   * @return The list of scalar arguments to this aggregate.
+   **/
+  inline const std::vector<ScalarPtr>& getArguments() const {
+    return arguments_;
+  }
+
+  /**
+   * @return The window info of this window aggregate function.
+   **/
+  inline const WindowInfo* getWindowInfo() const {
+    return window_info_;
+  }
+
+  /**
+   * @return Whether this is a DISTINCT aggregation.
+   **/
+  inline bool is_distinct() const {
+    return is_distinct_;
+  }
+
+  /**
+   * @brief Create a new WindowAggregateFunction by directly defined window.
+   *
+   * @warning It is an error to call this with arguments that the given
+   *          aggregate can not apply to.
+   *
+   * @param aggregate The underlying WindowAggregateFunction from the expression
+   *        system.
+   * @param arguments A list of arguments to the window aggregate function.
+   * @param window_info The window info of the window aggregate function.
+   * @param is_distinct Whether this is a DISTINCT aggregation.
+   * @return A new AggregateFunctionPtr.
+   **/
+  static WindowAggregateFunctionPtr Create(const ::quickstep::AggregateFunction &window_aggregate,
+                                           const std::vector<ScalarPtr> &arguments,
+                                           const WindowInfo *window_info,
+                                           const bool is_distinct);
+
+  /**
+   * @brief Create a new WindowAggregateFunction by window name.
+   *
+   * @warning It is an error to call this with arguments that the given
+   *          aggregate can not apply to.
+   *
+   * @param aggregate The underlying WindowAggregateFunction from the expression
+   *        system.
+   * @param arguments A list of arguments to the window aggregate function.
+   * @param window_name The window name of the window aggregate function.
+   * @param is_distinct Whether this is a DISTINCT aggregation.
+   * @return A new AggregateFunctionPtr.
+   **/
+  static WindowAggregateFunctionPtr Create(const ::quickstep::AggregateFunction &window_aggregate,
+                                           const std::vector<ScalarPtr> &arguments,
+                                           const std::string window_name,
+                                           const bool is_distinct);
+
+ protected:
+  void getFieldStringItems(
+      std::vector<std::string> *inline_field_names,
+      std::vector<std::string> *inline_field_values,
+      std::vector<std::string> *non_container_child_field_names,
+      std::vector<OptimizerTreeBaseNodePtr> *non_container_child_fields,
+      std::vector<std::string> *container_child_field_names,
+      std::vector<std::vector<OptimizerTreeBaseNodePtr>> *container_child_fields) const override;
+
+ private:
+  /**
+   * @brief Constructor.
+   *
+   * @param window_aggregate The actual AggregateFunction to use.
+   * @param arguments A list of arguments to the window aggregate function.
+   * @param window_info The window info of the window aggregate function.
+   * @param is_distinct Indicates whether this is a DISTINCT aggregation.
+   */
+  WindowAggregateFunction(const ::quickstep::AggregateFunction &window_aggregate,
+                          const std::vector<ScalarPtr> &arguments,
+                          const WindowInfo *window_info,
+                          const std::string window_name,
+                          const bool is_distinct)
+      : window_aggregate_(window_aggregate),
+        arguments_(arguments),
+        window_info_(window_info),
+        window_name_(window_name),
+        is_distinct_(is_distinct) {
+    for (const ScalarPtr &child : arguments_) {
+      addChild(child);
+    }
+  }
+
+  // TODO(Shixuan): Currently this class uses AggregationFunction as
+  // window_aggregate_. If it really needs to be seperated from the
+  // AggregationFunction, a new class for WindowAggregationFunction should be
+  // created as quickstep::WindowAggregateFunction.
+  const ::quickstep::AggregateFunction &window_aggregate_;
+  std::vector<ScalarPtr> arguments_;
+  const WindowInfo *window_info_;
+  const std::string window_name_;
+  const bool is_distinct_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowAggregateFunction);
+};
+
+/** @} */
+
+}  // namespace expressions
+}  // namespace optimizer
+}  // namespace quickstep
+
+#endif /* QUICKSTEP_QUERY_OPTIMIZER_EXPRESSIONS_AGGREGATE_FUNCTION_HPP_ */

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/ae66fbe4/query_optimizer/resolver/Resolver.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/Resolver.cpp b/query_optimizer/resolver/Resolver.cpp
index ffc173a..7895f6c 100644
--- a/query_optimizer/resolver/Resolver.cpp
+++ b/query_optimizer/resolver/Resolver.cpp
@@ -85,6 +85,7 @@
 #include "query_optimizer/expressions/SimpleCase.hpp"
 #include "query_optimizer/expressions/SubqueryExpression.hpp"
 #include "query_optimizer/expressions/UnaryExpression.hpp"
+#include "query_optimizer/expressions/WindowAggregateFunction.hpp"
 #include "query_optimizer/logical/Aggregate.hpp"
 #include "query_optimizer/logical/CopyFrom.hpp"
 #include "query_optimizer/logical/CreateIndex.hpp"
@@ -187,16 +188,28 @@ struct Resolver::ExpressionResolutionInfo {
    */
   bool hasAggregate() const { return parse_aggregate_expression != nullptr; }
 
+  /**
+   * @return True if the expression contains a window aggregate function.
+   **/
+  bool hasWindowAggregate() const {
+    return parse_window_aggregate_expression != nullptr;
+  }
+
   const NameResolver &name_resolver;
   // Empty if aggregations are allowed.
   const std::string not_allow_aggregate_here;
 
+  // Alias expressions that wraps window aggregate functions
+  std::vector<E::AliasPtr> window_aggregate_expressions;
+
   // Can be NULL if aggregations are not allowed.
   QueryAggregationInfo *query_aggregation_info = nullptr;
   // Can be NULL if alias references to SELECT-list expressions are not allowed.
   SelectListInfo *select_list_info = nullptr;
   // The first aggregate in the expression.
   const ParseTreeNode *parse_aggregate_expression = nullptr;
+  // The first window aggregate in the expression.
+  const ParseTreeNode *parse_window_aggregate_expression = nullptr;
 };
 
 struct Resolver::QueryAggregationInfo {
@@ -209,6 +222,16 @@ struct Resolver::QueryAggregationInfo {
   std::vector<E::AliasPtr> aggregate_expressions;
 };
 
+struct Resolver::WindowAggregationInfo {
+  explicit WindowAggregationInfo(E::WindowInfo window_info_in,
+                                 L::LogicalPtr logical_plan_in)
+      : window_info(window_info_in),
+        logical_plan(logical_plan_in) {}
+
+  const E::WindowInfo window_info;
+  const L::LogicalPtr logical_plan;
+};
+
 struct Resolver::SelectListInfo {
  public:
   /**
@@ -973,6 +996,49 @@ L::LogicalPtr Resolver::resolveSelect(
         logical_plan, resolvePredicate(parse_predicate, &expr_resolution_info));
   }
 
+  // Resolve WINDOW clause.
+  std::unordered_map<std::string, WindowAggregationInfo> sorted_window_table;
+  if (select_query.window_list() != nullptr) {
+    if (select_query.window_list()->size() > 1) {
+      THROW_SQL_ERROR_AT(&(*select_query.window_list()->begin()))
+        << "Currently we don't support multiple window aggregation functions";
+    }
+    
+    for (const ParseWindow &window : *select_query.window_list()) {
+      E::WindowInfo resolved_window = resolveWindow(window, *name_resolver);
+      
+      // Sort the table by (p_key, o_key)
+      std::vector<E::AttributeReferencePtr> sort_attributes(resolved_window.partition_by_attributes);
+      sort_attributes.insert(sort_attributes.end(),
+                             resolved_window.order_by_attributes.begin(),
+                             resolved_window.order_by_attributes.end());
+                      
+      std::vector<bool> sort_directions(
+          resolved_window.partition_by_attributes.size(), true);
+      sort_directions.insert(sort_directions.end(),
+                            resolved_window.order_by_directions.begin(),
+                            resolved_window.order_by_directions.end());
+                          
+      std::vector<bool> sort_nulls_first(
+          resolved_window.partition_by_attributes.size(), false);
+      sort_nulls_first.insert(sort_nulls_first.end(),
+                              resolved_window.nulls_first.begin(),
+                              resolved_window.nulls_first.end());
+                              
+      L::LogicalPtr sorted_logical_plan =
+          L::Sort::Create(logical_plan,
+                          sort_attributes,
+                          sort_directions,
+                          sort_nulls_first,
+                          -1 /* limit */);
+
+      WindowAggregationInfo window_aggregation_info(resolved_window,
+                                                    sorted_logical_plan);
+      
+      sorted_window_table.emplace(window.name()->value(), window_aggregation_info);
+    }
+  }
+
   QueryAggregationInfo query_aggregation_info(
       (select_query.group_by() != nullptr));
 
@@ -1528,6 +1594,89 @@ L::LogicalPtr Resolver::RenameOutputColumns(
   return L::Project::Create(logical_plan, project_expressions);
 }
 
+E::WindowInfo Resolver::resolveWindow(const ParseWindow &parse_window,
+                                      const NameResolver &name_resolver) {
+  std::vector<E::AttributeReferencePtr> partition_by_attributes;
+  std::vector<E::AttributeReferencePtr> order_by_attributes;
+  std::vector<bool> order_by_directions;
+  std::vector<bool> nulls_first;
+  E::WindowFrameInfo *frame_info = nullptr;
+
+  // Resolve PARTITION BY
+  if (parse_window.partition_by_expressions() != nullptr) {
+    for (const ParseExpression &unresolved_partition_by_expression :
+         *parse_window.partition_by_expressions()) {
+      ExpressionResolutionInfo expr_resolution_info(
+          name_resolver,
+          "PARTITION BY clause" /* clause_name */,
+          nullptr /* select_list_info */);
+      E::ScalarPtr partition_by_scalar = resolveExpression(
+          unresolved_partition_by_expression,
+          nullptr,  // No Type hint.
+          &expr_resolution_info);
+
+      if (partition_by_scalar->isConstant()) {
+        THROW_SQL_ERROR_AT(&unresolved_partition_by_expression)
+            << "Constant expression not allowed in PARTITION BY";
+      }
+
+      E::AttributeReferencePtr partition_by_attribute;
+      if (!E::SomeAttributeReference::MatchesWithConditionalCast(partition_by_scalar,
+                                                                 &partition_by_attribute)) {
+        THROW_SQL_ERROR_AT(&unresolved_partition_by_expression)
+            << "Only attribute name allowed in PARTITION BY in window definition";
+      }
+
+      partition_by_attributes.push_back(partition_by_attribute);
+    }
+  }
+
+  // Resolve ORDER BY
+  if (parse_window.order_by_expressions() != nullptr) {
+    for (const ParseOrderByItem &order_by_item :
+         *parse_window.order_by_expressions()) {
+      ExpressionResolutionInfo expr_resolution_info(
+          name_resolver,
+          "ORDER BY clause" /* clause name */,
+          nullptr /* select_list_info */);
+      E::ScalarPtr order_by_scalar = resolveExpression(
+          *order_by_item.ordering_expression(),
+          nullptr,  // No Type hint.
+          &expr_resolution_info);
+          
+      if (order_by_scalar->isConstant()) {
+        THROW_SQL_ERROR_AT(&order_by_item)
+            << "Constant expression not allowed in ORDER BY";
+      }
+
+      E::AttributeReferencePtr order_by_attribute;
+      if (!E::SomeAttributeReference::MatchesWithConditionalCast(order_by_scalar,
+                                                                 &order_by_attribute)) {
+        THROW_SQL_ERROR_AT(&order_by_item)
+            << "Only attribute name allowed in ORDER BY in window definition";
+      }
+
+      order_by_attributes.push_back(order_by_attribute);
+      order_by_directions.push_back(order_by_item.is_ascending());
+      nulls_first.push_back(order_by_item.nulls_first());
+    }
+  }
+
+  // Resolve window frame
+  if (parse_window.frame_info() != nullptr) {
+    const quickstep::ParseFrameInfo *parse_frame_info = parse_window.frame_info();
+    frame_info = new E::WindowFrameInfo(parse_frame_info->is_row,
+                                     parse_frame_info->num_preceding,
+                                     parse_frame_info->num_following);
+  }
+
+  return E::WindowInfo(partition_by_attributes,
+                       order_by_attributes,
+                       order_by_directions,
+                       nulls_first,
+                       frame_info);
+}
+
 const CatalogRelation* Resolver::resolveRelationName(
     const ParseString *relation_name) {
   const CatalogRelation *relation =
@@ -2362,17 +2511,19 @@ E::ScalarPtr Resolver::resolveSimpleCaseExpression(
 
 // TODO(chasseur): For now this only handles resolving aggregate functions. In
 // the future it should be extended to resolve scalar functions as well.
+// TODO(Shixuan): This will handle resolving window aggregation function as well,
+// which could be extended to general scalar functions.
 E::ScalarPtr Resolver::resolveFunctionCall(
     const ParseFunctionCall &parse_function_call,
     ExpressionResolutionInfo *expression_resolution_info) {
-  std::string function_name = ToLower(parse_function_call.name()->value());
-
-  // TODO(Shixuan): Add support for window aggregation function.
+  // Check if it is a window function.
   if (parse_function_call.isWindow()) {
-    THROW_SQL_ERROR_AT(&parse_function_call)
-        << "Window Aggregation Function is not supported currently";
+    return resolveWindowAggregateFunction(parse_function_call,
+                                          expression_resolution_info);
   }
 
+  std::string function_name = ToLower(parse_function_call.name()->value());
+
   // First check for the special case COUNT(*).
   bool count_star = false;
   if (parse_function_call.star() != nullptr) {
@@ -2471,6 +2622,135 @@ E::ScalarPtr Resolver::resolveFunctionCall(
   return E::ToRef(aggregate_alias);
 }
 
+E::ScalarPtr Resolver::resolveWindowAggregateFunction(
+    const ParseFunctionCall &parse_function_call,
+    ExpressionResolutionInfo *expression_resolution_info) {
+  std::string function_name = ToLower(parse_function_call.name()->value());
+  
+  // First check for the special case COUNT(*).
+  bool count_star = false;
+  if (parse_function_call.star() != nullptr) {
+    if (function_name != "count") {
+      THROW_SQL_ERROR_AT(parse_function_call.star())
+          << "Only COUNT can have star (*) as an argument";
+    }
+    count_star = true;
+  }
+
+  std::vector<E::ScalarPtr> resolved_arguments;
+  const PtrList<ParseExpression> *unresolved_arguments =
+      parse_function_call.arguments();
+  // The first aggregate function in the arguments.
+  const ParseTreeNode *first_aggregate_function = nullptr;
+  const ParseTreeNode *first_window_aggregate_function = nullptr;
+  if (unresolved_arguments != nullptr) {
+    for (const ParseExpression &unresolved_argument : *unresolved_arguments) {
+      ExpressionResolutionInfo expr_resolution_info(
+          *expression_resolution_info);
+      resolved_arguments.push_back(
+          resolveExpression(unresolved_argument,
+                            nullptr,  // No Type hint.
+                            &expr_resolution_info));
+                            
+      // We don't allow aggregate or window aggregate nested in a window
+      // aggregate function
+      if (expr_resolution_info.hasAggregate() &&
+          first_aggregate_function == nullptr) {
+        first_aggregate_function =
+            expr_resolution_info.parse_aggregate_expression;
+      }
+
+      if (expr_resolution_info.hasWindowAggregate() &&
+          first_window_aggregate_function == nullptr) {
+        first_window_aggregate_function =
+            expr_resolution_info.parse_window_aggregate_expression;
+      }
+    }
+  }
+
+  if (count_star && !resolved_arguments.empty()) {
+    THROW_SQL_ERROR_AT(&parse_function_call)
+        << "COUNT aggregate has both star (*) and non-star arguments.";
+  }
+
+  // Try to look up the AggregateFunction by name using
+  // AggregateFunctionFactory.
+  const ::quickstep::AggregateFunction *window_aggregate
+      = AggregateFunctionFactory::GetByName(function_name);
+  if (window_aggregate == nullptr) {
+    THROW_SQL_ERROR_AT(&parse_function_call)
+        << "Unrecognized function name \""
+        << parse_function_call.name()->value()
+        << "\"";
+  }
+
+  // Make sure aggregates are allowed in this context.
+  if (first_aggregate_function != nullptr) {
+    THROW_SQL_ERROR_AT(first_aggregate_function)
+        << "Window Aggregation of Aggregates are not allowed";
+  }
+
+  // TODO(Shixuan): We currently don't support nested window aggregation since
+  // TPC-DS doesn't have that. However, it is essentially a nested scalar
+  // function, which should be supported in the future version of Quickstep.
+  if (first_window_aggregate_function != nullptr) {
+    THROW_SQL_ERROR_AT(first_window_aggregate_function)
+        << "Window Aggregation of Window Aggregates are not allowed";
+  }
+
+  // Make sure a naked COUNT() with no arguments wasn't specified.
+  if ((window_aggregate->getAggregationID() == AggregationID::kCount)
+      && (resolved_arguments.empty())
+      && (!count_star)) {
+    THROW_SQL_ERROR_AT(&parse_function_call)
+        << "COUNT aggregate requires an argument (either scalar or star (*))";
+  }
+
+  // Resolve each of the Scalar arguments to the aggregate.
+  std::vector<const Type*> argument_types;
+  for (const E::ScalarPtr &argument : resolved_arguments) {
+    argument_types.emplace_back(&argument->getValueType());
+  }
+
+  // Make sure that the aggregate can apply to the specified argument(s).
+  if (!window_aggregate->canApplyToTypes(argument_types)) {
+    THROW_SQL_ERROR_AT(&parse_function_call)
+        << "Aggregate function " << window_aggregate->getName()
+        << " can not apply to the given argument(s).";
+  }
+
+  // A window aggregate function might be defined OVER a window name or a window.
+  E::WindowAggregateFunctionPtr window_aggregate_function;
+  if (parse_function_call.window_name() != nullptr) {
+    window_aggregate_function =
+        E::WindowAggregateFunction::Create(*window_aggregate,
+                                           resolved_arguments,
+                                           parse_function_call.window_name()->value(),
+                                           parse_function_call.is_distinct());
+  }
+  else {
+    E::WindowInfo resolved_window = resolveWindow(*parse_function_call.window(),
+                                                  expression_resolution_info->name_resolver);
+    window_aggregate_function =
+        E::WindowAggregateFunction::Create(*window_aggregate,
+                                           resolved_arguments,
+                                           &resolved_window,
+                                           parse_function_call.is_distinct());
+  }
+
+  const std::string internal_alias = GenerateAggregateAttributeAlias(
+      expression_resolution_info->query_aggregation_info->aggregate_expressions.size());
+  const E::AliasPtr aggregate_alias = E::Alias::Create(context_->nextExprId(),
+                                                       window_aggregate_function,
+                                                       "" /* attribute_name */,
+                                                       internal_alias,
+                                                       "$window_aggregate" /* relation_name */);
+                                                       
+  expression_resolution_info->window_aggregate_expressions.emplace_back(aggregate_alias);
+  expression_resolution_info->parse_window_aggregate_expression = &parse_function_call;
+  return E::ToRef(aggregate_alias);
+}
+    
 std::vector<E::PredicatePtr> Resolver::resolvePredicates(
     const PtrList<ParsePredicate> &parse_predicates,
     ExpressionResolutionInfo *expression_resolution_info) {
@@ -2794,6 +3074,10 @@ void Resolver::rewriteIfOrdinalReference(
   }
 }
 
+std::string Resolver::GenerateWindowAggregateAttributeAlias(int index) {
+  return std::string("$window_aggregate").append(std::to_string(index));
+}
+
 std::string Resolver::GenerateAggregateAttributeAlias(int index) {
   return std::string("$aggregate").append(std::to_string(index));
 }

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/ae66fbe4/query_optimizer/resolver/Resolver.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/Resolver.hpp b/query_optimizer/resolver/Resolver.hpp
index a84c61c..1c7dad5 100644
--- a/query_optimizer/resolver/Resolver.hpp
+++ b/query_optimizer/resolver/Resolver.hpp
@@ -29,6 +29,7 @@
 #include "query_optimizer/expressions/Predicate.hpp"
 #include "query_optimizer/expressions/SubqueryExpression.hpp"
 #include "query_optimizer/expressions/Scalar.hpp"
+#include "query_optimizer/expressions/WindowAggregateFunction.hpp"
 #include "query_optimizer/logical/Logical.hpp"
 #include "utility/Macros.hpp"
 #include "utility/PtrVector.hpp"
@@ -65,6 +66,7 @@ class ParseSubqueryExpression;
 class ParseTableReference;
 class ParseTableReferenceSignature;
 class ParseTreeNode;
+class ParseWindow;
 template <class T>
 class PtrList;
 class StorageBlockLayoutDescription;
@@ -123,6 +125,11 @@ class Resolver {
   struct QueryAggregationInfo;
 
   /**
+   * @brief A wrapper for resolved window and the corresponding sorted plan.
+   **/
+  struct WindowAggregationInfo;
+
+  /**
    * @brief Query-scoped info that contains select-list expressions
    *        and whether an expression is referenced by an
    *        ordinal or alias reference.
@@ -412,7 +419,8 @@ class Resolver {
    * @brief Resolves a function call. For a non-scalar function, the returned
    *        expression is an AttributeReference to the actual resolved expression.
    *
-   * @note This currently only handles resolving aggregate functions.
+   * @note This currently only handles resolving aggregate functions and window
+   *       aggregate functions.
    *
    * @param parse_function_call The function call to be resolved.
    * @param expression_resolution_info Resolution info that contains the name
@@ -425,6 +433,19 @@ class Resolver {
       ExpressionResolutionInfo *expression_resolution_info);
 
   /**
+   * @brief Resolves a window aggregate function.
+   *
+   * @param parse_function_call The function call to be resolved.
+   * @param expression_resolution_info Resolution info that contains the name
+   *                                   resolver and info to be updated after
+   *                                   resolution.
+   * @return An expression in the query optimizer.
+   */
+  expressions::ScalarPtr resolveWindowAggregateFunction(
+      const ParseFunctionCall &parse_function_call,
+      ExpressionResolutionInfo *expression_resolution_info);
+
+  /**
    * @brief Resolves a parse Predicate and converts it to a predicate in the
    *        query optimizer.
    *
@@ -469,6 +490,15 @@ class Resolver {
       const bool has_single_column);
 
   /**
+   * @brief Resolves a window definition.
+   *
+   * @param parse_window The parsed window definition.
+   * @param name_resolver The resolver to resolve names.
+   **/
+  expressions::WindowInfo resolveWindow(const ParseWindow &parse_window,
+                                        const NameResolver &name_resolver);
+
+  /**
    * @brief Resolves a relation name to a pointer to the corresponding
    *        CatalogRelation with the name.
    *
@@ -501,6 +531,15 @@ class Resolver {
   static std::string GenerateAggregateAttributeAlias(int index);
 
   /**
+   * @brief Generates an internal alias for a window aggregate attribute.
+   *
+   * @param index The index of the window aggregate attribute used for
+   *              generating the name.
+   * @return A string for the name.
+   */
+  static std::string GenerateWindowAggregateAttributeAlias(int index);
+
+  /**
    * @brief Generates an internal alias for a grouping attribute.
    *
    * @param index The index of the grouping attribute used for generating the