quickstep-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jianq...@apache.org
Subject [02/14] incubator-quickstep git commit: Implement parser and resolver for UNION and INTERSECT.
Date Sun, 09 Apr 2017 01:48:42 GMT
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5b7b5cb8/query_optimizer/logical/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/logical/CMakeLists.txt b/query_optimizer/logical/CMakeLists.txt
index 8aca550..4480e0b 100644
--- a/query_optimizer/logical/CMakeLists.txt
+++ b/query_optimizer/logical/CMakeLists.txt
@@ -35,6 +35,7 @@ add_library(quickstep_queryoptimizer_logical_NestedLoopsJoin ../../empty_src.cpp
 add_library(quickstep_queryoptimizer_logical_PatternMatcher ../../empty_src.cpp PatternMatcher.hpp)
 add_library(quickstep_queryoptimizer_logical_Project Project.cpp Project.hpp)
 add_library(quickstep_queryoptimizer_logical_Sample Sample.cpp Sample.hpp)
+add_library(quickstep_queryoptimizer_logical_SetOperation ../../empty_src.cpp SetOperation.hpp)
 add_library(quickstep_queryoptimizer_logical_SharedSubplanReference
             SharedSubplanReference.cpp
             SharedSubplanReference.hpp)
@@ -204,6 +205,13 @@ target_link_libraries(quickstep_queryoptimizer_logical_Sample
                       quickstep_queryoptimizer_logical_LogicalType
                       quickstep_utility_Cast
                       quickstep_utility_Macros)
+target_link_libraries(quickstep_queryoptimizer_logical_SetOperation
+                      quickstep_queryoptimizer_OptimizerTree
+                      quickstep_queryoptimizer_expressions_AttributeReference
+                      quickstep_queryoptimizer_logical_Logical
+                      quickstep_queryoptimizer_logical_LogicalType
+                      quickstep_utility_Cast
+                      quickstep_utility_Macros)
 target_link_libraries(quickstep_queryoptimizer_logical_SharedSubplanReference
                       glog
                       quickstep_queryoptimizer_OptimizerTree
@@ -298,6 +306,7 @@ target_link_libraries(quickstep_queryoptimizer_logical
                       quickstep_queryoptimizer_logical_PatternMatcher
                       quickstep_queryoptimizer_logical_Project
                       quickstep_queryoptimizer_logical_Sample
+                      quickstep_queryoptimizer_logical_SetOperation
                       quickstep_queryoptimizer_logical_SharedSubplanReference
                       quickstep_queryoptimizer_logical_Sort
                       quickstep_queryoptimizer_logical_TableGenerator

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5b7b5cb8/query_optimizer/logical/LogicalType.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/logical/LogicalType.hpp b/query_optimizer/logical/LogicalType.hpp
index d1011b0..21ffdca 100644
--- a/query_optimizer/logical/LogicalType.hpp
+++ b/query_optimizer/logical/LogicalType.hpp
@@ -46,6 +46,7 @@ enum class LogicalType {
   kNestedLoopsJoin,
   kProject,
   kSample,
+  kSetOperation,
   kSharedSubplanReference,
   kSort,
   kTableGenerator,

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5b7b5cb8/query_optimizer/logical/PatternMatcher.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/logical/PatternMatcher.hpp b/query_optimizer/logical/PatternMatcher.hpp
index b931ace..23c2872 100644
--- a/query_optimizer/logical/PatternMatcher.hpp
+++ b/query_optimizer/logical/PatternMatcher.hpp
@@ -42,6 +42,7 @@ class Join;
 class MultiwayCartesianJoin;
 class NestedLoopsJoin;
 class Project;
+class SetOperation;
 class SharedSubplanReference;
 class Sort;
 class TableReference;
@@ -128,6 +129,7 @@ using SomeJoin = SomeLogicalNode<Join,
 using SomeMultiwayCartesianJoin = SomeLogicalNode<MultiwayCartesianJoin, LogicalType::kMultiwayCartesianJoin>;
 using SomeNestedLoopsJoin = SomeLogicalNode<NestedLoopsJoin, LogicalType::kNestedLoopsJoin>;
 using SomeProject = SomeLogicalNode<Project, LogicalType::kProject>;
+using SomeSetOperation = SomeLogicalNode<SetOperation, LogicalType::kSetOperation>;
 using SomeSharedSubplanReference = SomeLogicalNode<SharedSubplanReference, LogicalType::kSharedSubplanReference>;
 using SomeSort = SomeLogicalNode<Sort, LogicalType::kSort>;
 using SomeTableReference = SomeLogicalNode<TableReference, LogicalType::kTableReference>;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5b7b5cb8/query_optimizer/logical/SetOperation.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/logical/SetOperation.hpp b/query_optimizer/logical/SetOperation.hpp
new file mode 100644
index 0000000..7e45231
--- /dev/null
+++ b/query_optimizer/logical/SetOperation.hpp
@@ -0,0 +1,182 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ **/
+
+#ifndef QUICKSTEP_QUERY_OPTIMIZER_LOGICAL_SET_OPERATION_HPP_
+#define QUICKSTEP_QUERY_OPTIMIZER_LOGICAL_SET_OPERATION_HPP_
+
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "query_optimizer/OptimizerTree.hpp"
+#include "query_optimizer/expressions/AttributeReference.hpp"
+#include "query_optimizer/logical/Logical.hpp"
+#include "query_optimizer/logical/LogicalType.hpp"
+#include "utility/Cast.hpp"
+#include "utility/Macros.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+namespace optimizer {
+namespace logical {
+
+/** \addtogroup OptimizerLogical
+ *  @{
+ */
+
+class SetOperation;
+typedef std::shared_ptr<const SetOperation> SetOperationPtr;
+
+/**
+ * @brief Base class for logical set operation operator that combines tuples
+ *        from two or more relations.
+ */
+class SetOperation : public Logical {
+ public:
+  enum SetOperationType {
+    kIntersect = 0,
+    kUnion,
+    kUnionAll
+  };
+
+  /**
+   * @brief Destructor.
+   */
+  ~SetOperation() override {}
+
+  LogicalType getLogicalType() const override {
+    return LogicalType::kSetOperation;
+  }
+
+  std::string getName() const override {
+    switch (set_operation_type_) {
+      case SetOperationType::kIntersect:
+        return "Intersect";
+      case SetOperationType::kUnion:
+        return "Union";
+      case SetOperationType::kUnionAll:
+        return "UnionAll";
+      default:
+        LOG(FATAL) << "Invalid set operation type: "
+                   << static_cast<typename std::underlying_type<SetOperationType>::type>(set_operation_type_);
+    }
+  }
+
+  /**
+   * @return The set operation type
+   */
+  SetOperationType getSetOperationType() const {
+    return set_operation_type_;
+  }
+
+  /**
+   * @return The operands for set operation.
+   */
+  const std::vector<LogicalPtr>& getOperands() const {
+    return operands_;
+  }
+
+  std::vector<expressions::AttributeReferencePtr> getOutputAttributes() const override
{
+    return project_attributes_;
+  }
+
+  std::vector<expressions::AttributeReferencePtr> getReferencedAttributes() const override
{
+    std::vector<expressions::AttributeReferencePtr> referenced_attributes;
+    for (const auto &operand : operands_) {
+      const std::vector<expressions::AttributeReferencePtr> reference =
+          operand->getOutputAttributes();
+      referenced_attributes.insert(referenced_attributes.end(),
+                                   reference.begin(),
+                                   reference.end());
+    }
+    return referenced_attributes;
+  }
+
+  LogicalPtr copyWithNewChildren(
+      const std::vector<LogicalPtr> &new_children) const override {
+    DCHECK_EQ(new_children.size(), children().size());
+    return SetOperation::Create(set_operation_type_, new_children, project_attributes_);
+  }
+
+  /**
+   * @brief Create a logical set operation operator that combines two or more
+   *        relations.
+   *
+   * @param type The type of set operation.
+   * @param operands The operands of the set operation.
+   * @param project_attributes The project attributes of this set operation.
+   */
+  static SetOperationPtr Create(
+      const SetOperationType type,
+      const std::vector<LogicalPtr> &operands,
+      const std::vector<expressions::AttributeReferencePtr> &project_attributes)
{
+    DCHECK_GT(operands.size(), 1u);
+    return SetOperationPtr(new SetOperation(type, operands, project_attributes));
+  }
+
+ 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 {
+    inline_field_names->push_back("set_operation_type");
+    inline_field_values->push_back(getName());
+
+    container_child_field_names->push_back("operands");
+    container_child_fields->push_back(
+        CastSharedPtrVector<OptimizerTreeBase>(operands_));
+
+    container_child_field_names->push_back("project_attributes");
+    container_child_fields->push_back(
+        CastSharedPtrVector<OptimizerTreeBase>(project_attributes_));
+  }
+
+ private:
+  /**
+   * @brief Constructor.
+   */
+  SetOperation(const SetOperationType set_operation_type,
+               const std::vector<LogicalPtr> &operands,
+               const std::vector<expressions::AttributeReferencePtr> &project_attributes)
+    : set_operation_type_(set_operation_type),
+      operands_(operands),
+      project_attributes_(project_attributes) {
+    for (const LogicalPtr &operand : operands) {
+      addChild(operand);
+    }
+  }
+
+  const SetOperationType set_operation_type_;
+  const std::vector<LogicalPtr> operands_;
+  const std::vector<expressions::AttributeReferencePtr> project_attributes_;
+
+  DISALLOW_COPY_AND_ASSIGN(SetOperation);
+};
+
+/** @} */
+
+}  // namespace logical
+}  // namespace optimizer
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_QUERY_OPTIMIZER_LOGICAL_SET_OPERATION_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5b7b5cb8/query_optimizer/resolver/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/CMakeLists.txt b/query_optimizer/resolver/CMakeLists.txt
index a34273e..4e364a6 100644
--- a/query_optimizer/resolver/CMakeLists.txt
+++ b/query_optimizer/resolver/CMakeLists.txt
@@ -109,6 +109,7 @@ target_link_libraries(quickstep_queryoptimizer_resolver_Resolver
                       quickstep_queryoptimizer_logical_MultiwayCartesianJoin
                       quickstep_queryoptimizer_logical_Project
                       quickstep_queryoptimizer_logical_Sample
+                      quickstep_queryoptimizer_logical_SetOperation
                       quickstep_queryoptimizer_logical_SharedSubplanReference
                       quickstep_queryoptimizer_logical_Sort
                       quickstep_queryoptimizer_logical_TableGenerator

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5b7b5cb8/query_optimizer/resolver/Resolver.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/Resolver.cpp b/query_optimizer/resolver/Resolver.cpp
index ed465e5..2d3a06b 100644
--- a/query_optimizer/resolver/Resolver.cpp
+++ b/query_optimizer/resolver/Resolver.cpp
@@ -104,6 +104,7 @@
 #include "query_optimizer/logical/MultiwayCartesianJoin.hpp"
 #include "query_optimizer/logical/Project.hpp"
 #include "query_optimizer/logical/Sample.hpp"
+#include "query_optimizer/logical/SetOperation.hpp"
 #include "query_optimizer/logical/SharedSubplanReference.hpp"
 #include "query_optimizer/logical/Sort.hpp"
 #include "query_optimizer/logical/TableGenerator.hpp"
@@ -372,23 +373,23 @@ L::LogicalPtr Resolver::resolve(const ParseStatement &parse_query)
{
       }
       break;
     }
-    case ParseStatement::kSelect: {
-      const ParseStatementSelect &select_statement =
-          static_cast<const ParseStatementSelect&>(parse_query);
-      if (select_statement.with_clause() != nullptr) {
-        resolveWithClause(*select_statement.with_clause());
+    case ParseStatement::kSetOperation: {
+      const ParseStatementSetOperation &set_operation_statement =
+          static_cast<const ParseStatementSetOperation&>(parse_query);
+      if (set_operation_statement.with_clause() != nullptr) {
+        resolveWithClause(*set_operation_statement.with_clause());
       }
       logical_plan_ =
-          resolveSelect(*select_statement.select_query(),
-                        "" /* select_name */,
-                        nullptr /* No Type hints */,
-                        nullptr /* parent_resolver */);
-      if (select_statement.with_clause() != nullptr) {
+          resolveSetOperation(*set_operation_statement.set_operation_query(),
+                              "" /* set_operation_name */,
+                              nullptr /* type_hints */,
+                              nullptr /* parent_resolver */);
+      if (set_operation_statement.with_clause() != nullptr) {
         // Report an error if there is a WITH query that is not actually used.
         if (!with_queries_info_.unreferenced_query_indexes.empty()) {
           int unreferenced_with_query_index = *with_queries_info_.unreferenced_query_indexes.begin();
           const ParseSubqueryTableReference &unreferenced_with_query =
-              (*select_statement.with_clause())[unreferenced_with_query_index];
+              (*set_operation_statement.with_clause())[unreferenced_with_query_index];
           THROW_SQL_ERROR_AT(&unreferenced_with_query)
               << "WITH query "
               << unreferenced_with_query.table_reference_signature()->table_alias()->value()
@@ -1350,16 +1351,173 @@ L::LogicalPtr Resolver::resolveSelect(
   return logical_plan;
 }
 
+L::LogicalPtr Resolver::resolveSetOperations(
+    const ParseSetOperation &parse_set_operations,
+    const std::string &set_operation_name,
+    const std::vector<const Type*> *type_hints,
+    const NameResolver *parent_resolver) {
+  std::vector<const ParseSetOperation*> operands;
+  CollapseSetOperation(parse_set_operations, parse_set_operations, &operands);
+
+  DCHECK_LT(1u, operands.size());
+  std::vector<L::LogicalPtr> resolved_operations;
+  std::vector<std::vector<E::AttributeReferencePtr>> attribute_matrix;
+
+  // Resolve the first operation, and get the output attributes.
+  auto iter = operands.begin();
+  const ParseSetOperation &operation = static_cast<const ParseSetOperation&>(**iter);
+  L::LogicalPtr operation_logical =
+      resolveSetOperation(operation, set_operation_name, type_hints, parent_resolver);
+  const std::vector<E::AttributeReferencePtr> operation_attributes =
+      operation_logical->getOutputAttributes();
+  attribute_matrix.push_back(operation_attributes);
+  resolved_operations.push_back(operation_logical);
+
+  // Resolve the rest operations, and check the size of output attributes.
+  for (++iter; iter != operands.end(); ++iter) {
+    const ParseSetOperation &current_operation =
+        static_cast<const ParseSetOperation&>(**iter);
+    L::LogicalPtr current_logical =
+        resolveSetOperation(current_operation, set_operation_name, type_hints, parent_resolver);
+    attribute_matrix.emplace_back(current_logical->getOutputAttributes());
+
+    // Check output attributes size.
+    // Detailed type check and type cast will perform later.
+    if (attribute_matrix.back().size() != operation_attributes.size()) {
+      THROW_SQL_ERROR_AT(&current_operation)
+          << "Can not perform " << parse_set_operations.getName()
+          << "opeartion between " << std::to_string(attribute_matrix.back().size())
+          << "and " << std::to_string(operation_attributes.size())
+          << "columns";
+    }
+
+    resolved_operations.push_back(current_logical);
+  }
+
+  // Get the possible output attributes that the attributes of all operands can cast to.
+  std::vector<E::AttributeReferencePtr> possible_attributes;
+  for (std::size_t aid = 0; aid < operation_attributes.size(); ++aid) {
+    E::AttributeReferencePtr possible_attribute = attribute_matrix[0][aid];
+    for (std::size_t opid = 1; opid < resolved_operations.size(); ++opid) {
+      const Type &current_type = attribute_matrix[opid][aid]->getValueType();
+      const Type &possible_type = possible_attribute->getValueType();
+      if (!possible_type.equals(current_type)) {
+        if (possible_type.getSuperTypeID() == Type::SuperTypeID::kNumeric &&
+            current_type.getSuperTypeID() == Type::SuperTypeID::kNumeric) {
+          if (possible_type.isSafelyCoercibleFrom(current_type)) {
+            // Cast current_type to possible_type.
+            // Possible_attribute remain the same, nothing needs to change.
+          } else if (current_type.isSafelyCoercibleFrom(possible_type)) {
+            // Cast possible_type to current_type.
+            possible_attribute = attribute_matrix[opid][aid];
+          } else {
+            // Can not cast between possible_type and current_type.
+            // Throw an SQL error.
+            THROW_SQL_ERROR_AT(&parse_set_operations)
+                << "There is not a safely coerce between "
+                << current_type.getName()
+                << "and " << possible_type.getName();
+          }
+        } else {
+          THROW_SQL_ERROR_AT(&parse_set_operations)
+              << "Does not support cast operation between non-numeric types"
+              << current_type.getName()
+              << "and " << possible_type.getName();
+        }
+      }
+    }
+    possible_attributes.push_back(possible_attribute);
+  }
+
+  for (std::size_t opid = 0; opid < operation_attributes.size(); ++opid) {
+    // Generate a cast operation if needed.
+    std::vector<E::NamedExpressionPtr> cast_expressions;
+    for (std::size_t aid = 0; aid < operation_attributes.size(); ++aid) {
+      const E::AttributeReferencePtr current_attr = attribute_matrix[opid][aid];
+      const Type &current_type = current_attr->getValueType();
+      const Type &possible_type = possible_attributes[aid]->getValueType();
+      if (possible_type.equals(current_type)) {
+        cast_expressions.emplace_back(current_attr);
+      } else {
+        cast_expressions.emplace_back(
+            E::Alias::Create(context_->nextExprId(),
+                             E::Cast::Create(current_attr, possible_type),
+                             current_attr->attribute_name(),
+                             current_attr->attribute_alias()));
+      }
+    }
+    resolved_operations[opid] = L::Project::Create(resolved_operations[opid], cast_expressions);
+  }
+
+  std::vector<E::AttributeReferencePtr> output_attributes;
+  for (const auto &attr : possible_attributes) {
+    output_attributes.emplace_back(
+        E::AttributeReference::Create(context_->nextExprId(),
+                                      attr->attribute_name(),
+                                      attr->attribute_alias(),
+                                      "" /* relation_name */,
+                                      attr->getValueType(),
+                                      attr->scope()));
+  }
+
+  // Generate the set operation logical node.
+  switch (parse_set_operations.getOperationType()) {
+    case ParseSetOperation::kIntersect:
+      return L::SetOperation::Create(
+          L::SetOperation::kIntersect, resolved_operations, output_attributes);
+    case ParseSetOperation::kUnion:
+      return L::SetOperation::Create(
+          L::SetOperation::kUnion, resolved_operations, output_attributes);
+    case ParseSetOperation::kUnionAll:
+      return L::SetOperation::Create(
+          L::SetOperation::kUnionAll, resolved_operations, output_attributes);
+    default:
+      LOG(FATAL) << "Unknown operation: " << parse_set_operations.toString();
+      return nullptr;
+  }
+}
+
+L::LogicalPtr Resolver::resolveSetOperation(
+    const ParseSetOperation &set_operation_query,
+    const std::string &set_operation_name,
+    const std::vector<const Type*> *type_hints,
+    const NameResolver *parent_resolver) {
+  switch (set_operation_query.getOperationType()) {
+    case ParseSetOperation::kIntersect:
+    case ParseSetOperation::kUnion:
+    case ParseSetOperation::kUnionAll: {
+      return resolveSetOperations(set_operation_query,
+                                  set_operation_name,
+                                  type_hints,
+                                  parent_resolver);
+    }
+    case ParseSetOperation::kSelect: {
+      DCHECK_EQ(1u, set_operation_query.operands().size());
+      const ParseSelect &select_query =
+          static_cast<const ParseSelect&>(set_operation_query.operands().front());
+      return resolveSelect(select_query,
+                           set_operation_name,
+                           type_hints,
+                           parent_resolver);
+    }
+    default:
+      LOG(FATAL) << "Unknown set operation: " << set_operation_query.toString();
+      return nullptr;
+  }
+}
+
 E::SubqueryExpressionPtr Resolver::resolveSubqueryExpression(
     const ParseSubqueryExpression &parse_subquery_expression,
     const std::vector<const Type*> *type_hints,
     ExpressionResolutionInfo *expression_resolution_info,
     const bool has_single_column) {
+
+  // Subquery is now a set operation, not only a select operation
   L::LogicalPtr logical_subquery =
-      resolveSelect(*parse_subquery_expression.query(),
-                    "" /* select_name */,
-                    type_hints,
-                    &expression_resolution_info->name_resolver);
+      resolveSetOperation(*parse_subquery_expression.set_operation(),
+                          "" /* set_operation_name */,
+                          type_hints,
+                          &expression_resolution_info->name_resolver);
 
   // Raise SQL error if the subquery is expected to return only one column but
   // it returns multiple columns.
@@ -1614,10 +1772,10 @@ L::LogicalPtr Resolver::resolveTableReference(const ParseTableReference
&table_r
       DCHECK(reference_signature->table_alias() != nullptr);
 
       reference_alias = reference_signature->table_alias();
-      logical_plan = resolveSelect(
-          *static_cast<const ParseSubqueryTableReference&>(table_reference).subquery_expr()->query(),
+      logical_plan = resolveSetOperation(
+          *static_cast<const ParseSubqueryTableReference&>(table_reference).subquery_expr()->set_operation(),
           reference_alias->value(),
-          nullptr /* No Type hints */,
+          nullptr /* type_hints */,
           nullptr /* parent_resolver */);
 
       if (reference_signature->column_aliases() != nullptr) {
@@ -3164,6 +3322,20 @@ void Resolver::rewriteIfOrdinalReference(
   }
 }
 
+void Resolver::CollapseSetOperation(const ParseSetOperation &toplevel,
+                                    const ParseSetOperation &current,
+                                    std::vector<const ParseSetOperation*> *output)
{
+  if (current.getOperationType() == ParseSetOperation::kSelect ||
+      current.getOperationType() != toplevel.getOperationType()) {
+    output->emplace_back(&current);
+  } else {
+    for (const auto &child : current.operands()) {
+      CollapseSetOperation(
+          toplevel, static_cast<const ParseSetOperation&>(child), output);
+    }
+  }
+}
+
 std::string Resolver::GenerateWindowAggregateAttributeAlias(int index) {
   return "$window_aggregate" + std::to_string(index);
 }

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/5b7b5cb8/query_optimizer/resolver/Resolver.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/resolver/Resolver.hpp b/query_optimizer/resolver/Resolver.hpp
index a3d0833..1ae565a 100644
--- a/query_optimizer/resolver/Resolver.hpp
+++ b/query_optimizer/resolver/Resolver.hpp
@@ -50,6 +50,7 @@ class ParsePredicate;
 class ParseSearchedCaseExpression;
 class ParseSelect;
 class ParseSelectionClause;
+class ParseSetOperation;
 class ParseSimpleCaseExpression;
 class ParseSimpleTableReference;
 class ParseSubqueryTableReference;
@@ -61,7 +62,7 @@ class ParseStatementDelete;
 class ParseStatementDropTable;
 class ParseStatementInsertSelection;
 class ParseStatementInsertTuple;
-class ParseStatementSelect;
+class ParseStatementSetOperation;
 class ParseStatementUpdate;
 class ParseString;
 class ParseSubqueryExpression;
@@ -183,6 +184,24 @@ class Resolver {
       const NameResolver *parent_resolver);
 
   /**
+   * @brief Resolves multiple set operations at the same level.
+   */
+  logical::LogicalPtr resolveSetOperations(
+      const ParseSetOperation &parse_set_operations,
+      const std::string &set_operation_name,
+      const std::vector<const Type*> *type_hints,
+      const NameResolver *parent_resolver);
+
+  /**
+   * @brief Resolves a set operation and returns a logical plan.
+   */
+  logical::LogicalPtr resolveSetOperation(
+      const ParseSetOperation &set_operation_query,
+      const std::string &set_operation_name,
+      const std::vector<const Type*> *type_hints,
+      const NameResolver *parent_resolver);
+
+  /**
    * @brief Resolves a CREATE TABLE query and returns a logical plan.
    *
    * @param create_table_statement The CREATE TABLE parse tree.
@@ -559,6 +578,13 @@ class Resolver {
                                  const expressions::ScalarPtr &right_operand) const;
 
   /**
+   * @brief Collapse tree of homogenous set operations into a flat vector.
+   */
+  static void CollapseSetOperation(const ParseSetOperation &toplevel,
+                                   const ParseSetOperation &current,
+                                   std::vector<const ParseSetOperation*> *output);
+
+  /**
    * @brief Generates an internal alias for an aggregate attribute.
    *
    * @param index The index of the aggregate attribute used for generating the


Mime
View raw message