You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@quickstep.apache.org by zu...@apache.org on 2016/06/25 02:01:45 UTC
incubator-quickstep git commit: Added Window Aggregation Function in
optimizer.
Repository: incubator-quickstep
Updated Branches:
refs/heads/master d64289148 -> 714874ce5
Added Window Aggregation Function in optimizer.
- The resolver could understand optional window clause w/ 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/714874ce
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/714874ce
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/714874ce
Branch: refs/heads/master
Commit: 714874ce54e12972285a43f92784ef6954a8b6fd
Parents: d642891
Author: shixuan <sh...@wisc.edu>
Authored: Tue Jun 21 20:08:52 2016 +0000
Committer: Zuyu Zhang <zu...@apache.org>
Committed: Fri Jun 24 18:59:47 2016 -0700
----------------------------------------------------------------------
query_optimizer/expressions/CMakeLists.txt | 17 +-
query_optimizer/expressions/ExpressionType.hpp | 3 +-
query_optimizer/expressions/PatternMatcher.hpp | 3 +
.../expressions/WindowAggregateFunction.cpp | 193 ++++++++++++
.../expressions/WindowAggregateFunction.hpp | 246 +++++++++++++++
query_optimizer/logical/CMakeLists.txt | 18 +-
query_optimizer/logical/LogicalType.hpp | 3 +-
query_optimizer/logical/PatternMatcher.hpp | 2 +
query_optimizer/logical/WindowAggregate.cpp | 85 +++++
query_optimizer/logical/WindowAggregate.hpp | 123 ++++++++
query_optimizer/resolver/CMakeLists.txt | 2 +
query_optimizer/resolver/Resolver.cpp | 314 ++++++++++++++++++-
query_optimizer/resolver/Resolver.hpp | 66 +++-
query_optimizer/strategy/CMakeLists.txt | 3 +-
query_optimizer/strategy/OneToOne.cpp | 5 +
.../tests/logical_generator/Select.test | 162 ++++++++++
query_optimizer/tests/resolver/Select.test | 162 ++++++++++
17 files changed, 1387 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/expressions/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/CMakeLists.txt b/query_optimizer/expressions/CMakeLists.txt
index 6c40741..08d7df5 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
@@ -301,6 +302,19 @@ target_link_libraries(quickstep_queryoptimizer_expressions_UnaryExpression
quickstep_types_operations_unaryoperations_UnaryOperation
quickstep_types_operations_unaryoperations_UnaryOperationID
quickstep_utility_Macros)
+target_link_libraries(quickstep_queryoptimizer_expressions_WindowAggregateFunction
+ glog
+ quickstep_expressions_aggregation_AggregateFunction
+ quickstep_queryoptimizer_OptimizerTree
+ quickstep_queryoptimizer_expressions_AttributeReference
+ quickstep_queryoptimizer_expressions_Expression
+ quickstep_queryoptimizer_expressions_ExpressionType
+ quickstep_queryoptimizer_expressions_PatternMatcher
+ quickstep_queryoptimizer_expressions_Scalar
+ quickstep_types_Type
+ quickstep_utility_Cast
+ quickstep_utility_Macros)
+
# Module all-in-one library:
add_library(quickstep_queryoptimizer_expressions ../../empty_src.cpp OptimizerExpressionsModule.hpp)
@@ -330,4 +344,5 @@ target_link_libraries(quickstep_queryoptimizer_expressions
quickstep_queryoptimizer_expressions_SearchedCase
quickstep_queryoptimizer_expressions_SimpleCase
quickstep_queryoptimizer_expressions_SubqueryExpression
- quickstep_queryoptimizer_expressions_UnaryExpression)
+ quickstep_queryoptimizer_expressions_UnaryExpression
+ quickstep_queryoptimizer_expressions_WindowAggregateFunction)
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/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/714874ce/query_optimizer/expressions/PatternMatcher.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/PatternMatcher.hpp b/query_optimizer/expressions/PatternMatcher.hpp
index 87bc52a..2cc91d6 100644
--- a/query_optimizer/expressions/PatternMatcher.hpp
+++ b/query_optimizer/expressions/PatternMatcher.hpp
@@ -52,6 +52,7 @@ class Scalar;
class ScalarLiteral;
class Sum;
class UnaryExpression;
+class WindowAggregateFunction;
/** \addtogroup OptimizerExpressions
* @{
@@ -155,6 +156,8 @@ using SomeScalar = SomeExpressionNode<Scalar,
ExpressionType::kUnaryExpression>;
using SomeScalarLiteral = SomeExpressionNode<ScalarLiteral, ExpressionType::kScalarLiteral>;
using SomeUnaryExpression = SomeExpressionNode<UnaryExpression, ExpressionType::kUnaryExpression>;
+using SomeWindowAggregateFunction = SomeExpressionNode<WindowAggregateFunction,
+ ExpressionType::kWindowAggregateFunction>;
using SomeAggregateFunction = SomeExpressionNode<AggregateFunction,
ExpressionType::kAggregateFunction>;
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/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..7b1f304
--- /dev/null
+++ b/query_optimizer/expressions/WindowAggregateFunction.cpp
@@ -0,0 +1,193 @@
+/**
+ * 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 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, window_info, 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 WindowAggregateFunctionPtr(
+ new WindowAggregateFunction(window_aggregate_,
+ new_arguments,
+ window_info_,
+ window_name_,
+ 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());
+ }
+
+ referenced_attributes.insert(referenced_attributes.end(),
+ window_info_.partition_by_attributes.begin(),
+ window_info_.partition_by_attributes.end());
+
+ referenced_attributes.insert(referenced_attributes.end(),
+ window_info_.order_by_attributes.begin(),
+ window_info_.order_by_attributes.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());
+
+ container_child_field_names->push_back("arguments");
+ container_child_fields->emplace_back(CastSharedPtrVector<OptimizerTreeBase>(arguments_));
+
+ inline_field_names->push_back("window_name");
+ inline_field_values->push_back(window_name_);
+
+ container_child_field_names->push_back("partition_by");
+ container_child_fields->emplace_back(
+ CastSharedPtrVector<OptimizerTreeBase>(window_info_.partition_by_attributes));
+
+ container_child_field_names->push_back("order_by");
+ container_child_fields->emplace_back(
+ CastSharedPtrVector<OptimizerTreeBase>(window_info_.order_by_attributes));
+
+ inline_field_names->push_back("is_ascending");
+ std::string ascending_list("[");
+ for (const bool is_ascending : window_info_.order_by_directions) {
+ if (is_ascending) {
+ ascending_list.append("true,");
+ } else {
+ ascending_list.append("false,");
+ }
+ }
+ if (!window_info_.order_by_directions.empty()) {
+ ascending_list.pop_back();
+ }
+ ascending_list.append("]");
+ inline_field_values->push_back(ascending_list);
+
+ inline_field_names->push_back("nulls_first");
+ std::string nulls_first_flags("[");
+ for (const bool nulls_first_flag : window_info_.nulls_first) {
+ if (nulls_first_flag) {
+ nulls_first_flags.append("true,");
+ } else {
+ nulls_first_flags.append("false,");
+ }
+ }
+ if (!window_info_.nulls_first.empty()) {
+ nulls_first_flags.pop_back();
+ }
+ nulls_first_flags.append("]");
+ inline_field_values->push_back(nulls_first_flags);
+
+ if (window_info_.frame_info != nullptr) {
+ const WindowFrameInfo *frame_info = window_info_.frame_info;
+
+ inline_field_names->push_back("frame_mode");
+ inline_field_values->push_back(frame_info->is_row ? "row" : "range");
+
+ inline_field_names->push_back("num_preceding");
+ inline_field_values->push_back(std::to_string(frame_info->num_preceding));
+
+ inline_field_names->push_back("num_following");
+ inline_field_values->push_back(std::to_string(frame_info->num_following));
+ }
+
+ if (is_distinct_) {
+ inline_field_names->push_back("is_distinct");
+ inline_field_values->push_back("true");
+ }
+}
+
+} // namespace expressions
+} // namespace optimizer
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/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..0bee28f
--- /dev/null
+++ b/query_optimizer/expressions/WindowAggregateFunction.hpp
@@ -0,0 +1,246 @@
+/**
+ * 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.
+ **/
+ 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.
+ **/
+ 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),
+ order_by_directions(order_by_directions_in),
+ nulls_first(nulls_first_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& window_aggregate() const {
+ return window_aggregate_;
+ }
+
+ /**
+ * @return The list of scalar arguments to this aggregate.
+ **/
+ inline const std::vector<ScalarPtr>& arguments() const {
+ return arguments_;
+ }
+
+ /**
+ * @return The window info of this window aggregate function.
+ **/
+ inline const WindowInfo window_info() const {
+ return window_info_;
+ }
+
+ /**
+ * @return The name of the window.
+ **/
+ inline const std::string window_name() const {
+ return window_name_;
+ }
+
+ /**
+ * @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 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_WINDOW_AGGREGATE_FUNCTION_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/logical/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/logical/CMakeLists.txt b/query_optimizer/logical/CMakeLists.txt
index 61c6234..b787c60 100644
--- a/query_optimizer/logical/CMakeLists.txt
+++ b/query_optimizer/logical/CMakeLists.txt
@@ -43,6 +43,7 @@ add_library(quickstep_queryoptimizer_logical_TableReference TableReference.cpp T
add_library(quickstep_queryoptimizer_logical_TableGenerator ../../empty_src.cpp TableGenerator.hpp)
add_library(quickstep_queryoptimizer_logical_TopLevelPlan TopLevelPlan.cpp TopLevelPlan.hpp)
add_library(quickstep_queryoptimizer_logical_UpdateTable UpdateTable.cpp UpdateTable.hpp)
+add_library(quickstep_queryoptimizer_logical_WindowAggregate WindowAggregate.cpp WindowAggregate.hpp)
# Link dependencies:
target_link_libraries(quickstep_queryoptimizer_logical_Aggregate
@@ -259,6 +260,20 @@ target_link_libraries(quickstep_queryoptimizer_logical_UpdateTable
quickstep_queryoptimizer_logical_LogicalType
quickstep_utility_Cast
quickstep_utility_Macros)
+target_link_libraries(quickstep_queryoptimizer_logical_WindowAggregate
+ glog
+ quickstep_queryoptimizer_expressions_Alias
+ quickstep_queryoptimizer_expressions_AttributeReference
+ quickstep_queryoptimizer_expressions_Expression
+ quickstep_queryoptimizer_expressions_ExpressionUtil
+ quickstep_queryoptimizer_expressions_NamedExpression
+ quickstep_queryoptimizer_expressions_PatternMatcher
+ quickstep_queryoptimizer_logical_Logical
+ quickstep_queryoptimizer_logical_LogicalType
+ quickstep_queryoptimizer_OptimizerTree
+ quickstep_utility_Cast
+ quickstep_utility_Macros)
+
# Module all-in-one library:
add_library(quickstep_queryoptimizer_logical ../../empty_src.cpp OptimizerLogicalModule.hpp)
@@ -287,4 +302,5 @@ target_link_libraries(quickstep_queryoptimizer_logical
quickstep_queryoptimizer_logical_TableGenerator
quickstep_queryoptimizer_logical_TableReference
quickstep_queryoptimizer_logical_TopLevelPlan
- quickstep_queryoptimizer_logical_UpdateTable)
+ quickstep_queryoptimizer_logical_UpdateTable
+ quickstep_queryoptimizer_logical_WindowAggregate)
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/logical/LogicalType.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/logical/LogicalType.hpp b/query_optimizer/logical/LogicalType.hpp
index 1b9366e..c82fb47 100644
--- a/query_optimizer/logical/LogicalType.hpp
+++ b/query_optimizer/logical/LogicalType.hpp
@@ -49,7 +49,8 @@ enum class LogicalType {
kTableGenerator,
kTableReference,
kTopLevelPlan,
- kUpdateTable
+ kUpdateTable,
+ kWindowAggregate
};
/** @} */
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/logical/PatternMatcher.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/logical/PatternMatcher.hpp b/query_optimizer/logical/PatternMatcher.hpp
index ff8f3d0..de8609e 100644
--- a/query_optimizer/logical/PatternMatcher.hpp
+++ b/query_optimizer/logical/PatternMatcher.hpp
@@ -45,6 +45,7 @@ class Sort;
class TableReference;
class TopLevelPlan;
class UpdateTable;
+class WindowAggregate;
/** \addtogroup OptimizerLogical
* @{
@@ -130,6 +131,7 @@ using SomeSort = SomeLogicalNode<Sort, LogicalType::kSort>;
using SomeTableReference = SomeLogicalNode<TableReference, LogicalType::kTableReference>;
using SomeTopLevelPlan = SomeLogicalNode<TopLevelPlan, LogicalType::kTopLevelPlan>;
using SomeUpdateTable = SomeLogicalNode<UpdateTable, LogicalType::kUpdateTable>;
+using SomeWindowAggregate = SomeLogicalNode<WindowAggregate, LogicalType::kWindowAggregate>;
/** @} */
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/logical/WindowAggregate.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/logical/WindowAggregate.cpp b/query_optimizer/logical/WindowAggregate.cpp
new file mode 100644
index 0000000..0d747b6
--- /dev/null
+++ b/query_optimizer/logical/WindowAggregate.cpp
@@ -0,0 +1,85 @@
+/**
+ * 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.
+ **/
+
+#include "query_optimizer/logical/WindowAggregate.hpp"
+
+#include <string>
+#include <vector>
+
+#include "query_optimizer/OptimizerTree.hpp"
+#include "query_optimizer/expressions/Alias.hpp"
+#include "query_optimizer/expressions/AttributeReference.hpp"
+#include "query_optimizer/expressions/ExpressionUtil.hpp"
+#include "query_optimizer/expressions/NamedExpression.hpp"
+#include "query_optimizer/expressions/PatternMatcher.hpp"
+#include "utility/Cast.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+namespace optimizer {
+namespace logical {
+
+namespace E = ::quickstep::optimizer::expressions;
+
+LogicalPtr WindowAggregate::copyWithNewChildren(
+ const std::vector<LogicalPtr> &new_children) const {
+ DCHECK_EQ(getNumChildren(), new_children.size());
+ return Create(new_children[0], window_aggregate_expression_);
+}
+
+std::vector<E::AttributeReferencePtr> WindowAggregate::getOutputAttributes() const {
+ std::vector<E::AttributeReferencePtr> output_attributes(input_->getOutputAttributes());
+ output_attributes.push_back(E::ToRef(window_aggregate_expression_));
+ return output_attributes;
+}
+
+std::vector<E::AttributeReferencePtr> WindowAggregate::getReferencedAttributes() const {
+ return window_aggregate_expression_->getReferencedAttributes();
+}
+
+LogicalPtr WindowAggregate::copyWithNewInputExpressions(
+ const std::vector<E::ExpressionPtr> &input_expressions) const {
+ // Only one expression needed
+ DCHECK_EQ(1u, input_expressions.size());
+
+ E::AliasPtr window_aggregate_expression;
+ E::SomeAlias::MatchesWithConditionalCast(input_expressions[0],
+ &window_aggregate_expression);
+
+ return Create(input_, window_aggregate_expression);
+}
+
+void WindowAggregate::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 {
+ non_container_child_field_names->push_back("input");
+ non_container_child_fields->push_back(input_);
+
+ non_container_child_field_names->push_back("window_aggregate_expression");
+ non_container_child_fields->push_back(window_aggregate_expression_);
+}
+
+} // namespace logical
+} // namespace optimizer
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/logical/WindowAggregate.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/logical/WindowAggregate.hpp b/query_optimizer/logical/WindowAggregate.hpp
new file mode 100644
index 0000000..dcd9a7d
--- /dev/null
+++ b/query_optimizer/logical/WindowAggregate.hpp
@@ -0,0 +1,123 @@
+/**
+ * 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_LOGICAL_WINDOW_AGGREGATE_HPP_
+#define QUICKSTEP_QUERY_OPTIMIZER_LOGICAL_WINDOW_AGGREGATE_HPP_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "query_optimizer/OptimizerTree.hpp"
+#include "query_optimizer/expressions/Alias.hpp"
+#include "query_optimizer/expressions/AttributeReference.hpp"
+#include "query_optimizer/expressions/Expression.hpp"
+#include "query_optimizer/expressions/NamedExpression.hpp"
+#include "query_optimizer/logical/Logical.hpp"
+#include "query_optimizer/logical/LogicalType.hpp"
+#include "utility/Macros.hpp"
+
+namespace quickstep {
+namespace optimizer {
+namespace logical {
+
+/** \addtogroup OptimizerLogical
+ * @{
+ */
+
+class WindowAggregate;
+typedef std::shared_ptr<const WindowAggregate> WindowAggregatePtr;
+
+/**
+ * @brief Window aggregate operator that computes window aggregate expressions.
+ */
+class WindowAggregate : public Logical {
+ public:
+ LogicalType getLogicalType() const override {
+ return LogicalType::kWindowAggregate;
+ }
+
+ std::string getName() const override { return "WindowAggregate"; }
+
+ /**
+ * @return The input logical node.
+ */
+ const LogicalPtr& input() const { return input_; }
+
+ /**
+ * @return PARTITION BY expressions.
+ */
+ const expressions::AliasPtr window_aggregate_expression() const {
+ return window_aggregate_expression_;
+ }
+
+ LogicalPtr copyWithNewChildren(
+ const std::vector<LogicalPtr> &new_children) const override;
+
+ LogicalPtr copyWithNewInputExpressions(
+ const std::vector<expressions::ExpressionPtr> &input_expressions) const override;
+
+ std::vector<expressions::AttributeReferencePtr> getOutputAttributes() const override;
+
+ std::vector<expressions::AttributeReferencePtr> getReferencedAttributes() const override;
+
+ /**
+ * @brief Creates an Aggregate logical node.
+ *
+ * @param input The input node.
+ * @param window_aggregate_expression The window aggregate expression.
+ * @return An immutable WindowAggregate node.
+ */
+ static WindowAggregatePtr Create(
+ const LogicalPtr &input,
+ const expressions::AliasPtr &window_aggregate_expression) {
+ return WindowAggregatePtr(new WindowAggregate(input, window_aggregate_expression));
+ }
+
+ 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:
+ WindowAggregate(const LogicalPtr &input,
+ const expressions::AliasPtr &window_aggregate_expression)
+ : input_(input),
+ window_aggregate_expression_(window_aggregate_expression) {
+ addChild(input_);
+ addInputExpression(window_aggregate_expression_);
+ }
+
+ const LogicalPtr input_;
+ const expressions::AliasPtr window_aggregate_expression_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowAggregate);
+};
+
+/** @} */
+
+} // namespace logical
+} // namespace optimizer
+} // namespace quickstep
+
+#endif // QUICKSTEP_QUERY_OPTIMIZER_LOGICAL_WINDOW_AGGREGATE_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/resolver/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/CMakeLists.txt b/query_optimizer/resolver/CMakeLists.txt
index dc7eac0..fb75767 100644
--- a/query_optimizer/resolver/CMakeLists.txt
+++ b/query_optimizer/resolver/CMakeLists.txt
@@ -89,6 +89,7 @@ target_link_libraries(quickstep_queryoptimizer_resolver_Resolver
quickstep_queryoptimizer_expressions_SimpleCase
quickstep_queryoptimizer_expressions_SubqueryExpression
quickstep_queryoptimizer_expressions_UnaryExpression
+ quickstep_queryoptimizer_expressions_WindowAggregateFunction
quickstep_queryoptimizer_logical_Aggregate
quickstep_queryoptimizer_logical_CopyFrom
quickstep_queryoptimizer_logical_CreateIndex
@@ -109,6 +110,7 @@ target_link_libraries(quickstep_queryoptimizer_resolver_Resolver
quickstep_queryoptimizer_logical_TableReference
quickstep_queryoptimizer_logical_TopLevelPlan
quickstep_queryoptimizer_logical_UpdateTable
+ quickstep_queryoptimizer_logical_WindowAggregate
quickstep_queryoptimizer_resolver_NameResolver
quickstep_storage_StorageBlockLayout_proto
quickstep_storage_StorageConstants
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/resolver/Resolver.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/Resolver.cpp b/query_optimizer/resolver/Resolver.cpp
index ffc173a..f880ce7 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"
@@ -104,6 +105,7 @@
#include "query_optimizer/logical/TableReference.hpp"
#include "query_optimizer/logical/TopLevelPlan.hpp"
#include "query_optimizer/logical/UpdateTable.hpp"
+#include "query_optimizer/logical/WindowAggregate.hpp"
#include "query_optimizer/resolver/NameResolver.hpp"
#include "storage/StorageBlockLayout.pb.h"
#include "storage/StorageConstants.hpp"
@@ -164,9 +166,11 @@ struct Resolver::ExpressionResolutionInfo {
*/
ExpressionResolutionInfo(const NameResolver &name_resolver_in,
QueryAggregationInfo *query_aggregation_info_in,
+ WindowAggregationInfo *window_aggregation_info_in,
SelectListInfo *select_list_info_in)
: name_resolver(name_resolver_in),
query_aggregation_info(query_aggregation_info_in),
+ window_aggregation_info(window_aggregation_info_in),
select_list_info(select_list_info_in) {}
/**
@@ -180,6 +184,7 @@ struct Resolver::ExpressionResolutionInfo {
: name_resolver(parent.name_resolver),
not_allow_aggregate_here(parent.not_allow_aggregate_here),
query_aggregation_info(parent.query_aggregation_info),
+ window_aggregation_info(parent.window_aggregation_info),
select_list_info(parent.select_list_info) {}
/**
@@ -187,16 +192,29 @@ 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;
// Can be NULL if aggregations are not allowed.
QueryAggregationInfo *query_aggregation_info = nullptr;
+
+ // Alias expressions that wraps window aggregate functions.
+ WindowAggregationInfo *window_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 +227,26 @@ struct Resolver::QueryAggregationInfo {
std::vector<E::AliasPtr> aggregate_expressions;
};
+struct Resolver::WindowPlan {
+ WindowPlan(const E::WindowInfo &window_info_in,
+ const 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::WindowAggregationInfo {
+ explicit WindowAggregationInfo(const std::unordered_map<std::string, WindowPlan> &window_map_in)
+ : window_map(window_map_in) {}
+
+ // Whether the current query block has a GROUP BY.
+ const std::unordered_map<std::string, WindowPlan> window_map;
+ // Alias expressions that wraps window aggregate functions.
+ std::vector<E::AliasPtr> window_aggregate_expressions;
+};
+
struct Resolver::SelectListInfo {
public:
/**
@@ -973,8 +1011,36 @@ L::LogicalPtr Resolver::resolveSelect(
logical_plan, resolvePredicate(parse_predicate, &expr_resolution_info));
}
+ // Resolve WINDOW clause.
+ std::unordered_map<std::string, WindowPlan> sorted_window_map;
+ 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";
+ }
+
+ // Sort the table according to the window.
+ for (const ParseWindow &window : *select_query.window_list()) {
+ // Check for duplicate definition.
+ // Currently this is useless since we only support one window.
+ if (sorted_window_map.find(window.name()->value()) != sorted_window_map.end()) {
+ THROW_SQL_ERROR_AT(window.name())
+ << "Duplicate definition of window " << window.name()->value();
+ }
+
+ E::WindowInfo resolved_window = resolveWindow(window, *name_resolver);
+ L::LogicalPtr sorted_logical_plan = resolveSortInWindow(logical_plan,
+ resolved_window);
+
+ WindowPlan window_plan(resolved_window, sorted_logical_plan);
+
+ sorted_window_map.emplace(window.name()->value(), window_plan);
+ }
+ }
+
QueryAggregationInfo query_aggregation_info(
(select_query.group_by() != nullptr));
+ WindowAggregationInfo window_aggregation_info(sorted_window_map);
// Resolve SELECT-list clause.
std::vector<E::NamedExpressionPtr> select_list_expressions;
@@ -984,6 +1050,7 @@ L::LogicalPtr Resolver::resolveSelect(
type_hints,
*name_resolver,
&query_aggregation_info,
+ &window_aggregation_info,
&select_list_expressions,
&has_aggregate_per_expression);
DCHECK_EQ(has_aggregate_per_expression.size(),
@@ -992,6 +1059,29 @@ L::LogicalPtr Resolver::resolveSelect(
SelectListInfo select_list_info(select_list_expressions,
has_aggregate_per_expression);
+ // Create window aggregate node if needed
+ for (const E::AliasPtr &alias : window_aggregation_info.window_aggregate_expressions) {
+ E::WindowAggregateFunctionPtr window_aggregate_function;
+ if (!E::SomeWindowAggregateFunction::MatchesWithConditionalCast(alias->expression(),
+ &window_aggregate_function)) {
+ THROW_SQL_ERROR()
+ << "Unexpected expression in window aggregation function";
+ }
+ L::LogicalPtr sorted_logical_plan;
+
+ // Get the sorted logical plan
+ const std::string window_name = window_aggregate_function->window_name();
+ if (!window_name.empty()) {
+ sorted_logical_plan = sorted_window_map.at(window_name).logical_plan;
+ } else {
+ sorted_logical_plan = resolveSortInWindow(logical_plan,
+ window_aggregate_function->window_info());
+ }
+
+ logical_plan = L::WindowAggregate::Create(sorted_logical_plan,
+ alias);
+ }
+
// Resolve GROUP BY.
std::vector<E::NamedExpressionPtr> group_by_expressions;
if (select_query.group_by() != nullptr) {
@@ -1039,7 +1129,7 @@ L::LogicalPtr Resolver::resolveSelect(
E::PredicatePtr having_predicate;
if (select_query.having() != nullptr) {
ExpressionResolutionInfo expr_resolution_info(
- *name_resolver, &query_aggregation_info, &select_list_info);
+ *name_resolver, &query_aggregation_info, &window_aggregation_info, &select_list_info);
having_predicate = resolvePredicate(
*select_query.having()->having_predicate(), &expr_resolution_info);
}
@@ -1053,7 +1143,7 @@ L::LogicalPtr Resolver::resolveSelect(
for (const ParseOrderByItem &order_by_item :
*select_query.order_by()->order_by_items()) {
ExpressionResolutionInfo expr_resolution_info(
- *name_resolver, &query_aggregation_info, &select_list_info);
+ *name_resolver, &query_aggregation_info, &window_aggregation_info, &select_list_info);
E::ScalarPtr order_by_scalar = resolveExpression(
*order_by_item.ordering_expression(),
nullptr, // No Type hint.
@@ -1528,6 +1618,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 =
@@ -1684,13 +1857,45 @@ L::LogicalPtr Resolver::resolveJoinedTableReference(
THROW_SQL_ERROR_AT(&joined_table_reference) << "Full outer join is not supported yet";
}
+L::LogicalPtr Resolver::resolveSortInWindow(
+ const L::LogicalPtr &logical_plan,
+ const E::WindowInfo &window_info) {
+ // Sort the table by (p_key, o_key)
+ std::vector<E::AttributeReferencePtr> sort_attributes(window_info.partition_by_attributes);
+ sort_attributes.insert(sort_attributes.end(),
+ window_info.order_by_attributes.begin(),
+ window_info.order_by_attributes.end());
+
+ std::vector<bool> sort_directions(
+ window_info.partition_by_attributes.size(), true);
+ sort_directions.insert(sort_directions.end(),
+ window_info.order_by_directions.begin(),
+ window_info.order_by_directions.end());
+
+ std::vector<bool> sort_nulls_first(
+ window_info.partition_by_attributes.size(), false);
+ sort_nulls_first.insert(sort_nulls_first.end(),
+ window_info.nulls_first.begin(),
+ window_info.nulls_first.end());
+
+ L::LogicalPtr sorted_logical_plan =
+ L::Sort::Create(logical_plan,
+ sort_attributes,
+ sort_directions,
+ sort_nulls_first,
+ -1 /* limit */);
+
+ return sorted_logical_plan;
+}
+
void Resolver::resolveSelectClause(
const ParseSelectionClause &parse_selection,
const std::string &select_name,
const std::vector<const Type*> *type_hints,
const NameResolver &name_resolver,
QueryAggregationInfo *query_aggregation_info,
- std::vector<expressions::NamedExpressionPtr> *project_expressions,
+ WindowAggregationInfo *window_aggregation_info,
+ std::vector<E::NamedExpressionPtr> *project_expressions,
std::vector<bool> *has_aggregate_per_expression) {
project_expressions->clear();
switch (parse_selection.getSelectionType()) {
@@ -1720,6 +1925,7 @@ void Resolver::resolveSelectClause(
ExpressionResolutionInfo expr_resolution_info(
name_resolver,
query_aggregation_info,
+ window_aggregation_info,
nullptr /* select_list_info */);
const E::ScalarPtr project_scalar =
resolveExpression(*parse_project_expression,
@@ -2362,16 +2568,12 @@ 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.
- if (parse_function_call.isWindow()) {
- THROW_SQL_ERROR_AT(&parse_function_call)
- << "Window Aggregation Function is not supported currently";
- }
+ const std::string function_name = ToLower(parse_function_call.name()->value());
// First check for the special case COUNT(*).
bool count_star = false;
@@ -2386,8 +2588,9 @@ E::ScalarPtr Resolver::resolveFunctionCall(
std::vector<E::ScalarPtr> resolved_arguments;
const PtrList<ParseExpression> *unresolved_arguments =
parse_function_call.arguments();
- // The first aggregate function in the arguments.
+ // The first aggregate function and window 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(
@@ -2401,6 +2604,13 @@ E::ScalarPtr Resolver::resolveFunctionCall(
first_aggregate_function =
expr_resolution_info.parse_aggregate_expression;
}
+
+ if (expr_resolution_info.hasWindowAggregate() &&
+ first_window_aggregate_function == nullptr &&
+ parse_function_call.isWindow()) {
+ first_window_aggregate_function =
+ expr_resolution_info.parse_window_aggregate_expression;
+ }
}
}
@@ -2431,6 +2641,15 @@ E::ScalarPtr Resolver::resolveFunctionCall(
<< "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 (parse_function_call.isWindow() &&
+ first_window_aggregate_function != nullptr) {
+ THROW_SQL_ERROR_AT(first_window_aggregate_function)
+ << "Window aggregation of window aggregates is not allowed";
+ }
+
// Make sure a naked COUNT() with no arguments wasn't specified.
if ((aggregate->getAggregationID() == AggregationID::kCount)
&& (resolved_arguments.empty())
@@ -2452,6 +2671,13 @@ E::ScalarPtr Resolver::resolveFunctionCall(
<< " can not apply to the given argument(s).";
}
+ if (parse_function_call.isWindow()) {
+ return resolveWindowAggregateFunction(parse_function_call,
+ expression_resolution_info,
+ aggregate,
+ resolved_arguments);
+ }
+
// Create the optimizer representation of the resolved aggregate and an alias
// for it to appear in the output relation.
const E::AggregateFunctionPtr aggregate_function
@@ -2471,6 +2697,62 @@ E::ScalarPtr Resolver::resolveFunctionCall(
return E::ToRef(aggregate_alias);
}
+E::ScalarPtr Resolver::resolveWindowAggregateFunction(
+ const ParseFunctionCall &parse_function_call,
+ ExpressionResolutionInfo *expression_resolution_info,
+ const ::quickstep::AggregateFunction *window_aggregate,
+ const std::vector<E::ScalarPtr> &resolved_arguments) {
+ // 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) {
+ std::unordered_map<std::string, WindowPlan> window_map
+ = expression_resolution_info->window_aggregation_info->window_map;
+ std::string window_name = parse_function_call.window_name()->value();
+ std::unordered_map<std::string, WindowPlan>::const_iterator map_it
+ = window_map.find(window_name);
+
+ if (map_it == window_map.end()) {
+ THROW_SQL_ERROR_AT(parse_function_call.window_name())
+ << "Undefined window " << window_name;
+ }
+
+ window_aggregate_function =
+ E::WindowAggregateFunction::Create(*window_aggregate,
+ resolved_arguments,
+ map_it->second.window_info,
+ 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,
+ "" /* window name */,
+ parse_function_call.is_distinct());
+ }
+
+ const std::string internal_alias = GenerateWindowAggregateAttributeAlias(
+ 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 */);
+
+ if (!expression_resolution_info->window_aggregation_info->window_aggregate_expressions.empty()) {
+ THROW_SQL_ERROR_AT(&parse_function_call)
+ << "Currently we only support single window aggregate in the query";
+ }
+
+ expression_resolution_info->window_aggregation_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,16 +3076,20 @@ void Resolver::rewriteIfOrdinalReference(
}
}
+std::string Resolver::GenerateWindowAggregateAttributeAlias(int index) {
+ return "$window_aggregate" + std::to_string(index);
+}
+
std::string Resolver::GenerateAggregateAttributeAlias(int index) {
- return std::string("$aggregate").append(std::to_string(index));
+ return "$aggregate" + std::to_string(index);
}
std::string Resolver::GenerateGroupingAttributeAlias(int index) {
- return std::string("$groupby").append(std::to_string(index));
+ return "$groupby" + std::to_string(index);
}
std::string Resolver::GenerateOrderingAttributeAlias(int index) {
- return std::string("$orderby").append(std::to_string(index));
+ return "$orderby" + std::to_string(index);
}
} // namespace resolver
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/resolver/Resolver.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/Resolver.hpp b/query_optimizer/resolver/Resolver.hpp
index a84c61c..f4024e9 100644
--- a/query_optimizer/resolver/Resolver.hpp
+++ b/query_optimizer/resolver/Resolver.hpp
@@ -24,11 +24,13 @@
#include <vector>
#include "query_optimizer/expressions/AggregateFunction.hpp"
+#include "query_optimizer/expressions/Alias.hpp"
#include "query_optimizer/expressions/ExprId.hpp"
#include "query_optimizer/expressions/NamedExpression.hpp"
#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 +67,7 @@ class ParseSubqueryExpression;
class ParseTableReference;
class ParseTableReferenceSignature;
class ParseTreeNode;
+class ParseWindow;
template <class T>
class PtrList;
class StorageBlockLayoutDescription;
@@ -123,6 +126,17 @@ class Resolver {
struct QueryAggregationInfo;
/**
+ * @brief Query-scoped info that contains window aggregate expressions and a
+ * window map.
+ **/
+ struct WindowAggregationInfo;
+
+ /**
+ * @brief A wrapper for resolved window and the corresponding sorted plan.
+ **/
+ struct WindowPlan;
+
+ /**
* @brief Query-scoped info that contains select-list expressions
* and whether an expression is referenced by an
* ordinal or alias reference.
@@ -271,6 +285,8 @@ class Resolver {
* @param name_resolver NameResolver to resolve the relation/attribute names.
* @param query_aggregation_info Passed down to each expression to collects
* aggregate expressions.
+ * @param window_aggregate_expressions Passed down to each expressions to
+ * collects window aggregate expressions.
* @param project_expressions Converted SELECT-list expressions.
* @param has_aggregate_per_expression For each SELECT-list expression,
* indicates whether it contains
@@ -282,6 +298,7 @@ class Resolver {
const std::vector<const Type*> *type_hints,
const NameResolver &name_resolver,
QueryAggregationInfo *query_aggregation_info,
+ WindowAggregationInfo *window_aggregation_info,
std::vector<expressions::NamedExpressionPtr> *project_expressions,
std::vector<bool> *has_aggregate_per_expression);
@@ -359,6 +376,17 @@ class Resolver {
const ParseTableReferenceSignature &table_signature);
/**
+ * @brief Sort the input table in (p_key, o_key) order specified by the window.
+ *
+ * @param logical_plan The input logical node.
+ * @param window_info The window that the input table has to be sorted accordingly.
+ * @return A logical plan that sorts the table according to window_info.
+ **/
+ logical::LogicalPtr resolveSortInWindow(
+ const logical::LogicalPtr &logical_plan,
+ const expressions::WindowInfo &window_info);
+
+ /**
* @brief Resolves a parse expression and converts it to a scalar expression
* in the query optimizer. A non-scalar parse expression is resolved
* to an AttributeReference to another optimizer expression.
@@ -412,7 +440,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 +454,23 @@ 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.
+ * @param aggregate The aggregate function.
+ * @param resolved_arguments The resolved arguments.
+ * @return An expression in the query optimizer.
+ */
+ expressions::ScalarPtr resolveWindowAggregateFunction(
+ const ParseFunctionCall &parse_function_call,
+ ExpressionResolutionInfo *expression_resolution_info,
+ const ::quickstep::AggregateFunction *aggregate,
+ const std::vector<expressions::ScalarPtr> &resolved_arguments);
+
+ /**
* @brief Resolves a parse Predicate and converts it to a predicate in the
* query optimizer.
*
@@ -469,6 +515,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 +556,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
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/strategy/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/strategy/CMakeLists.txt b/query_optimizer/strategy/CMakeLists.txt
index 74f5a4b..84e151e 100644
--- a/query_optimizer/strategy/CMakeLists.txt
+++ b/query_optimizer/strategy/CMakeLists.txt
@@ -105,7 +105,8 @@ target_link_libraries(quickstep_queryoptimizer_strategy_OneToOne
quickstep_queryoptimizer_physical_TopLevelPlan
quickstep_queryoptimizer_physical_UpdateTable
quickstep_queryoptimizer_strategy_Strategy
- quickstep_utility_Macros)
+ quickstep_utility_Macros
+ quickstep_utility_SqlError)
target_link_libraries(quickstep_queryoptimizer_strategy_Selection
glog
quickstep_queryoptimizer_LogicalToPhysicalMapper
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/strategy/OneToOne.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/strategy/OneToOne.cpp b/query_optimizer/strategy/OneToOne.cpp
index 7f59151..f49a25c 100644
--- a/query_optimizer/strategy/OneToOne.cpp
+++ b/query_optimizer/strategy/OneToOne.cpp
@@ -55,6 +55,7 @@
#include "query_optimizer/physical/TableReference.hpp"
#include "query_optimizer/physical/TopLevelPlan.hpp"
#include "query_optimizer/physical/UpdateTable.hpp"
+#include "utility/SqlError.hpp"
namespace quickstep {
namespace optimizer {
@@ -208,6 +209,10 @@ bool OneToOne::generatePlan(const L::LogicalPtr &logical_input,
update_table->predicate());
return true;
}
+ case L::LogicalType::kWindowAggregate: {
+ THROW_SQL_ERROR()
+ << "Window aggregate function is not supported currently :(";
+ }
default:
return false;
}
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/tests/logical_generator/Select.test
----------------------------------------------------------------------
diff --git a/query_optimizer/tests/logical_generator/Select.test b/query_optimizer/tests/logical_generator/Select.test
index 3c152e8..e0003bf 100644
--- a/query_optimizer/tests/logical_generator/Select.test
+++ b/query_optimizer/tests/logical_generator/Select.test
@@ -1354,3 +1354,165 @@ TopLevelPlan
+-output_attributes=
+-AttributeReference[id=5,name=x,relation=,type=Int]
+-AttributeReference[id=6,name=y,relation=,type=Int]
+==
+
+# Window Aggregate Function Test.
+SELECT avg(int_col) OVER w FROM test
+WINDOW w AS
+(PARTITION BY char_col
+ ORDER BY long_col DESC NULLS LAST
+ ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW);
+--
+TopLevelPlan
++-plan=Project
+| +-input=WindowAggregate
+| | +-input=Sort[is_ascending=[true,false],nulls_first=[false,false]]
+| | | +-input=TableReference[relation_name=Test,relation_alias=test]
+| | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | | +-AttributeReference[id=2,name=float_col,relation=test,type=Float]
+| | | | +-AttributeReference[id=3,name=double_col,relation=test,type=Double NULL]
+| | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | type=VarChar(20) NULL]
+| | | +-sort_expressions=
+| | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | +-window_aggregate_expression=Alias[id=6,name=,alias=$window_aggregate0,
+| | relation=$window_aggregate,type=Double NULL]
+| | +-WindowAggregateFunction[function=AVG,window_name=w,is_ascending=[false],
+| | nulls_first=[false],frame_mode=row,num_preceding=-1,num_following=0]
+| | +-arguments=
+| | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | +-partition_by=
+| | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | +-order_by=
+| | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| +-project_list=
+| +-Alias[id=6,name=,alias=avg(int_col),relation=,type=Double NULL]
+| +-AttributeReference[id=6,name=,alias=$window_aggregate0,
+| relation=$window_aggregate,type=Double NULL]
++-output_attributes=
+ +-AttributeReference[id=6,name=,alias=avg(int_col),relation=,type=Double NULL]
+==
+
+SELECT int_col, sum(float_col) OVER
+(PARTITION BY vchar_col, long_col
+ ORDER BY double_col DESC NULLS LAST, int_col ASC NULLS FIRST
+ RANGE BETWEEN 3 PRECEDING AND 3 FOLLOWING)
+FROM test;
+--
+TopLevelPlan
++-plan=Project
+| +-input=WindowAggregate
+| | +-input=Sort[is_ascending=[true,true,false,true],
+| | | nulls_first=[false,false,false,true]]
+| | | +-input=TableReference[relation_name=Test,relation_alias=test]
+| | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | | +-AttributeReference[id=2,name=float_col,relation=test,type=Float]
+| | | | +-AttributeReference[id=3,name=double_col,relation=test,type=Double NULL]
+| | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | type=VarChar(20) NULL]
+| | | +-sort_expressions=
+| | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | type=VarChar(20) NULL]
+| | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | +-AttributeReference[id=3,name=double_col,relation=test,type=Double NULL]
+| | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | +-window_aggregate_expression=Alias[id=6,name=,alias=$window_aggregate0,
+| | relation=$window_aggregate,type=Double NULL]
+| | +-WindowAggregateFunction[function=SUM,window_name=,
+| | is_ascending=[false,true],nulls_first=[false,true],frame_mode=range,
+| | num_preceding=3,num_following=3]
+| | +-arguments=
+| | | +-AttributeReference[id=2,name=float_col,relation=test,type=Float]
+| | +-partition_by=
+| | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | type=VarChar(20) NULL]
+| | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | +-order_by=
+| | +-AttributeReference[id=3,name=double_col,relation=test,
+| | | type=Double NULL]
+| | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| +-project_list=
+| +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| +-Alias[id=6,name=,alias=sum(float_col),relation=,type=Double NULL]
+| +-AttributeReference[id=6,name=,alias=$window_aggregate0,
+| relation=$window_aggregate,type=Double NULL]
++-output_attributes=
+ +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+ +-AttributeReference[id=6,name=,alias=sum(float_col),relation=,
+ type=Double NULL]
+==
+
+SELECT sum(avg(int_col) OVER w) FROM test
+WINDOW w AS
+(PARTITION BY char_col
+ ORDER BY long_col
+ ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW);
+--
+TopLevelPlan
++-plan=Project
+| +-input=Aggregate
+| | +-input=WindowAggregate
+| | | +-input=Sort[is_ascending=[true,true],nulls_first=[false,false]]
+| | | | +-input=TableReference[relation_name=Test,relation_alias=test]
+| | | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | | | +-AttributeReference[id=2,name=float_col,relation=test,type=Float]
+| | | | | +-AttributeReference[id=3,name=double_col,relation=test,
+| | | | | | type=Double NULL]
+| | | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | | type=VarChar(20) NULL]
+| | | | +-sort_expressions=
+| | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | +-window_aggregate_expression=Alias[id=6,name=,alias=$window_aggregate0,
+| | | relation=$window_aggregate,type=Double NULL]
+| | | +-WindowAggregateFunction[function=AVG,window_name=w,
+| | | is_ascending=[true],nulls_first=[false],frame_mode=row,
+| | | num_preceding=-1,num_following=0]
+| | | +-arguments=
+| | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | | +-partition_by=
+| | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | +-order_by=
+| | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | +-grouping_expressions=
+| | | +-[]
+| | +-aggregate_expressions=
+| | +-Alias[id=7,name=,alias=$aggregate0,relation=$aggregate,type=Double NULL]
+| | +-AggregateFunction[function=SUM]
+| | +-AttributeReference[id=6,name=,alias=$window_aggregate0,
+| | relation=$window_aggregate,type=Double NULL]
+| +-project_list=
+| +-Alias[id=7,name=,alias=sum(avg(int_col)),relation=,type=Double NULL]
+| +-AttributeReference[id=7,name=,alias=$aggregate0,relation=$aggregate,
+| type=Double NULL]
++-output_attributes=
+ +-AttributeReference[id=7,name=,alias=sum(avg(int_col)),relation=,
+ type=Double NULL]
+==
+
+SELECT int_col, sum(float_col) OVER w1 FROM test
+WINDOW w2 AS
+(PARTITION BY vchar_col, long_col
+ ORDER BY double_col DESC NULLS LAST, int_col ASC NULLS FIRST
+ RANGE BETWEEN 3 PRECEDING AND 3 FOLLOWING);
+--
+ERROR: Undefined window w1 (1 : 37)
+SELECT int_col, sum(float_col) OVER w1 FROM test
+ ^
+==
+
+SELECT sum(avg(int_col)) OVER w FROM test
+WINDOW w AS
+(PARTITION BY double_col
+ ORDER BY char_col)
+--
+ERROR: Aggregation of Aggregates are not allowed (1 : 12)
+SELECT sum(avg(int_col)) OVER w FROM test
+ ^
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/714874ce/query_optimizer/tests/resolver/Select.test
----------------------------------------------------------------------
diff --git a/query_optimizer/tests/resolver/Select.test b/query_optimizer/tests/resolver/Select.test
index 141bfa0..89ab84d 100644
--- a/query_optimizer/tests/resolver/Select.test
+++ b/query_optimizer/tests/resolver/Select.test
@@ -3126,3 +3126,165 @@ FROM test;
ERROR: The substring length must be greater than 0 (1 : 8)
SELECT SUBSTRING(char_col FROM 1 FOR ...
^
+==
+
+# Window Aggregate Function Test.
+SELECT avg(int_col) OVER w FROM test
+WINDOW w AS
+(PARTITION BY char_col
+ ORDER BY long_col DESC NULLS LAST
+ ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW);
+--
+TopLevelPlan
++-plan=Project
+| +-input=WindowAggregate
+| | +-input=Sort[is_ascending=[true,false],nulls_first=[false,false]]
+| | | +-input=TableReference[relation_name=Test,relation_alias=test]
+| | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | | +-AttributeReference[id=2,name=float_col,relation=test,type=Float]
+| | | | +-AttributeReference[id=3,name=double_col,relation=test,type=Double NULL]
+| | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | type=VarChar(20) NULL]
+| | | +-sort_expressions=
+| | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | +-window_aggregate_expression=Alias[id=6,name=,alias=$window_aggregate0,
+| | relation=$window_aggregate,type=Double NULL]
+| | +-WindowAggregateFunction[function=AVG,window_name=w,is_ascending=[false],
+| | nulls_first=[false],frame_mode=row,num_preceding=-1,num_following=0]
+| | +-arguments=
+| | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | +-partition_by=
+| | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | +-order_by=
+| | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| +-project_list=
+| +-Alias[id=6,name=,alias=avg(int_col),relation=,type=Double NULL]
+| +-AttributeReference[id=6,name=,alias=$window_aggregate0,
+| relation=$window_aggregate,type=Double NULL]
++-output_attributes=
+ +-AttributeReference[id=6,name=,alias=avg(int_col),relation=,type=Double NULL]
+==
+
+SELECT int_col, sum(float_col) OVER
+(PARTITION BY vchar_col, long_col
+ ORDER BY double_col DESC NULLS LAST, int_col ASC NULLS FIRST
+ RANGE BETWEEN 3 PRECEDING AND 3 FOLLOWING)
+FROM test;
+--
+TopLevelPlan
++-plan=Project
+| +-input=WindowAggregate
+| | +-input=Sort[is_ascending=[true,true,false,true],
+| | | nulls_first=[false,false,false,true]]
+| | | +-input=TableReference[relation_name=Test,relation_alias=test]
+| | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | | +-AttributeReference[id=2,name=float_col,relation=test,type=Float]
+| | | | +-AttributeReference[id=3,name=double_col,relation=test,type=Double NULL]
+| | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | type=VarChar(20) NULL]
+| | | +-sort_expressions=
+| | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | type=VarChar(20) NULL]
+| | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | +-AttributeReference[id=3,name=double_col,relation=test,type=Double NULL]
+| | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | +-window_aggregate_expression=Alias[id=6,name=,alias=$window_aggregate0,
+| | relation=$window_aggregate,type=Double NULL]
+| | +-WindowAggregateFunction[function=SUM,window_name=,
+| | is_ascending=[false,true],nulls_first=[false,true],frame_mode=range,
+| | num_preceding=3,num_following=3]
+| | +-arguments=
+| | | +-AttributeReference[id=2,name=float_col,relation=test,type=Float]
+| | +-partition_by=
+| | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | type=VarChar(20) NULL]
+| | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | +-order_by=
+| | +-AttributeReference[id=3,name=double_col,relation=test,
+| | | type=Double NULL]
+| | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| +-project_list=
+| +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| +-Alias[id=6,name=,alias=sum(float_col),relation=,type=Double NULL]
+| +-AttributeReference[id=6,name=,alias=$window_aggregate0,
+| relation=$window_aggregate,type=Double NULL]
++-output_attributes=
+ +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+ +-AttributeReference[id=6,name=,alias=sum(float_col),relation=,
+ type=Double NULL]
+==
+
+SELECT sum(avg(int_col) OVER w) FROM test
+WINDOW w AS
+(PARTITION BY char_col
+ ORDER BY long_col
+ ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW);
+--
+TopLevelPlan
++-plan=Project
+| +-input=Aggregate
+| | +-input=WindowAggregate
+| | | +-input=Sort[is_ascending=[true,true],nulls_first=[false,false]]
+| | | | +-input=TableReference[relation_name=Test,relation_alias=test]
+| | | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | | | +-AttributeReference[id=2,name=float_col,relation=test,type=Float]
+| | | | | +-AttributeReference[id=3,name=double_col,relation=test,
+| | | | | | type=Double NULL]
+| | | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | | | +-AttributeReference[id=5,name=vchar_col,relation=test,
+| | | | | type=VarChar(20) NULL]
+| | | | +-sort_expressions=
+| | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | | +-window_aggregate_expression=Alias[id=6,name=,alias=$window_aggregate0,
+| | | relation=$window_aggregate,type=Double NULL]
+| | | +-WindowAggregateFunction[function=AVG,window_name=w,
+| | | is_ascending=[true],nulls_first=[false],frame_mode=row,
+| | | num_preceding=-1,num_following=0]
+| | | +-arguments=
+| | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
+| | | +-partition_by=
+| | | | +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
+| | | +-order_by=
+| | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
+| | +-grouping_expressions=
+| | | +-[]
+| | +-aggregate_expressions=
+| | +-Alias[id=7,name=,alias=$aggregate0,relation=$aggregate,type=Double NULL]
+| | +-AggregateFunction[function=SUM]
+| | +-AttributeReference[id=6,name=,alias=$window_aggregate0,
+| | relation=$window_aggregate,type=Double NULL]
+| +-project_list=
+| +-Alias[id=7,name=,alias=sum(avg(int_col)),relation=,type=Double NULL]
+| +-AttributeReference[id=7,name=,alias=$aggregate0,relation=$aggregate,
+| type=Double NULL]
++-output_attributes=
+ +-AttributeReference[id=7,name=,alias=sum(avg(int_col)),relation=,
+ type=Double NULL]
+==
+
+SELECT int_col, sum(float_col) OVER w1 FROM test
+WINDOW w2 AS
+(PARTITION BY vchar_col, long_col
+ ORDER BY double_col DESC NULLS LAST, int_col ASC NULLS FIRST
+ RANGE BETWEEN 3 PRECEDING AND 3 FOLLOWING);
+--
+ERROR: Undefined window w1 (1 : 37)
+SELECT int_col, sum(float_col) OVER w1 FROM test
+ ^
+==
+
+SELECT sum(avg(int_col)) OVER w FROM test
+WINDOW w AS
+(PARTITION BY double_col
+ ORDER BY char_col)
+--
+ERROR: Aggregation of Aggregates are not allowed (1 : 12)
+SELECT sum(avg(int_col)) OVER w FROM test
+ ^