Added has_repartition in RelationalOperators.
diff --git a/query_optimizer/ExecutionGenerator.cpp b/query_optimizer/ExecutionGenerator.cpp
index d43432c..d82a0c7 100644
--- a/query_optimizer/ExecutionGenerator.cpp
+++ b/query_optimizer/ExecutionGenerator.cpp
@@ -747,6 +747,8 @@
                                  insert_destination_proto);
 
   // Create and add a Select operator.
+  const bool has_repartition = physical_selection->hasRepartition();
+
   // Use the "simple" form of the selection operator (a pure projection that
   // doesn't require any expression evaluation or intermediate copies) if
   // possible.
@@ -755,6 +757,7 @@
       convertSimpleProjection(project_expressions_group_index, &attributes)
           ? new SelectOperator(query_handle_->query_id(),
                                input_relation,
+                               has_repartition,
                                *output_relation,
                                insert_destination_index,
                                execution_predicate_index,
@@ -762,6 +765,7 @@
                                input_relation_info->isStoredRelation())
           : new SelectOperator(query_handle_->query_id(),
                                input_relation,
+                               has_repartition,
                                *output_relation,
                                insert_destination_index,
                                execution_predicate_index,
@@ -1040,6 +1044,7 @@
               probe_attribute_ids,
               any_probe_attributes_nullable,
               probe_num_partitions,
+              physical_plan->hasRepartition(),
               *output_relation,
               insert_destination_index,
               join_hash_table_index,
@@ -1152,6 +1157,7 @@
                                       left_relation,
                                       right_relation,
                                       num_partitions,
+                                      physical_plan->hasRepartition(),
                                       *output_relation,
                                       insert_destination_index,
                                       execution_join_predicate_index,
@@ -1539,6 +1545,15 @@
         static_cast<const ScalarAttribute*>(attribute.get())->getAttribute().getID());
   }
 
+  const P::PartitionSchemeHeader *input_physical_partition_scheme_header =
+      physical_plan->selection()->getOutputPartitionSchemeHeader();
+  const P::PartitionSchemeHeader *output_physical_partition_scheme_header =
+      physical_plan->destination()->getOutputPartitionSchemeHeader();
+  const bool has_repartition =
+      (input_physical_partition_scheme_header && output_physical_partition_scheme_header)
+          ? input_physical_partition_scheme_header->equal(*output_physical_partition_scheme_header)
+          : (input_physical_partition_scheme_header || output_physical_partition_scheme_header);
+
   // Create the select operator.
   // TODO(jianqiao): This select operator is actually redundant. That is,
   // we may directly set physical_plan_->selection()'s output relation to be
@@ -1549,6 +1564,7 @@
   SelectOperator *insert_selection_op =
       new SelectOperator(query_handle_->query_id(),
                          selection_relation,
+                         has_repartition,
                          destination_relation,
                          insert_destination_index,
                          QueryContext::kInvalidPredicateId,
@@ -1901,6 +1917,7 @@
           new FinalizeAggregationOperator(query_handle_->query_id(),
                                           aggr_state_index,
                                           num_partitions,
+                                          physical_plan->hasRepartition(),
                                           aggr_state_num_partitions,
                                           *output_relation,
                                           insert_destination_index));
@@ -2078,6 +2095,7 @@
           new FinalizeAggregationOperator(query_handle_->query_id(),
                                           aggr_state_index,
                                           num_partitions,
+                                          physical_plan->hasRepartition(),
                                           aggr_state_num_partitions,
                                           *output_relation,
                                           insert_destination_index));
diff --git a/query_optimizer/physical/Aggregate.cpp b/query_optimizer/physical/Aggregate.cpp
index f249e95..94be616 100644
--- a/query_optimizer/physical/Aggregate.cpp
+++ b/query_optimizer/physical/Aggregate.cpp
@@ -96,6 +96,9 @@
     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("has_repartition");
+  inline_field_values->push_back(has_repartition_ ? "true" : "false");
+
   if (partition_scheme_header_) {
     inline_field_names->push_back("output_partition_scheme_header");
     inline_field_values->push_back(partition_scheme_header_->toString());
diff --git a/query_optimizer/physical/Aggregate.hpp b/query_optimizer/physical/Aggregate.hpp
index c19a951..68f8811 100644
--- a/query_optimizer/physical/Aggregate.hpp
+++ b/query_optimizer/physical/Aggregate.hpp
@@ -89,7 +89,7 @@
       const std::vector<PhysicalPtr> &new_children) const override {
     DCHECK_EQ(getNumChildren(), new_children.size());
     return Create(new_children[0], grouping_expressions_, aggregate_expressions_, filter_predicate_,
-                  cloneOutputPartitionSchemeHeader());
+                  has_repartition_, cloneOutputPartitionSchemeHeader());
   }
 
   std::vector<expressions::AttributeReferencePtr> getOutputAttributes() const override;
@@ -97,9 +97,10 @@
   std::vector<expressions::AttributeReferencePtr> getReferencedAttributes() const override;
 
   PhysicalPtr copyWithNewOutputPartitionSchemeHeader(
-      PartitionSchemeHeader *partition_scheme_header) const override {
+      PartitionSchemeHeader *partition_scheme_header,
+      const bool has_repartition = true) const override {
     return Create(input_, grouping_expressions_, aggregate_expressions_, filter_predicate_,
-                  partition_scheme_header);
+                  has_repartition, partition_scheme_header);
   }
 
   bool maybeCopyWithPrunedExpressions(
@@ -125,9 +126,11 @@
       const std::vector<expressions::NamedExpressionPtr> &grouping_expressions,
       const std::vector<expressions::AliasPtr> &aggregate_expressions,
       const expressions::PredicatePtr &filter_predicate,
+      const bool has_repartition = false,
       PartitionSchemeHeader *partition_scheme_header = nullptr) {
     return AggregatePtr(
-        new Aggregate(input, grouping_expressions, aggregate_expressions, filter_predicate, partition_scheme_header));
+        new Aggregate(input, grouping_expressions, aggregate_expressions, filter_predicate, has_repartition,
+                      partition_scheme_header));
   }
 
  protected:
@@ -145,8 +148,9 @@
       const std::vector<expressions::NamedExpressionPtr> &grouping_expressions,
       const std::vector<expressions::AliasPtr> &aggregate_expressions,
       const expressions::PredicatePtr &filter_predicate,
+      const bool has_repartition,
       PartitionSchemeHeader *partition_scheme_header)
-      : Physical(partition_scheme_header),
+      : Physical(has_repartition, partition_scheme_header),
         input_(input),
         grouping_expressions_(grouping_expressions),
         aggregate_expressions_(aggregate_expressions),
diff --git a/query_optimizer/physical/BinaryJoin.cpp b/query_optimizer/physical/BinaryJoin.cpp
index 1928198..b8e8609 100644
--- a/query_optimizer/physical/BinaryJoin.cpp
+++ b/query_optimizer/physical/BinaryJoin.cpp
@@ -40,6 +40,9 @@
     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("has_repartition");
+  inline_field_values->push_back(has_repartition_ ? "true" : "false");
+
   if (partition_scheme_header_) {
     inline_field_names->push_back("output_partition_scheme_header");
     inline_field_values->push_back(partition_scheme_header_->toString());
diff --git a/query_optimizer/physical/BinaryJoin.hpp b/query_optimizer/physical/BinaryJoin.hpp
index d1f652f..39d5e31 100644
--- a/query_optimizer/physical/BinaryJoin.hpp
+++ b/query_optimizer/physical/BinaryJoin.hpp
@@ -70,13 +70,15 @@
    * @param left The left operand.
    * @param right The right operand.
    * @param project_expressions The project expressions.
+   * @param has_repartition Whether this node has repartition.
    * @param partition_scheme_header The optional output partition scheme header.
    */
   BinaryJoin(const PhysicalPtr &left,
              const PhysicalPtr &right,
              const std::vector<expressions::NamedExpressionPtr> &project_expressions,
+             const bool has_repartition = false,
              PartitionSchemeHeader *partition_scheme_header = nullptr)
-      : Join(project_expressions, partition_scheme_header),
+      : Join(project_expressions, has_repartition, partition_scheme_header),
         left_(left),
         right_(right) {
     addChild(left_);
diff --git a/query_optimizer/physical/HashJoin.cpp b/query_optimizer/physical/HashJoin.cpp
index b0ee913..a49bc8e 100644
--- a/query_optimizer/physical/HashJoin.cpp
+++ b/query_optimizer/physical/HashJoin.cpp
@@ -81,6 +81,7 @@
                      residual_predicate_,
                      new_project_expressions,
                      join_type_,
+                     has_repartition_,
                      cloneOutputPartitionSchemeHeader());
     return true;
   }
diff --git a/query_optimizer/physical/HashJoin.hpp b/query_optimizer/physical/HashJoin.hpp
index 1804d4b..2ed83af 100644
--- a/query_optimizer/physical/HashJoin.hpp
+++ b/query_optimizer/physical/HashJoin.hpp
@@ -119,15 +119,18 @@
                   residual_predicate_,
                   project_expressions(),
                   join_type_,
+                  has_repartition_,
                   cloneOutputPartitionSchemeHeader());
   }
 
   std::vector<expressions::AttributeReferencePtr> getReferencedAttributes() const override;
 
   PhysicalPtr copyWithNewOutputPartitionSchemeHeader(
-      PartitionSchemeHeader *partition_scheme_header) const override {
+      PartitionSchemeHeader *partition_scheme_header,
+      const bool has_repartition = true) const override {
     return Create(left(), right(), left_join_attributes_, right_join_attributes_,
-                  residual_predicate_, project_expressions(), join_type_, partition_scheme_header);
+                  residual_predicate_, project_expressions(), join_type_,
+                  has_repartition, partition_scheme_header);
   }
 
   bool maybeCopyWithPrunedExpressions(
@@ -145,6 +148,7 @@
    * @param residual_predicate Optional filtering predicate evaluated after join.
    * @param project_expressions The project expressions.
    * @param Join type of this hash join.
+   * @param has_repartition Whether this node has repartition.
    * @param partition_scheme_header The optional output partition scheme header.
    *
    * @return An immutable physical HashJoin.
@@ -157,6 +161,7 @@
       const expressions::PredicatePtr &residual_predicate,
       const std::vector<expressions::NamedExpressionPtr> &project_expressions,
       const JoinType join_type,
+      const bool has_repartition = false,
       PartitionSchemeHeader *partition_scheme_header = nullptr) {
     return HashJoinPtr(
         new HashJoin(left,
@@ -166,6 +171,7 @@
                      residual_predicate,
                      project_expressions,
                      join_type,
+                     has_repartition,
                      partition_scheme_header));
   }
 
@@ -187,8 +193,9 @@
       const expressions::PredicatePtr &residual_predicate,
       const std::vector<expressions::NamedExpressionPtr> &project_expressions,
       const JoinType join_type,
+      const bool has_repartition,
       PartitionSchemeHeader *partition_scheme_header)
-      : BinaryJoin(left, right, project_expressions, partition_scheme_header),
+      : BinaryJoin(left, right, project_expressions, has_repartition, partition_scheme_header),
         left_join_attributes_(left_join_attributes),
         right_join_attributes_(right_join_attributes),
         residual_predicate_(residual_predicate),
diff --git a/query_optimizer/physical/Join.hpp b/query_optimizer/physical/Join.hpp
index d72d072..63f67c8 100644
--- a/query_optimizer/physical/Join.hpp
+++ b/query_optimizer/physical/Join.hpp
@@ -70,12 +70,14 @@
    * @brief Constructor.
    *
    * @param project_expressions The project expressions.
+   * @param has_repartition Whether this node has repartition.
    * @param partition_scheme_header The optional output partition scheme header.
    */
   explicit Join(
       const std::vector<expressions::NamedExpressionPtr>& project_expressions,
+      const bool has_repartition = false,
       PartitionSchemeHeader *partition_scheme_header = nullptr)
-      : Physical(partition_scheme_header),
+      : Physical(has_repartition, partition_scheme_header),
         project_expressions_(project_expressions) {}
 
  private:
diff --git a/query_optimizer/physical/NestedLoopsJoin.hpp b/query_optimizer/physical/NestedLoopsJoin.hpp
index f4c3a42..0e0260c 100644
--- a/query_optimizer/physical/NestedLoopsJoin.hpp
+++ b/query_optimizer/physical/NestedLoopsJoin.hpp
@@ -75,6 +75,7 @@
                   new_children[1],
                   join_predicate_,
                   project_expressions(),
+                  has_repartition_,
                   cloneOutputPartitionSchemeHeader());
   }
 
@@ -85,8 +86,10 @@
       PhysicalPtr *output) const override;
 
   PhysicalPtr copyWithNewOutputPartitionSchemeHeader(
-      PartitionSchemeHeader *partition_scheme_header) const override {
-    return Create(left(), right(), join_predicate_, project_expressions(), partition_scheme_header);
+      PartitionSchemeHeader *partition_scheme_header,
+      const bool has_repartition = true) const override {
+    return Create(left(), right(), join_predicate_, project_expressions(),
+                  has_repartition, partition_scheme_header);
   }
 
   /**
@@ -105,9 +108,11 @@
       const PhysicalPtr &right,
       const expressions::PredicatePtr &join_predicate,
       const std::vector<expressions::NamedExpressionPtr> &project_expressions,
+      const bool has_repartition = false,
       PartitionSchemeHeader *partition_scheme_header = nullptr) {
     return NestedLoopsJoinPtr(
-        new NestedLoopsJoin(left, right, join_predicate, project_expressions, partition_scheme_header));
+        new NestedLoopsJoin(left, right, join_predicate, project_expressions,
+                            has_repartition, partition_scheme_header));
   }
 
  protected:
@@ -125,8 +130,9 @@
       const PhysicalPtr &right,
       const expressions::PredicatePtr &join_predicate,
       const std::vector<expressions::NamedExpressionPtr> &project_expressions,
+      const bool has_repartition,
       PartitionSchemeHeader *partition_scheme_header)
-      : BinaryJoin(left, right, project_expressions, partition_scheme_header),
+      : BinaryJoin(left, right, project_expressions, has_repartition, partition_scheme_header),
         join_predicate_(join_predicate) {
     DCHECK(join_predicate_ != nullptr);
   }
diff --git a/query_optimizer/physical/Physical.hpp b/query_optimizer/physical/Physical.hpp
index a3a56d0..4491520 100644
--- a/query_optimizer/physical/Physical.hpp
+++ b/query_optimizer/physical/Physical.hpp
@@ -95,12 +95,14 @@
    * @param partition_scheme_header The partition scheme header to be
    *        substituted for the existing one, if any. It takes ownership of
    *        'partition_scheme_header'.
+   * @param has_repartition Whether the new node does repartition.
    *
    * @return A copy with \p partition_scheme_header as the partition scheme
    *         header.
    */
   virtual PhysicalPtr copyWithNewOutputPartitionSchemeHeader(
-      PartitionSchemeHeader *partition_scheme_header) const {
+      PartitionSchemeHeader *partition_scheme_header,
+      const bool has_repartition = true) const {
     std::unique_ptr<PartitionSchemeHeader> new_partition_scheme_header(partition_scheme_header);
     LOG(FATAL) << "copyWithNewOutputPartitionSchemeHeader is not implemented for " << getName();
   }
@@ -128,16 +130,29 @@
     return nullptr;
   }
 
+  /**
+   * @brief Whether the physical plan node does repartition.
+   *
+   * @return True if this node does repartition. Otherwise, false.
+   **/
+  bool hasRepartition() const {
+    return has_repartition_;
+  }
+
  protected:
   /**
    * @brief Constructor.
    *
+   * @param has_repartition Whether this node does repartition.
    * @param partition_scheme_header The partition scheme header of the relation.
    *        The constructor takes ownership of 'partition_scheme_header'.
    */
-  explicit Physical(PartitionSchemeHeader *partition_scheme_header = nullptr)
-      : partition_scheme_header_(partition_scheme_header) {}
+  explicit Physical(const bool has_repartition = false,
+                    PartitionSchemeHeader *partition_scheme_header = nullptr)
+      : has_repartition_(has_repartition),
+        partition_scheme_header_(partition_scheme_header) {}
 
+  const bool has_repartition_;
   std::unique_ptr<PartitionSchemeHeader> partition_scheme_header_;
 
  private:
diff --git a/query_optimizer/physical/Selection.cpp b/query_optimizer/physical/Selection.cpp
index 3307e9e..b2b3f7e 100644
--- a/query_optimizer/physical/Selection.cpp
+++ b/query_optimizer/physical/Selection.cpp
@@ -45,7 +45,8 @@
 PhysicalPtr Selection::copyWithNewChildren(
     const std::vector<PhysicalPtr> &new_children) const {
   DCHECK_EQ(children().size(), new_children.size());
-  return Create(new_children[0], project_expressions_, filter_predicate_, cloneOutputPartitionSchemeHeader());
+  return Create(new_children[0], project_expressions_, filter_predicate_,
+                has_repartition_, cloneOutputPartitionSchemeHeader());
 }
 
 std::vector<E::AttributeReferencePtr> Selection::getOutputAttributes() const {
@@ -82,7 +83,8 @@
     }
   }
   if (new_project_expressions.size() != project_expressions_.size()) {
-    *output = Create(input(), new_project_expressions, filter_predicate_, cloneOutputPartitionSchemeHeader());
+    *output = Create(input(), new_project_expressions, filter_predicate_,
+                     has_repartition_, cloneOutputPartitionSchemeHeader());
     return true;
   }
   return false;
@@ -95,6 +97,9 @@
     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("has_repartition");
+  inline_field_values->push_back(has_repartition_ ? "true" : "false");
+
   if (partition_scheme_header_) {
     inline_field_names->push_back("output_partition_scheme_header");
     inline_field_values->push_back(partition_scheme_header_->toString());
diff --git a/query_optimizer/physical/Selection.hpp b/query_optimizer/physical/Selection.hpp
index 4cbc856..2b50061 100644
--- a/query_optimizer/physical/Selection.hpp
+++ b/query_optimizer/physical/Selection.hpp
@@ -85,8 +85,10 @@
   std::vector<expressions::AttributeReferencePtr> getReferencedAttributes() const override;
 
   PhysicalPtr copyWithNewOutputPartitionSchemeHeader(
-      PartitionSchemeHeader *partition_scheme_header) const override {
-    return Create(input(), project_expressions_, filter_predicate_, partition_scheme_header);
+      PartitionSchemeHeader *partition_scheme_header,
+      const bool has_repartition = true) const override {
+    return Create(input(), project_expressions_, filter_predicate_,
+                  has_repartition, partition_scheme_header);
   }
 
   bool maybeCopyWithPrunedExpressions(
@@ -109,9 +111,11 @@
       const PhysicalPtr &input,
       const std::vector<expressions::NamedExpressionPtr> &project_expressions,
       const expressions::PredicatePtr &filter_predicate,
+      const bool has_repartition = false,
       PartitionSchemeHeader *output_partition_scheme_header = nullptr) {
     return SelectionPtr(
-        new Selection(input, project_expressions, filter_predicate, output_partition_scheme_header));
+        new Selection(input, project_expressions, filter_predicate,
+                      has_repartition, output_partition_scheme_header));
   }
 
   /**
@@ -153,8 +157,9 @@
       const PhysicalPtr &input,
       const std::vector<expressions::NamedExpressionPtr> &project_expressions,
       const expressions::PredicatePtr &filter_predicate,
+      const bool has_repartition,
       PartitionSchemeHeader *partition_scheme_header)
-      : Physical(partition_scheme_header),
+      : Physical(has_repartition, partition_scheme_header),
         project_expressions_(project_expressions),
         filter_predicate_(filter_predicate) {
     addChild(input);
diff --git a/query_optimizer/physical/TableGenerator.hpp b/query_optimizer/physical/TableGenerator.hpp
index 4d6419f..0798165 100644
--- a/query_optimizer/physical/TableGenerator.hpp
+++ b/query_optimizer/physical/TableGenerator.hpp
@@ -102,9 +102,11 @@
   }
 
   PhysicalPtr copyWithNewOutputPartitionSchemeHeader(
-      PartitionSchemeHeader *partition_scheme_header) const override {
+      PartitionSchemeHeader *partition_scheme_header,
+      const bool has_repartition = true) const override {
     return TableGeneratorPtr(
-        new TableGenerator(generator_function_handle_, table_alias_, attribute_list_, partition_scheme_header));
+        new TableGenerator(generator_function_handle_, table_alias_, attribute_list_,
+                           partition_scheme_header != nullptr, partition_scheme_header));
   }
 
   void getFieldStringItems(
@@ -152,8 +154,9 @@
   TableGenerator(const GeneratorFunctionHandlePtr &generator_function_handle,
                  const std::string &table_alias,
                  const std::vector<E::AttributeReferencePtr> &attribute_list,
+                 const bool has_repartition = false,
                  PartitionSchemeHeader *partition_scheme_header = nullptr)
-      : Physical(partition_scheme_header),
+      : Physical(has_repartition, partition_scheme_header),
         generator_function_handle_(generator_function_handle),
         table_alias_(table_alias),
         attribute_list_(attribute_list) {
diff --git a/query_optimizer/physical/TableReference.hpp b/query_optimizer/physical/TableReference.hpp
index bdc0578..85cb76b 100644
--- a/query_optimizer/physical/TableReference.hpp
+++ b/query_optimizer/physical/TableReference.hpp
@@ -114,7 +114,7 @@
       const CatalogRelation *relation, const std::string &alias,
       const std::vector<expressions::AttributeReferencePtr> &attribute_list,
       PartitionSchemeHeader *partition_scheme_header)
-      : Physical(partition_scheme_header),
+      : Physical(false /* has_repartition */, partition_scheme_header),
         relation_(relation),
         alias_(alias),
         attribute_list_(attribute_list) {}
diff --git a/query_optimizer/rules/Partition.cpp b/query_optimizer/rules/Partition.cpp
index fd4deb3..5f8b2c6 100644
--- a/query_optimizer/rules/Partition.cpp
+++ b/query_optimizer/rules/Partition.cpp
@@ -100,7 +100,8 @@
     // Add a Selection node.
     return P::Selection::Create(node,
                                 CastSharedPtrVector<E::NamedExpression>(node->getOutputAttributes()),
-                                nullptr /* filter_predicate */, repartition_scheme_header);
+                                nullptr /* filter_predicate */,
+                                true /* has_repartition */, repartition_scheme_header);
   } else {
     // Overwrite the output partition scheme header of the node.
     return node->copyWithNewOutputPartitionSchemeHeader(repartition_scheme_header);
@@ -180,7 +181,8 @@
       // Add a Selection node.
       left = P::Selection::Create(left,
                                   CastSharedPtrVector<E::NamedExpression>(left->getOutputAttributes()),
-                                  nullptr /* filter_predicate */, left_repartition_scheme_header.release());
+                                  nullptr /* filter_predicate */,
+                                  true /* has_repartition */, left_repartition_scheme_header.release());
       break;
     default: {
       if (!left_partition_scheme_header) {
@@ -199,7 +201,8 @@
       // Add a Selection node.
       right = P::Selection::Create(right,
                                    CastSharedPtrVector<E::NamedExpression>(right->getOutputAttributes()),
-                                   nullptr /* filter_predicate */, right_repartition_scheme_header.release());
+                                   nullptr /* filter_predicate */,
+                                   true /* has_repartition */, right_repartition_scheme_header.release());
     } else {
       right = right->copyWithNewOutputPartitionSchemeHeader(right_repartition_scheme_header.release());
     }
@@ -227,9 +230,11 @@
   }
 
   std::unique_ptr<P::PartitionSchemeHeader> output_partition_scheme_header;
+  bool has_repartition = false;
   if (left_partition_expr_ids != output_partition_expr_ids) {
     output_partition_scheme_header = make_unique<P::PartitionSchemeHeader>(
         left_partition_scheme_header->partition_type, num_partitions, move(output_partition_expr_ids));
+    has_repartition = true;
   } else {
     output_partition_scheme_header = make_unique<P::PartitionSchemeHeader>(*left_partition_scheme_header);
   }
@@ -237,6 +242,7 @@
   return P::NestedLoopsJoin::Create(left, right,
                                     nested_loops_join->join_predicate(),
                                     nested_loops_join->project_expressions(),
+                                    has_repartition,
                                     output_partition_scheme_header.release());
 }
 
@@ -277,7 +283,8 @@
               input_partition_scheme_header->num_partitions,
               move(output_partition_expr_ids));
 
-          return aggregate->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release());
+          return aggregate->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release(),
+                                                                   false /* has_repartition */);
         }
       }
 
@@ -364,7 +371,8 @@
           avg_recompute_expressions.empty()
               ? aggregate->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release())
               : P::Aggregate::Create(input, grouping_expressions, partial_aggregate_expressions,
-                                     filter_predicate, output_partition_scheme_header.release());
+                                     filter_predicate, true /* has_repartition */,
+                                     output_partition_scheme_header.release());
 
       vector<E::AliasPtr> reaggregate_expressions;
       for (const auto &aggregate_expr : partial_aggregate_expressions) {
@@ -383,7 +391,8 @@
       }
       const P::AggregatePtr reaggregate =
           P::Aggregate::Create(partial_aggregate, grouping_expressions, reaggregate_expressions,
-                               nullptr /* filter_predicate */, output_partition_scheme_header.release());
+                               nullptr /* filter_predicate */, false /* has_repartition */,
+                               output_partition_scheme_header.release());
 
       if (avg_recompute_expressions.empty()) {
         return reaggregate;
@@ -419,7 +428,7 @@
             make_unique<P::PartitionSchemeHeader>(*reaggregate->getOutputPartitionSchemeHeader());
       }
       return P::Selection::Create(reaggregate, project_expressions, nullptr /* filter_predicate */,
-                                  output_partition_scheme_header.release());
+                                  false /* has_repartition */, output_partition_scheme_header.release());
     }
     case P::PhysicalType::kHashJoin: {
       const P::HashJoinPtr hash_join = static_pointer_cast<const P::HashJoin>(node);
@@ -489,10 +498,12 @@
                                    hash_join->residual_predicate(),
                                    hash_join->project_expressions(),
                                    hash_join->join_type(),
+                                   false /* has_repartition */,
                                    output_partition_scheme_header.release());
       }
 
-      return hash_join->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release());
+      return hash_join->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release(),
+                                                               false /* has_repartition */);
     }
     case P::PhysicalType::kNestedLoopsJoin: {
       const P::NestedLoopsJoinPtr nested_loops_join = static_pointer_cast<const P::NestedLoopsJoin>(node);
@@ -552,7 +563,8 @@
       // TODO(quickstep-team): Check RangePartitionSchemeHeader against the project expressions.
       DCHECK(input_partition_scheme_header->partition_type != P::PartitionSchemeHeader::PartitionType::kRange);
       auto output_partition_scheme_header = make_unique<P::PartitionSchemeHeader>(*input_partition_scheme_header);
-      return selection->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release());
+      return selection->copyWithNewOutputPartitionSchemeHeader(output_partition_scheme_header.release(),
+                                                               false /* has_repartition */);
     }
     default:
       break;
diff --git a/query_optimizer/tests/physical_generator/CommonSubexpression.test b/query_optimizer/tests/physical_generator/CommonSubexpression.test
index b23a97d..147cfeb 100644
--- a/query_optimizer/tests/physical_generator/CommonSubexpression.test
+++ b/query_optimizer/tests/physical_generator/CommonSubexpression.test
@@ -44,7 +44,7 @@
   +-AttributeReference[id=7,name=,alias=(1+int_col),relation=,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -114,8 +114,8 @@
     type=Float NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -216,7 +216,7 @@
     type=Float NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashJoin
++-plan=HashJoin[has_repartition=false]
 | +-left=TableGenerator[function_name=generate_series,table_alias=g]
 | | +-AttributeReference[id=6,name=generate_series,alias=g,
 | |   relation=generate_series,type=Int]
@@ -318,7 +318,7 @@
     type=Float NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=NestedLoopsJoin
++-plan=NestedLoopsJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -416,7 +416,7 @@
   +-AttributeReference[id=7,name=result,relation=,type=Long]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -512,7 +512,7 @@
   +-AttributeReference[id=8,name=,alias=(int_col+1),relation=,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -627,8 +627,8 @@
   +-AttributeReference[id=11,name=,alias=COUNT(*),relation=,type=Long]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -731,8 +731,8 @@
     type=Long NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -769,4 +769,3 @@
   | type=Long NULL]
   +-AttributeReference[id=9,name=,alias=((SUM((long_col+1))+2)*3),relation=,
     type=Long NULL]
-==
diff --git a/query_optimizer/tests/physical_generator/Join.test b/query_optimizer/tests/physical_generator/Join.test
index 4ebbac7..45ea0ed 100644
--- a/query_optimizer/tests/physical_generator/Join.test
+++ b/query_optimizer/tests/physical_generator/Join.test
@@ -23,9 +23,9 @@
        JOIN d ON a.y = d.y;
 --
 TopLevelPlan
-+-plan=HashJoin
-| +-left=HashJoin
-| | +-left=HashJoin
++-plan=HashJoin[has_repartition=false]
+| +-left=HashJoin[has_repartition=false]
+| | +-left=HashJoin[has_repartition=false]
 | | | +-left=TableReference[relation=a]
 | | | | +-AttributeReference[id=0,name=w,relation=a,type=Int]
 | | | | +-AttributeReference[id=1,name=x,relation=a,type=Int]
@@ -71,9 +71,9 @@
        JOIN d ON (a.y = d.y OR a.z > d.z);
 --
 TopLevelPlan
-+-plan=NestedLoopsJoin
-| +-left=HashJoin
-| | +-left=NestedLoopsJoin
++-plan=NestedLoopsJoin[has_repartition=false]
+| +-left=HashJoin[has_repartition=false]
+| | +-left=NestedLoopsJoin[has_repartition=false]
 | | | +-left=TableReference[relation=a]
 | | | | +-AttributeReference[id=0,name=w,relation=a,type=Int]
 | | | | +-AttributeReference[id=1,name=x,relation=a,type=Int]
@@ -131,9 +131,9 @@
   AND a1.z = d1.z;
 --
 TopLevelPlan
-+-plan=HashJoin
-| +-left=HashJoin
-| | +-left=HashJoin
++-plan=HashJoin[has_repartition=false]
+| +-left=HashJoin[has_repartition=false]
+| | +-left=HashJoin[has_repartition=false]
 | | | +-left=TableReference[relation=a,alias=a1]
 | | | | +-AttributeReference[id=0,name=w,relation=a1,type=Int]
 | | | | +-AttributeReference[id=1,name=x,relation=a1,type=Int]
@@ -188,9 +188,9 @@
   AND a1.z = d1.z;
 --
 TopLevelPlan
-+-plan=HashJoin
-| +-left=HashJoin
-| | +-left=HashJoin
++-plan=HashJoin[has_repartition=false]
+| +-left=HashJoin[has_repartition=false]
+| | +-left=HashJoin[has_repartition=false]
 | | | +-left=TableReference[relation=a,alias=a1]
 | | | | +-AttributeReference[id=0,name=w,relation=a1,type=Int]
 | | | | +-AttributeReference[id=1,name=x,relation=a1,type=Int]
@@ -245,9 +245,9 @@
        LEFT JOIN d ON a.y = d.y;
 --
 TopLevelPlan
-+-plan=HashLeftOuterJoin
-| +-left=HashLeftOuterJoin
-| | +-left=HashLeftOuterJoin
++-plan=HashLeftOuterJoin[has_repartition=false]
+| +-left=HashLeftOuterJoin[has_repartition=false]
+| | +-left=HashLeftOuterJoin[has_repartition=false]
 | | | +-left=TableReference[relation=a]
 | | | | +-AttributeReference[id=0,name=w,relation=a,type=Int]
 | | | | +-AttributeReference[id=1,name=x,relation=a,type=Int]
@@ -304,10 +304,10 @@
   AND c.y > 20;
 --
 TopLevelPlan
-+-plan=HashLeftOuterJoin
-| +-left=HashJoin
-| | +-left=HashLeftOuterJoin
-| | | +-left=Selection
++-plan=HashLeftOuterJoin[has_repartition=false]
+| +-left=HashJoin[has_repartition=false]
+| | +-left=HashLeftOuterJoin[has_repartition=false]
+| | | +-left=Selection[has_repartition=false]
 | | | | +-input=TableReference[relation=b]
 | | | | | +-AttributeReference[id=4,name=w,relation=b,type=Int]
 | | | | | +-AttributeReference[id=5,name=x,relation=b,type=Int]
@@ -331,7 +331,7 @@
 | | | | +-AttributeReference[id=4,name=w,relation=b,type=Int]
 | | | +-right_join_attributes=
 | | |   +-AttributeReference[id=0,name=w,relation=a,type=Int]
-| | +-right=Selection
+| | +-right=Selection[has_repartition=false]
 | | | +-input=TableReference[relation=c]
 | | | | +-AttributeReference[id=6,name=x,relation=c,type=Int]
 | | | | +-AttributeReference[id=7,name=y,relation=c,type=Int]
@@ -373,11 +373,11 @@
 FROM b LEFT JOIN c ON (b.x = c.x AND c.x > 10);
 --
 TopLevelPlan
-+-plan=HashLeftOuterJoin
++-plan=HashLeftOuterJoin[has_repartition=false]
 | +-left=TableReference[relation=b]
 | | +-AttributeReference[id=0,name=w,relation=b,type=Int]
 | | +-AttributeReference[id=1,name=x,relation=b,type=Int]
-| +-right=Selection
+| +-right=Selection[has_repartition=false]
 | | +-input=TableReference[relation=c]
 | | | +-AttributeReference[id=2,name=x,relation=c,type=Int]
 | | | +-AttributeReference[id=3,name=y,relation=c,type=Int]
diff --git a/query_optimizer/tests/physical_generator/Select.test b/query_optimizer/tests/physical_generator/Select.test
index dc923ae..8bb6599 100644
--- a/query_optimizer/tests/physical_generator/Select.test
+++ b/query_optimizer/tests/physical_generator/Select.test
@@ -44,7 +44,7 @@
   +-AttributeReference[id=5,name=vchar_col,relation=test,type=VarChar(20) NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -90,7 +90,7 @@
   +-AttributeReference[id=7,name=,alias=2,relation=,type=Int]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -148,7 +148,7 @@
     type=Float NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashJoin
++-plan=HashJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=a]
 | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=a,type=Long]
@@ -233,7 +233,7 @@
   +-AttributeReference[id=9,name=int_col,relation=,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -325,7 +325,7 @@
   +-AttributeReference[id=12,name=float_col,relation=b,type=Float]
 [Physical Plan]
 TopLevelPlan
-+-plan=NestedLoopsJoin
++-plan=NestedLoopsJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=a]
 | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=a,type=Long]
@@ -421,7 +421,7 @@
   +-AttributeReference[id=8,name=float_col,relation=b,type=Float]
 [Physical Plan]
 TopLevelPlan
-+-plan=NestedLoopsJoin
++-plan=NestedLoopsJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=a]
 | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=a,type=Long]
@@ -429,7 +429,7 @@
 | | +-AttributeReference[id=3,name=double_col,relation=a,type=Double NULL]
 | | +-AttributeReference[id=4,name=char_col,relation=a,type=Char(20)]
 | | +-AttributeReference[id=5,name=vchar_col,relation=a,type=VarChar(20) NULL]
-| +-right=Selection
+| +-right=Selection[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=7,name=long_col,relation=test,type=Long]
@@ -518,7 +518,7 @@
   +-AttributeReference[id=12,name=float_col,relation=b,type=Float]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashJoin
++-plan=HashJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=a]
 | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=a,type=Long]
@@ -526,7 +526,7 @@
 | | +-AttributeReference[id=3,name=double_col,relation=a,type=Double NULL]
 | | +-AttributeReference[id=4,name=char_col,relation=a,type=Char(20)]
 | | +-AttributeReference[id=5,name=vchar_col,relation=a,type=VarChar(20) NULL]
-| +-right=Selection
+| +-right=Selection[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=7,name=long_col,relation=test,type=Long]
@@ -604,7 +604,7 @@
   +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashJoin
++-plan=HashJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=a]
 | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=a,type=Long]
@@ -675,7 +675,7 @@
   +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashJoin
++-plan=HashJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=a]
 | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=a,type=Long]
@@ -683,7 +683,7 @@
 | | +-AttributeReference[id=3,name=double_col,relation=a,type=Double NULL]
 | | +-AttributeReference[id=4,name=char_col,relation=a,type=Char(20)]
 | | +-AttributeReference[id=5,name=vchar_col,relation=a,type=VarChar(20) NULL]
-| +-right=Selection
+| +-right=Selection[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=7,name=long_col,relation=test,type=Long]
@@ -755,7 +755,7 @@
   +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashJoin
++-plan=HashJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=a]
 | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=a,type=Long]
@@ -835,8 +835,8 @@
   +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=NestedLoopsJoin
-| +-left=HashJoin
++-plan=NestedLoopsJoin[has_repartition=false]
+| +-left=HashJoin[has_repartition=false]
 | | +-left=TableReference[relation=Test,alias=a]
 | | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=a,type=Long]
@@ -857,7 +857,7 @@
 | | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | +-right_join_attributes=
 | |   +-AttributeReference[id=7,name=long_col,relation=b,type=Long]
-| +-right=Selection
+| +-right=Selection[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=c]
 | | | +-AttributeReference[id=12,name=int_col,relation=c,type=Int NULL]
 | | | +-AttributeReference[id=13,name=long_col,relation=c,type=Long]
@@ -916,7 +916,7 @@
   +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=NestedLoopsJoin
++-plan=NestedLoopsJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=a]
 | | +-AttributeReference[id=0,name=int_col,relation=a,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=a,type=Long]
@@ -924,7 +924,7 @@
 | | +-AttributeReference[id=3,name=double_col,relation=a,type=Double NULL]
 | | +-AttributeReference[id=4,name=char_col,relation=a,type=Char(20)]
 | | +-AttributeReference[id=5,name=vchar_col,relation=a,type=VarChar(20) NULL]
-| +-right=Selection
+| +-right=Selection[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=7,name=long_col,relation=test,type=Long]
@@ -1021,8 +1021,8 @@
   +-AttributeReference[id=10,name=col,relation=,type=Double NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -1157,8 +1157,8 @@
   +-AttributeReference[id=6,name=col2,relation=,type=Long]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -1296,8 +1296,8 @@
   +-AttributeReference[id=4,name=subquery_col3,relation=subquery,type=Char(20)]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -1407,8 +1407,8 @@
   +-AttributeReference[id=6,name=,alias=count(*),relation=,type=Long]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -1465,8 +1465,8 @@
   +-AttributeReference[id=6,name=,alias=count(*),relation=,type=Long]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -1522,8 +1522,8 @@
   +-AttributeReference[id=7,name=,alias=count(*),relation=,type=Long]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -1585,7 +1585,7 @@
   +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=SharedSubplanReference[subplan_id=0]
 | | +-referenced_attributes=
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
@@ -1598,7 +1598,7 @@
 | +-project_expressions=
 |   +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 +-shared_subplans=
-| +-Selection
+| +-Selection[has_repartition=false]
 |   +-input=TableReference[relation=Test,alias=test]
 |   | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 |   | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -1673,8 +1673,8 @@
     type=Double NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -1786,9 +1786,9 @@
   +-AttributeReference[id=1,name=i,relation=,type=Int]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashLeftSemiJoin
-| +-left=HashLeftAntiJoin
-| | +-left=Selection
++-plan=HashLeftSemiJoin[has_repartition=false]
+| +-left=HashLeftAntiJoin[has_repartition=false]
+| | +-left=Selection[has_repartition=false]
 | | | +-input=TableGenerator[function_name=generate_series,table_alias=gs1]
 | | | | +-AttributeReference[id=0,name=generate_series,alias=gs1,
 | | | |   relation=generate_series,type=Int]
@@ -1859,7 +1859,7 @@
   +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -1925,7 +1925,7 @@
   +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -2014,7 +2014,7 @@
   +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashLeftSemiJoin
++-plan=HashLeftSemiJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -2022,8 +2022,8 @@
 | | +-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]
-| +-right=Selection
-| | +-input=Aggregate
+| +-right=Selection[has_repartition=false]
+| | +-input=Aggregate[has_repartition=false]
 | | | +-input=TableReference[relation=Test,alias=test]
 | | | | +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 | | | | +-AttributeReference[id=7,name=long_col,relation=test,type=Long]
@@ -2105,7 +2105,7 @@
   +-AttributeReference[id=4,name=char_col,relation=test,type=Char(20)]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashLeftAntiJoin
++-plan=HashLeftAntiJoin[has_repartition=false]
 | +-left=TableReference[relation=Test,alias=test]
 | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -2113,7 +2113,7 @@
 | | +-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]
-| +-right=Selection
+| +-right=Selection[has_repartition=false]
 | | +-input=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=7,name=long_col,relation=test,type=Long]
@@ -2179,11 +2179,11 @@
     type=Long NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=NestedLoopsJoin
++-plan=NestedLoopsJoin[has_repartition=false]
 | +-left=TableReference[relation=b]
 | | +-AttributeReference[id=0,name=w,relation=b,type=Int]
 | | +-AttributeReference[id=1,name=x,relation=b,type=Int]
-| +-right=Aggregate
+| +-right=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=c]
 | | | +-AttributeReference[id=2,name=x,relation=c,type=Int]
 | | | +-AttributeReference[id=3,name=y,relation=c,type=Int]
@@ -2246,8 +2246,8 @@
     type=Long NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashJoin
-| +-left=Aggregate
++-plan=HashJoin[has_repartition=false]
+| +-left=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=c]
 | | | +-AttributeReference[id=2,name=x,relation=c,type=Int]
 | | | +-AttributeReference[id=3,name=y,relation=c,type=Int]
@@ -2313,11 +2313,11 @@
   +-AttributeReference[id=1,name=x,relation=b,type=Int]
 [Physical Plan]
 TopLevelPlan
-+-plan=NestedLoopsJoin
++-plan=NestedLoopsJoin[has_repartition=false]
 | +-left=TableReference[relation=b]
 | | +-AttributeReference[id=0,name=w,relation=b,type=Int]
 | | +-AttributeReference[id=1,name=x,relation=b,type=Int]
-| +-right=Aggregate
+| +-right=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=c]
 | | | +-AttributeReference[id=2,name=x,relation=c,type=Int]
 | | | +-AttributeReference[id=3,name=y,relation=c,type=Int]
@@ -2383,8 +2383,8 @@
   +-AttributeReference[id=1,name=x,relation=b,type=Int]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashJoin
-| +-left=Aggregate
++-plan=HashJoin[has_repartition=false]
+| +-left=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=c]
 | | | +-AttributeReference[id=2,name=x,relation=c,type=Int]
 | | | +-AttributeReference[id=3,name=y,relation=c,type=Int]
@@ -2490,9 +2490,9 @@
     type=Long NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=HashJoin
-| +-left=NestedLoopsJoin
-| | +-left=Aggregate
++-plan=HashJoin[has_repartition=false]
+| +-left=NestedLoopsJoin[has_repartition=false]
+| | +-left=Aggregate[has_repartition=false]
 | | | +-input=TableReference[relation=c]
 | | | | +-AttributeReference[id=2,name=x,relation=c,type=Int]
 | | | | +-AttributeReference[id=3,name=y,relation=c,type=Int]
@@ -2505,7 +2505,7 @@
 | | |   +-Alias[id=4,name=,alias=$aggregate0,relation=$aggregate,type=Long NULL]
 | | |     +-AggregateFunction[function=SUM]
 | | |       +-AttributeReference[id=3,name=y,relation=c,type=Int]
-| | +-right=Aggregate
+| | +-right=Aggregate[has_repartition=false]
 | | | +-input=TableReference[relation=a]
 | | | | +-AttributeReference[id=5,name=w,relation=a,type=Int]
 | | | | +-AttributeReference[id=6,name=x,relation=a,type=Int]
@@ -2606,12 +2606,12 @@
     alias=((x*SubqueryExpression)+SubqueryExpression),relation=,type=Double NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=NestedLoopsJoin
++-plan=NestedLoopsJoin[has_repartition=false]
 | +-left=TableReference[relation=b]
 | | +-AttributeReference[id=0,name=w,relation=b,type=Int]
 | | +-AttributeReference[id=1,name=x,relation=b,type=Int]
-| +-right=NestedLoopsJoin
-| | +-left=Aggregate
+| +-right=NestedLoopsJoin[has_repartition=false]
+| | +-left=Aggregate[has_repartition=false]
 | | | +-input=TableReference[relation=c]
 | | | | +-AttributeReference[id=2,name=x,relation=c,type=Int]
 | | | | +-AttributeReference[id=3,name=y,relation=c,type=Int]
@@ -2621,7 +2621,7 @@
 | | |   +-Alias[id=4,name=,alias=$aggregate0,relation=$aggregate,type=Long NULL]
 | | |     +-AggregateFunction[function=SUM]
 | | |       +-AttributeReference[id=3,name=y,relation=c,type=Int]
-| | +-right=Aggregate
+| | +-right=Aggregate[has_repartition=false]
 | | | +-input=TableReference[relation=d]
 | | | | +-AttributeReference[id=5,name=y,relation=d,type=Int]
 | | | | +-AttributeReference[id=6,name=z,relation=d,type=Int]
@@ -2712,12 +2712,12 @@
     type=Long NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=NestedLoopsJoin
-| +-left=NestedLoopsJoin
++-plan=NestedLoopsJoin[has_repartition=false]
+| +-left=NestedLoopsJoin[has_repartition=false]
 | | +-left=TableReference[relation=b]
 | | | +-AttributeReference[id=0,name=w,relation=b,type=Int]
 | | | +-AttributeReference[id=1,name=x,relation=b,type=Int]
-| | +-right=Aggregate
+| | +-right=Aggregate[has_repartition=false]
 | | | +-input=TableReference[relation=d]
 | | | | +-AttributeReference[id=2,name=y,relation=d,type=Int]
 | | | | +-AttributeReference[id=3,name=z,relation=d,type=Int]
@@ -2734,7 +2734,7 @@
 | | |   type=Double NULL]
 | | +-project_expressions=
 | |   +-AttributeReference[id=1,name=x,relation=b,type=Int]
-| +-right=Aggregate
+| +-right=Aggregate[has_repartition=false]
 | | +-input=TableReference[relation=c]
 | | | +-AttributeReference[id=5,name=x,relation=c,type=Int]
 | | | +-AttributeReference[id=6,name=y,relation=c,type=Int]
@@ -2835,9 +2835,9 @@
   +-AttributeReference[id=6,name=y,relation=,type=Int]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=Sort[is_ascending=[true],nulls_first=[false]]
-| | +-input=HashJoin
+| | +-input=HashJoin[has_repartition=false]
 | | | +-left=SharedSubplanReference[subplan_id=0]
 | | | | +-referenced_attributes=
 | | | | | +-AttributeReference[id=3,name=x,relation=,type=Int]
@@ -2845,7 +2845,7 @@
 | | | | +-output_attributes=
 | | | |   +-AttributeReference[id=5,name=x,relation=,type=Int]
 | | | |   +-AttributeReference[id=6,name=y,relation=,type=Int]
-| | | +-right=Aggregate
+| | | +-right=Aggregate[has_repartition=false]
 | | | | +-input=SharedSubplanReference[subplan_id=0]
 | | | | | +-referenced_attributes=
 | | | | | | +-AttributeReference[id=3,name=x,relation=,type=Int]
@@ -2875,7 +2875,7 @@
 |   +-AttributeReference[id=5,name=x,relation=,type=Int]
 |   +-AttributeReference[id=6,name=y,relation=,type=Int]
 +-shared_subplans=
-| +-Selection
+| +-Selection[has_repartition=false]
 |   +-input=TableGenerator[function_name=generate_series,table_alias=g]
 |   | +-AttributeReference[id=0,name=generate_series,alias=g,
 |   |   relation=generate_series,type=Int]
@@ -2934,7 +2934,7 @@
   +-AttributeReference[id=6,name=,alias=avg(int_col),relation=,type=Double NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=WindowAggregate
 | | +-input=Sort[is_ascending=[true,false],nulls_first=[false,false]]
 | | | +-input=TableReference[relation=Test,alias=test]
@@ -3018,7 +3018,7 @@
     type=Double NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=WindowAggregate
 | | +-input=Sort[is_ascending=[true,true,false,true],
 | | | nulls_first=[false,false,false,true]]
@@ -3113,8 +3113,8 @@
     type=Double NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
-| +-input=Aggregate
++-plan=Selection[has_repartition=false]
+| +-input=Aggregate[has_repartition=false]
 | | +-input=WindowAggregate
 | | | +-input=Sort[is_ascending=[true,true],nulls_first=[false,false]]
 | | | | +-input=TableReference[relation=Test,alias=test]
@@ -3192,10 +3192,10 @@
   +-AttributeReference[id=12,name=int_col,relation=,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Aggregate
++-plan=Aggregate[has_repartition=false]
 | +-input=UnionAll
 | | +-operands=
-| | | +-Selection
+| | | +-Selection[has_repartition=false]
 | | | | +-input=TableReference[relation=Test,alias=test]
 | | | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -3207,7 +3207,7 @@
 | | | | |   type=VarChar(20) NULL]
 | | | | +-project_expressions=
 | | | |   +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
-| | | +-Selection
+| | | +-Selection[has_repartition=false]
 | | |   +-input=TableReference[relation=Test,alias=test]
 | | |   | +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 | | |   | +-AttributeReference[id=7,name=long_col,relation=test,type=Long]
@@ -3278,10 +3278,10 @@
   +-AttributeReference[id=14,name=intv,relation=,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Selection
++-plan=Selection[has_repartition=false]
 | +-input=UnionAll
 | | +-operands=
-| | | +-Selection
+| | | +-Selection[has_repartition=false]
 | | | | +-input=TableReference[relation=Test,alias=test]
 | | | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -3293,7 +3293,7 @@
 | | | | |   type=VarChar(20) NULL]
 | | | | +-project_expressions=
 | | | |   +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
-| | | +-Selection
+| | | +-Selection[has_repartition=false]
 | | |   +-input=TableReference[relation=Test,alias=test]
 | | |   | +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 | | |   | +-AttributeReference[id=7,name=long_col,relation=test,type=Long]
@@ -3384,8 +3384,8 @@
   +-AttributeReference[id=22,name=int_col,relation=,type=Int NULL]
 [Physical Plan]
 TopLevelPlan
-+-plan=Aggregate
-| +-input=HashLeftSemiJoin
++-plan=Aggregate[has_repartition=false]
+| +-input=HashLeftSemiJoin[has_repartition=false]
 | | +-left=TableReference[relation=Test,alias=test]
 | | | +-AttributeReference[id=0,name=int_col,relation=test,type=Int NULL]
 | | | +-AttributeReference[id=1,name=long_col,relation=test,type=Long]
@@ -3396,7 +3396,7 @@
 | | |   type=VarChar(20) NULL]
 | | +-right=UnionAll
 | | | +-operands=
-| | | | +-Selection
+| | | | +-Selection[has_repartition=false]
 | | | | | +-input=TableReference[relation=Test,alias=test]
 | | | | | | +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
 | | | | | | +-AttributeReference[id=7,name=long_col,relation=test,type=Long]
@@ -3408,7 +3408,7 @@
 | | | | | |   type=VarChar(20) NULL]
 | | | | | +-project_expressions=
 | | | | |   +-AttributeReference[id=6,name=int_col,relation=test,type=Int NULL]
-| | | | +-Selection
+| | | | +-Selection[has_repartition=false]
 | | | |   +-input=TableReference[relation=Test,alias=test]
 | | | |   | +-AttributeReference[id=12,name=int_col,relation=test,type=Int NULL]
 | | | |   | +-AttributeReference[id=13,name=long_col,relation=test,type=Long]
diff --git a/relational_operators/FinalizeAggregationOperator.hpp b/relational_operators/FinalizeAggregationOperator.hpp
index 382a7da..b344c13 100644
--- a/relational_operators/FinalizeAggregationOperator.hpp
+++ b/relational_operators/FinalizeAggregationOperator.hpp
@@ -61,6 +61,7 @@
    * @param aggr_state_index The index of the AggregationState in QueryContext.
    * @param num_partitions The number of partitions of 'input_relation' in a
    *        partitioned aggregation. If no partitions, it is one.
+   * @param has_repartition Whether this operator does repartition.
    * @param output_relation The output relation.
    * @param output_destination_index The index of the InsertDestination in the
    *        QueryContext to insert aggregation results.
@@ -69,10 +70,11 @@
       const std::size_t query_id,
       const QueryContext::aggregation_state_id aggr_state_index,
       const std::size_t num_partitions,
+      const bool has_repartition,
       const std::size_t aggr_state_num_partitions,
       const CatalogRelation &output_relation,
       const QueryContext::insert_destination_id output_destination_index)
-      : RelationalOperator(query_id, num_partitions),
+      : RelationalOperator(query_id, num_partitions, has_repartition),
         aggr_state_index_(aggr_state_index),
         aggr_state_num_partitions_(aggr_state_num_partitions),
         output_relation_(output_relation),
diff --git a/relational_operators/HashJoinOperator.hpp b/relational_operators/HashJoinOperator.hpp
index 519718c..a5e6eb4 100644
--- a/relational_operators/HashJoinOperator.hpp
+++ b/relational_operators/HashJoinOperator.hpp
@@ -104,6 +104,7 @@
    * @param any_join_key_attributes_nullable If any attribute is nullable.
    * @param num_partitions The number of partitions in 'probe_relation'.
    *        If no partitions, it is one.
+   * @param has_repartition Whether this operator does repartition.
    * @param output_relation The output relation.
    * @param output_destination_index The index of the InsertDestination in the
    *        QueryContext to insert the join results.
@@ -130,6 +131,7 @@
       const std::vector<attribute_id> &join_key_attributes,
       const bool any_join_key_attributes_nullable,
       const std::size_t num_partitions,
+      const bool has_repartition,
       const CatalogRelation &output_relation,
       const QueryContext::insert_destination_id output_destination_index,
       const QueryContext::join_hash_table_id hash_table_index,
@@ -137,7 +139,7 @@
       const QueryContext::scalar_group_id selection_index,
       const std::vector<bool> *is_selection_on_build = nullptr,
       const JoinType join_type = JoinType::kInnerJoin)
-      : RelationalOperator(query_id, num_partitions),
+      : RelationalOperator(query_id, num_partitions, has_repartition),
         build_relation_(build_relation),
         probe_relation_(probe_relation),
         probe_relation_is_stored_(probe_relation_is_stored),
diff --git a/relational_operators/NestedLoopsJoinOperator.hpp b/relational_operators/NestedLoopsJoinOperator.hpp
index 1b14638..777a737 100644
--- a/relational_operators/NestedLoopsJoinOperator.hpp
+++ b/relational_operators/NestedLoopsJoinOperator.hpp
@@ -74,6 +74,7 @@
    * @param right_input_relation The second relation in the join (order is not
    *        actually important).
    * @param num_partitions The number of partitions.
+   * @param has_repartition Whether this operator does repartition.
    * @param output_relation The output relation.
    * @param output_destination_index The index of the InsertDestination in the
    *        QueryContext to insert the join results.
@@ -94,13 +95,14 @@
       const CatalogRelation &left_input_relation,
       const CatalogRelation &right_input_relation,
       const std::size_t num_partitions,
+      const bool has_repartition,
       const CatalogRelation &output_relation,
       const QueryContext::insert_destination_id output_destination_index,
       const QueryContext::predicate_id join_predicate_index,
       const QueryContext::scalar_group_id selection_index,
       const bool left_relation_is_stored,
       const bool right_relation_is_stored)
-      : RelationalOperator(query_id, num_partitions),
+      : RelationalOperator(query_id, num_partitions, has_repartition),
         nested_loops_join_index_(nested_loops_join_index),
         left_input_relation_(left_input_relation),
         right_input_relation_(right_input_relation),
diff --git a/relational_operators/RelationalOperator.hpp b/relational_operators/RelationalOperator.hpp
index 29ae194..0541bbd 100644
--- a/relational_operators/RelationalOperator.hpp
+++ b/relational_operators/RelationalOperator.hpp
@@ -269,6 +269,15 @@
   }
 
   /**
+   * @brief Whether this operator does repartition.
+   *
+   * @return True if this node does repartition. Otherwise, false.
+   */
+  bool hasRepartition() const {
+    return has_repartition_;
+  }
+
+  /**
    * @brief Deploy a group of LIPFilters to this operator.
    */
   void deployLIPFilters(const QueryContext::lip_deployment_id lip_deployment_index,
@@ -284,16 +293,20 @@
    * @param query_id The ID of the query to which this operator belongs.
    * @param num_partitions The number of partitions of the input relation.
    *        If create table / index, return zero. If no partitions, return one.
+   * @param has_repartition Whether this operator does repartition.
    **/
   explicit RelationalOperator(const std::size_t query_id,
-                              const std::size_t num_partitions = 1u)
+                              const std::size_t num_partitions = 1u,
+                              const bool has_repartition = false)
       : query_id_(query_id),
         num_partitions_(num_partitions),
+        has_repartition_(has_repartition),
         done_feeding_input_relation_(false),
         lip_deployment_index_(QueryContext::kInvalidLIPDeploymentId) {}
 
   const std::size_t query_id_;
   const std::size_t num_partitions_;
+  const bool has_repartition_;
 
   bool done_feeding_input_relation_;
   std::size_t op_index_;
diff --git a/relational_operators/SelectOperator.hpp b/relational_operators/SelectOperator.hpp
index a71f4c1..71dcfca 100644
--- a/relational_operators/SelectOperator.hpp
+++ b/relational_operators/SelectOperator.hpp
@@ -74,6 +74,7 @@
    *
    * @param query_id The ID of the query to which this operator belongs.
    * @param input_relation The relation to perform selection over.
+   * @param has_repartition Whether this operator does repartition.
    * @param output_relation The output relation.
    * @param output_destination_index The index of the InsertDestination in the
    *        QueryContext to insert the selection results.
@@ -89,12 +90,13 @@
   SelectOperator(
       const std::size_t query_id,
       const CatalogRelation &input_relation,
+      const bool has_repartition,
       const CatalogRelation &output_relation,
       const QueryContext::insert_destination_id output_destination_index,
       const QueryContext::predicate_id predicate_index,
       const QueryContext::scalar_group_id selection_index,
       const bool input_relation_is_stored)
-      : RelationalOperator(query_id, input_relation.getNumPartitions()),
+      : RelationalOperator(query_id, input_relation.getNumPartitions(), has_repartition),
         input_relation_(input_relation),
         output_relation_(output_relation),
         output_destination_index_(output_destination_index),
@@ -129,6 +131,7 @@
    *
    * @param query_id The ID of the query to which this operator belongs.
    * @param input_relation The relation to perform selection over.
+   * @param has_repartition Whether this operator does repartition.
    * @param output_relation The output relation.
    * @param output_destination_index The index of the InsertDestination in the
    *        QueryContext to insert the selection results.
@@ -144,12 +147,13 @@
   SelectOperator(
       const std::size_t query_id,
       const CatalogRelation &input_relation,
+      const bool has_repartition,
       const CatalogRelation &output_relation,
       const QueryContext::insert_destination_id output_destination_index,
       const QueryContext::predicate_id predicate_index,
       std::vector<attribute_id> &&selection,
       const bool input_relation_is_stored)
-      : RelationalOperator(query_id, input_relation.getNumPartitions()),
+      : RelationalOperator(query_id, input_relation.getNumPartitions(), has_repartition),
         input_relation_(input_relation),
         output_relation_(output_relation),
         output_destination_index_(output_destination_index),
diff --git a/relational_operators/tests/AggregationOperator_unittest.cpp b/relational_operators/tests/AggregationOperator_unittest.cpp
index 4cda2d1..5c9cc7a 100644
--- a/relational_operators/tests/AggregationOperator_unittest.cpp
+++ b/relational_operators/tests/AggregationOperator_unittest.cpp
@@ -83,6 +83,7 @@
 constexpr std::size_t kQueryId = 0;
 constexpr int kOpIndex = 0;
 constexpr std::size_t kNumPartitions = 1u;
+constexpr bool kNoRepartition = false;
 }  // namespace
 
 class Type;
@@ -293,6 +294,7 @@
         new FinalizeAggregationOperator(kQueryId,
                                         aggr_state_index,
                                         kNumPartitions,
+                                        kNoRepartition,
                                         kNumPartitions,
                                         *result_table_,
                                         insert_destination_index));
@@ -388,6 +390,7 @@
         new FinalizeAggregationOperator(kQueryId,
                                         aggr_state_index,
                                         kNumPartitions,
+                                        kNoRepartition,
                                         kNumPartitions,
                                         *result_table_,
                                         insert_destination_index));
diff --git a/relational_operators/tests/HashJoinOperator_unittest.cpp b/relational_operators/tests/HashJoinOperator_unittest.cpp
index 89aafe5..1fc84fc 100644
--- a/relational_operators/tests/HashJoinOperator_unittest.cpp
+++ b/relational_operators/tests/HashJoinOperator_unittest.cpp
@@ -104,6 +104,9 @@
 constexpr std::size_t kSinglePartition = 1;
 constexpr std::size_t kMultiplePartitions = 4;
 
+const bool kHasRepartition = true;
+const bool kNoRepartition = false;
+
 }  // namespace
 
 class HashJoinOperatorTest : public ::testing::TestWithParam<HashTableImplType> {
@@ -454,6 +457,7 @@
       std::vector<attribute_id>(1, fact_col_long.getID()),
       fact_col_long.getType().isNullable(),
       kSinglePartition,
+      kNoRepartition,
       *result_table,
       output_destination_index,
       join_hash_table_index,
@@ -604,6 +608,7 @@
       std::vector<attribute_id>(1, fact_col_int.getID()),
       fact_col_int.getType().isNullable(),
       kSinglePartition,
+      kNoRepartition,
       *result_table,
       output_destination_index,
       join_hash_table_index,
@@ -763,6 +768,7 @@
       std::vector<attribute_id>(1, fact_col_char.getID()),
       fact_col_char.getType().isNullable(),
       kSinglePartition,
+      kNoRepartition,
       *result_table,
       output_destination_index,
       join_hash_table_index,
@@ -906,6 +912,7 @@
       std::vector<attribute_id>(1, fact_col_varchar.getID()),
       fact_col_varchar.getType().isNullable(),
       kSinglePartition,
+      kNoRepartition,
       *result_table,
       output_destination_index,
       join_hash_table_index,
@@ -1085,6 +1092,7 @@
       fact_col_long.getType().isNullable() ||
           fact_col_varchar.getType().isNullable(),
       kSinglePartition,
+      kNoRepartition,
       *result_table,
       output_destination_index,
       join_hash_table_index,
@@ -1274,6 +1282,7 @@
                            fact_col_long.getType().isNullable() ||
                                fact_col_varchar.getType().isNullable(),
                            kSinglePartition,
+                           kNoRepartition,
                            *result_table,
                            output_destination_index,
                            join_hash_table_index,
@@ -1446,6 +1455,7 @@
       { fact_col_long.getID() },
       fact_col_long.getType().isNullable(),
       kMultiplePartitions,
+      kHasRepartition,
       *result_table,
       output_destination_index,
       join_hash_table_index,
@@ -1591,6 +1601,7 @@
       { fact_col_long.getID(), fact_col_varchar.getID() },
       fact_col_long.getType().isNullable() || fact_col_varchar.getType().isNullable(),
       kMultiplePartitions,
+      kHasRepartition,
       *result_table,
       output_destination_index,
       join_hash_table_index,
@@ -1771,6 +1782,7 @@
       { fact_col_long.getID(), fact_col_varchar.getID() },
       fact_col_long.getType().isNullable() || fact_col_varchar.getType().isNullable(),
       kMultiplePartitions,
+      kHasRepartition,
       *result_table,
       output_destination_index,
       join_hash_table_index,