quickstep-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jianq...@apache.org
Subject [1/2] incubator-quickstep git commit: QUICKSTEP-121: Added the self-join support.
Date Wed, 09 May 2018 23:10:58 GMT
Repository: incubator-quickstep
Updated Branches:
  refs/heads/master 42588d433 -> 8b7c38010


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/BinaryExpression.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/BinaryExpression.cpp b/query_optimizer/expressions/BinaryExpression.cpp
index 07eb5ff..af4929c 100644
--- a/query_optimizer/expressions/BinaryExpression.cpp
+++ b/query_optimizer/expressions/BinaryExpression.cpp
@@ -23,6 +23,7 @@
 #include <cstddef>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -101,11 +102,13 @@ std::vector<AttributeReferencePtr> BinaryExpression::getReferencedAttributes() c
 }
 
 ::quickstep::Scalar *BinaryExpression::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   return new ::quickstep::ScalarBinaryExpression(
       operation_,
-      left_->concretize(substitution_map),
-      right_->concretize(substitution_map));
+      left_->concretize(substitution_map, left_expr_ids, right_expr_ids),
+      right_->concretize(substitution_map, left_expr_ids, right_expr_ids));
 }
 
 std::size_t BinaryExpression::computeHash() const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/BinaryExpression.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/BinaryExpression.hpp b/query_optimizer/expressions/BinaryExpression.hpp
index df7454c..92419f6 100644
--- a/query_optimizer/expressions/BinaryExpression.hpp
+++ b/query_optimizer/expressions/BinaryExpression.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -88,7 +89,9 @@ class BinaryExpression : public Scalar {
   std::vector<AttributeReferencePtr> getReferencedAttributes() const override;
 
   ::quickstep::Scalar* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   bool equals(const ScalarPtr &other) const override;
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/CMakeLists.txt b/query_optimizer/expressions/CMakeLists.txt
index 7032f05..03a8247 100644
--- a/query_optimizer/expressions/CMakeLists.txt
+++ b/query_optimizer/expressions/CMakeLists.txt
@@ -79,6 +79,7 @@ target_link_libraries(quickstep_queryoptimizer_expressions_Alias
 target_link_libraries(quickstep_queryoptimizer_expressions_AttributeReference
                       glog
                       quickstep_catalog_CatalogTypedefs
+                      quickstep_expressions_scalar_Scalar
                       quickstep_expressions_scalar_ScalarAttribute
                       quickstep_queryoptimizer_expressions_ExprId
                       quickstep_queryoptimizer_expressions_Expression

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/Cast.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/Cast.cpp b/query_optimizer/expressions/Cast.cpp
index e6eb1bd..c5d8f94 100644
--- a/query_optimizer/expressions/Cast.cpp
+++ b/query_optimizer/expressions/Cast.cpp
@@ -22,6 +22,7 @@
 #include <cstddef>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/scalar/Scalar.hpp"
@@ -52,9 +53,12 @@ ExpressionPtr Cast::copyWithNewChildren(
 }
 
 ::quickstep::Scalar *Cast::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
-  return new ::quickstep::ScalarUnaryExpression(::quickstep::NumericCastOperation::Instance(target_type_),
-                                                operand_->concretize(substitution_map));
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
+  return new ::quickstep::ScalarUnaryExpression(
+      ::quickstep::NumericCastOperation::Instance(target_type_),
+      operand_->concretize(substitution_map, left_expr_ids, right_expr_ids));
 }
 
 std::size_t Cast::computeHash() const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/Cast.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/Cast.hpp b/query_optimizer/expressions/Cast.hpp
index fa40242..2e7ea96 100644
--- a/query_optimizer/expressions/Cast.hpp
+++ b/query_optimizer/expressions/Cast.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -76,7 +77,9 @@ class Cast : public Scalar {
       const std::vector<ExpressionPtr> &new_children) const override;
 
   ::quickstep::Scalar* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   bool equals(const ScalarPtr &other) const override;
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/CommonSubexpression.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/CommonSubexpression.cpp b/query_optimizer/expressions/CommonSubexpression.cpp
index 4b13a0e..dcd3f1f 100644
--- a/query_optimizer/expressions/CommonSubexpression.cpp
+++ b/query_optimizer/expressions/CommonSubexpression.cpp
@@ -22,6 +22,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/scalar/ScalarSharedExpression.hpp"
@@ -47,10 +48,12 @@ ExpressionPtr CommonSubexpression::copyWithNewChildren(
 }
 
 ::quickstep::Scalar* CommonSubexpression::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   return new ::quickstep::ScalarSharedExpression(
       static_cast<int>(common_subexpression_id_),
-      operand_->concretize(substitution_map));
+      operand_->concretize(substitution_map, left_expr_ids, right_expr_ids));
 }
 
 void CommonSubexpression::getFieldStringItems(

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/CommonSubexpression.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/CommonSubexpression.hpp b/query_optimizer/expressions/CommonSubexpression.hpp
index 2c2d86c..f0482c9 100644
--- a/query_optimizer/expressions/CommonSubexpression.hpp
+++ b/query_optimizer/expressions/CommonSubexpression.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/expressions/AttributeReference.hpp"
@@ -93,7 +94,9 @@ class CommonSubexpression : public Scalar {
   }
 
   ::quickstep::Scalar* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Creates an immutable CommonSubexpression.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/ComparisonExpression.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/ComparisonExpression.cpp b/query_optimizer/expressions/ComparisonExpression.cpp
index 8d93794..5529eef 100644
--- a/query_optimizer/expressions/ComparisonExpression.cpp
+++ b/query_optimizer/expressions/ComparisonExpression.cpp
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/predicate/ComparisonPredicate.hpp"
@@ -80,11 +81,13 @@ ComparisonExpression::getReferencedAttributes() const {
 }
 
 ::quickstep::Predicate* ComparisonExpression::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   return new ::quickstep::ComparisonPredicate(
       comparison_,
-      left_->concretize(substitution_map),
-      right_->concretize(substitution_map));
+      left_->concretize(substitution_map, left_expr_ids, right_expr_ids),
+      right_->concretize(substitution_map, left_expr_ids, right_expr_ids));
 }
 
 void ComparisonExpression::getFieldStringItems(

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/ComparisonExpression.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/ComparisonExpression.hpp b/query_optimizer/expressions/ComparisonExpression.hpp
index f119f71..26d44fc 100644
--- a/query_optimizer/expressions/ComparisonExpression.hpp
+++ b/query_optimizer/expressions/ComparisonExpression.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -89,7 +90,9 @@ class ComparisonExpression : public Predicate {
   std::vector<AttributeReferencePtr> getReferencedAttributes() const override;
 
   ::quickstep::Predicate* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Creates an immutable ComparisonExpression.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/Exists.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/Exists.cpp b/query_optimizer/expressions/Exists.cpp
index bf4cb72..792704b 100644
--- a/query_optimizer/expressions/Exists.cpp
+++ b/query_optimizer/expressions/Exists.cpp
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -38,7 +39,9 @@ namespace optimizer {
 namespace expressions {
 
 ::quickstep::Predicate* Exists::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   LOG(FATAL) << "Exists predicate should not be concretized";
   return nullptr;
 }

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/Exists.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/Exists.hpp b/query_optimizer/expressions/Exists.hpp
index e90348e..7f1046d 100644
--- a/query_optimizer/expressions/Exists.hpp
+++ b/query_optimizer/expressions/Exists.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -86,7 +87,9 @@ class Exists : public Predicate {
   }
 
   ::quickstep::Predicate* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Create an Exists predicate expression.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/InTableQuery.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/InTableQuery.cpp b/query_optimizer/expressions/InTableQuery.cpp
index 79018e5..29d8a4e 100644
--- a/query_optimizer/expressions/InTableQuery.cpp
+++ b/query_optimizer/expressions/InTableQuery.cpp
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -33,7 +34,9 @@ namespace optimizer {
 namespace expressions {
 
 ::quickstep::Predicate* InTableQuery::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   LOG(FATAL) << "InTableQuery predicate should not be concretized";
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/InTableQuery.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/InTableQuery.hpp b/query_optimizer/expressions/InTableQuery.hpp
index 245ff0d..bb659fb 100644
--- a/query_optimizer/expressions/InTableQuery.hpp
+++ b/query_optimizer/expressions/InTableQuery.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -96,7 +97,9 @@ class InTableQuery : public Predicate {
   }
 
   ::quickstep::Predicate* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Create an IN predicate with a subquery.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/InValueList.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/InValueList.cpp b/query_optimizer/expressions/InValueList.cpp
index d968d48..55f65b1 100644
--- a/query_optimizer/expressions/InValueList.cpp
+++ b/query_optimizer/expressions/InValueList.cpp
@@ -22,6 +22,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/predicate/DisjunctionPredicate.hpp"
@@ -40,7 +41,9 @@ namespace optimizer {
 namespace expressions {
 
 ::quickstep::Predicate* InValueList::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   std::unique_ptr<quickstep::DisjunctionPredicate>
       disjunction_predicate(new quickstep::DisjunctionPredicate());
   for (const ScalarPtr &match_expression : match_expressions_) {
@@ -51,7 +54,7 @@ namespace expressions {
             match_expression);
 
     disjunction_predicate->addPredicate(
-        match_predicate->concretize(substitution_map));
+        match_predicate->concretize(substitution_map, left_expr_ids, right_expr_ids));
   }
   return disjunction_predicate.release();
 }

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/InValueList.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/InValueList.hpp b/query_optimizer/expressions/InValueList.hpp
index e0f1f57..3d37352 100644
--- a/query_optimizer/expressions/InValueList.hpp
+++ b/query_optimizer/expressions/InValueList.hpp
@@ -24,6 +24,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -109,7 +110,9 @@ class InValueList : public Predicate {
   }
 
   ::quickstep::Predicate* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Create an IN predicate with a value list.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/LogicalAnd.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/LogicalAnd.cpp b/query_optimizer/expressions/LogicalAnd.cpp
index a3908bd..9bcc02c 100644
--- a/query_optimizer/expressions/LogicalAnd.cpp
+++ b/query_optimizer/expressions/LogicalAnd.cpp
@@ -22,6 +22,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/predicate/ConjunctionPredicate.hpp"
@@ -86,13 +87,15 @@ std::vector<AttributeReferencePtr> LogicalAnd::getReferencedAttributes() const {
 }
 
 ::quickstep::Predicate* LogicalAnd::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   if (operands_.empty()) {
     return new TruePredicate();
   }
 
   if (operands_.size() == 1u) {
-    return operands_[0]->concretize(substitution_map);
+    return operands_[0]->concretize(substitution_map, left_expr_ids, right_expr_ids);
   }
 
   std::unique_ptr<::quickstep::ConjunctionPredicate> concretized_predicate;
@@ -100,7 +103,7 @@ std::vector<AttributeReferencePtr> LogicalAnd::getReferencedAttributes() const {
 
   for (const PredicatePtr &operand : operands_) {
     concretized_predicate->addPredicate(
-        operand->concretize(substitution_map));
+        operand->concretize(substitution_map, left_expr_ids, right_expr_ids));
   }
 
   return concretized_predicate.release();

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/LogicalAnd.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/LogicalAnd.hpp b/query_optimizer/expressions/LogicalAnd.hpp
index 8785fc8..93dc39c 100644
--- a/query_optimizer/expressions/LogicalAnd.hpp
+++ b/query_optimizer/expressions/LogicalAnd.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -88,7 +89,9 @@ class LogicalAnd : public Predicate {
   std::vector<AttributeReferencePtr> getReferencedAttributes() const override;
 
   ::quickstep::Predicate* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Creates an immutable LogicalAnd. If any operand is also a LogicalAnd,

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/LogicalNot.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/LogicalNot.cpp b/query_optimizer/expressions/LogicalNot.cpp
index dce13a9..a6ccbd2 100644
--- a/query_optimizer/expressions/LogicalNot.cpp
+++ b/query_optimizer/expressions/LogicalNot.cpp
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/predicate/NegationPredicate.hpp"
@@ -44,9 +45,11 @@ ExpressionPtr LogicalNot::copyWithNewChildren(
 }
 
 ::quickstep::Predicate* LogicalNot::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   return new ::quickstep::NegationPredicate(
-      operand_->concretize(substitution_map));
+      operand_->concretize(substitution_map, left_expr_ids, right_expr_ids));
 }
 
 void LogicalNot::getFieldStringItems(

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/LogicalNot.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/LogicalNot.hpp b/query_optimizer/expressions/LogicalNot.hpp
index 7c4e660..9d773c5 100644
--- a/query_optimizer/expressions/LogicalNot.hpp
+++ b/query_optimizer/expressions/LogicalNot.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -73,7 +74,9 @@ class LogicalNot : public Predicate {
   }
 
   ::quickstep::Predicate* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Creates an immutable LogicalNot.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/LogicalOr.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/LogicalOr.cpp b/query_optimizer/expressions/LogicalOr.cpp
index c89fd5a..4126493 100644
--- a/query_optimizer/expressions/LogicalOr.cpp
+++ b/query_optimizer/expressions/LogicalOr.cpp
@@ -22,6 +22,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/predicate/DisjunctionPredicate.hpp"
@@ -84,13 +85,15 @@ std::vector<AttributeReferencePtr> LogicalOr::getReferencedAttributes() const {
 }
 
 ::quickstep::Predicate* LogicalOr::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   if (operands_.empty()) {
     return new FalsePredicate();
   }
 
   if (operands_.size() == 1u) {
-    return operands_[0]->concretize(substitution_map);
+    return operands_[0]->concretize(substitution_map, left_expr_ids, right_expr_ids);
   }
 
   std::unique_ptr<::quickstep::DisjunctionPredicate> concretized_predicate;
@@ -98,7 +101,7 @@ std::vector<AttributeReferencePtr> LogicalOr::getReferencedAttributes() const {
 
   for (const PredicatePtr &operand : operands_) {
     concretized_predicate->addPredicate(
-        operand->concretize(substitution_map));
+        operand->concretize(substitution_map, left_expr_ids, right_expr_ids));
   }
 
   return concretized_predicate.release();

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/LogicalOr.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/LogicalOr.hpp b/query_optimizer/expressions/LogicalOr.hpp
index 2e40c56..52f9ad3 100644
--- a/query_optimizer/expressions/LogicalOr.hpp
+++ b/query_optimizer/expressions/LogicalOr.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -88,7 +89,9 @@ class LogicalOr : public Predicate {
   std::vector<AttributeReferencePtr> getReferencedAttributes() const override;
 
   ::quickstep::Predicate* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Creates an immutable LogicalOr. If any operand is also a LogicalOr,

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/Predicate.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/Predicate.hpp b/query_optimizer/expressions/Predicate.hpp
index 444af6b..a0918e6 100644
--- a/query_optimizer/expressions/Predicate.hpp
+++ b/query_optimizer/expressions/Predicate.hpp
@@ -22,6 +22,7 @@
 
 #include <memory>
 #include <unordered_map>
+#include <unordered_set>
 
 #include "query_optimizer/expressions/ExprId.hpp"
 #include "query_optimizer/expressions/Expression.hpp"
@@ -70,10 +71,14 @@ class Predicate : public Expression {
    *
    * @param substitution_map Map from ExprId to CatalogAttribute for use in
    *                         replacing AttributeReference.
+   * @param left_expr_ids The ExprIds from the left hand side.
+   * @param right_expr_ids The ExprIds from the right hand side.
    * @return A concretized predicate for evaluation.
    */
   virtual ::quickstep::Predicate* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*>& substitution_map) const = 0;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const = 0;
 
  protected:
   Predicate() {}

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/PredicateLiteral.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/PredicateLiteral.cpp b/query_optimizer/expressions/PredicateLiteral.cpp
index 724458e..fb48eb3 100644
--- a/query_optimizer/expressions/PredicateLiteral.cpp
+++ b/query_optimizer/expressions/PredicateLiteral.cpp
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/predicate/TrivialPredicates.hpp"
@@ -40,7 +41,9 @@ ExpressionPtr PredicateLiteral::copyWithNewChildren(
 }
 
 ::quickstep::Predicate* PredicateLiteral::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   if (is_true()) {
     return new TruePredicate();
   } else {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/PredicateLiteral.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/PredicateLiteral.hpp b/query_optimizer/expressions/PredicateLiteral.hpp
index f354a83..f53b6e3 100644
--- a/query_optimizer/expressions/PredicateLiteral.hpp
+++ b/query_optimizer/expressions/PredicateLiteral.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -70,7 +71,9 @@ class PredicateLiteral : public Predicate {
   }
 
   ::quickstep::Predicate* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Creates an immutable PredicateLiteral.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/Scalar.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/Scalar.hpp b/query_optimizer/expressions/Scalar.hpp
index a163b21..5635a10 100644
--- a/query_optimizer/expressions/Scalar.hpp
+++ b/query_optimizer/expressions/Scalar.hpp
@@ -23,6 +23,7 @@
 #include <cstddef>
 #include <memory>
 #include <unordered_map>
+#include <unordered_set>
 
 #include "query_optimizer/expressions/Expression.hpp"
 #include "query_optimizer/expressions/ExprId.hpp"
@@ -61,11 +62,14 @@ class Scalar : public Expression {
    * @param substitution_map Map from ExprId to CatalogAttribute for use in
    *                         substituting CatalogAttribute for
    *                         AttributeReference.
+   * @param left_expr_ids The ExprIds from the left hand side.
+   * @param right_expr_ids The ExprIds from the right hand side.
    * @return Concretized expression for evaluation.
    */
   virtual ::quickstep::Scalar* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*>& substitution_map)
-      const = 0;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const = 0;
 
   /**
    * @brief Check whether this scalar is semantically equivalent to \p other.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/ScalarLiteral.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/ScalarLiteral.cpp b/query_optimizer/expressions/ScalarLiteral.cpp
index d2ab527..3b1bef5 100644
--- a/query_optimizer/expressions/ScalarLiteral.cpp
+++ b/query_optimizer/expressions/ScalarLiteral.cpp
@@ -22,6 +22,7 @@
 #include <cstddef>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/scalar/ScalarLiteral.hpp"
@@ -50,7 +51,9 @@ ExpressionPtr ScalarLiteral::copyWithNewChildren(
 }
 
 ::quickstep::Scalar *ScalarLiteral::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   return new ::quickstep::ScalarLiteral(value_, value_type_);
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/ScalarLiteral.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/ScalarLiteral.hpp b/query_optimizer/expressions/ScalarLiteral.hpp
index 7fab1d0..fc5e09d 100644
--- a/query_optimizer/expressions/ScalarLiteral.hpp
+++ b/query_optimizer/expressions/ScalarLiteral.hpp
@@ -24,6 +24,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -80,7 +81,9 @@ class ScalarLiteral : public Scalar {
   }
 
   ::quickstep::Scalar* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   bool equals(const ScalarPtr &other) const override;
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/SearchedCase.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/SearchedCase.cpp b/query_optimizer/expressions/SearchedCase.cpp
index c53e030..8e40b7b 100644
--- a/query_optimizer/expressions/SearchedCase.cpp
+++ b/query_optimizer/expressions/SearchedCase.cpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -114,15 +115,21 @@ ExpressionPtr SearchedCase::copyWithNewChildren(
 }
 
 ::quickstep::Scalar* SearchedCase::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   std::vector<std::unique_ptr<quickstep::Predicate>> when_predicates;
+  when_predicates.reserve(condition_predicates_.size());
   for (const PredicatePtr &predicate : condition_predicates_) {
-    when_predicates.emplace_back(predicate->concretize(substitution_map));
+    when_predicates.emplace_back(
+        predicate->concretize(substitution_map, left_expr_ids, right_expr_ids));
   }
 
   std::vector<std::unique_ptr<quickstep::Scalar>> result_expressions;
+  result_expressions.reserve(conditional_result_expressions_.size());
   for (const ScalarPtr &expression : conditional_result_expressions_) {
-    result_expressions.emplace_back(expression->concretize(substitution_map));
+    result_expressions.emplace_back(
+        expression->concretize(substitution_map, left_expr_ids, right_expr_ids));
   }
 
   std::unique_ptr<quickstep::Scalar> else_result_expression;
@@ -131,14 +138,14 @@ ExpressionPtr SearchedCase::copyWithNewChildren(
         new quickstep::ScalarLiteral(value_type_.makeNullValue(), value_type_));
   } else {
     else_result_expression.reset(
-        else_result_expression_->concretize(substitution_map));
+        else_result_expression_->concretize(substitution_map, left_expr_ids, right_expr_ids));
   }
 
   return new quickstep::ScalarCaseExpression(
       value_type_,
       std::move(when_predicates),
       std::move(result_expressions),
-      else_result_expression_->concretize(substitution_map));
+      else_result_expression_->concretize(substitution_map, left_expr_ids, right_expr_ids));
 }
 
 void SearchedCase::getFieldStringItems(

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/SearchedCase.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/SearchedCase.hpp b/query_optimizer/expressions/SearchedCase.hpp
index 3466396..8744642 100644
--- a/query_optimizer/expressions/SearchedCase.hpp
+++ b/query_optimizer/expressions/SearchedCase.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/scalar/Scalar.hpp"
@@ -101,7 +102,9 @@ class SearchedCase : public Scalar {
       const std::vector<ExpressionPtr> &new_children) const override;
 
   ::quickstep::Scalar* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*>& substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Creates an immutable SearchedCase.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/SimpleCase.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/SimpleCase.cpp b/query_optimizer/expressions/SimpleCase.cpp
index f11c8c8..21ee244 100644
--- a/query_optimizer/expressions/SimpleCase.cpp
+++ b/query_optimizer/expressions/SimpleCase.cpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -133,8 +134,11 @@ ExpressionPtr SimpleCase::copyWithNewChildren(const std::vector<ExpressionPtr> &
 }
 
 ::quickstep::Scalar* SimpleCase::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   std::vector<std::unique_ptr<quickstep::Predicate>> when_predicates;
+  when_predicates.reserve(condition_operands_.size());
   for (const ScalarPtr &condition_operand : condition_operands_) {
     const PredicatePtr predicate =
         ComparisonExpression::Create(
@@ -145,6 +149,7 @@ ExpressionPtr SimpleCase::copyWithNewChildren(const std::vector<ExpressionPtr> &
   }
 
   std::vector<std::unique_ptr<quickstep::Scalar>> result_expressions;
+  result_expressions.reserve(conditional_result_expressions_.size());
   for (const ScalarPtr &expression : conditional_result_expressions_) {
     result_expressions.emplace_back(expression->concretize(substitution_map));
   }

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/SimpleCase.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/SimpleCase.hpp b/query_optimizer/expressions/SimpleCase.hpp
index b42c034..e05c4ef 100644
--- a/query_optimizer/expressions/SimpleCase.hpp
+++ b/query_optimizer/expressions/SimpleCase.hpp
@@ -24,6 +24,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/scalar/Scalar.hpp"
@@ -109,7 +110,9 @@ class SimpleCase : public Scalar {
       const std::vector<ExpressionPtr> &new_children) const override;
 
   ::quickstep::Scalar* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*>& substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   bool equals(const ScalarPtr &other) const override;
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/SubqueryExpression.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/SubqueryExpression.cpp b/query_optimizer/expressions/SubqueryExpression.cpp
index bc5a6d3..b6c4772 100644
--- a/query_optimizer/expressions/SubqueryExpression.cpp
+++ b/query_optimizer/expressions/SubqueryExpression.cpp
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/OptimizerTree.hpp"
@@ -38,7 +39,9 @@ namespace optimizer {
 namespace expressions {
 
 ::quickstep::Scalar* SubqueryExpression::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   LOG(FATAL) << "SubqueryExpression should not be concretized";
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/SubqueryExpression.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/SubqueryExpression.hpp b/query_optimizer/expressions/SubqueryExpression.hpp
index 184bc8c..96bf204 100644
--- a/query_optimizer/expressions/SubqueryExpression.hpp
+++ b/query_optimizer/expressions/SubqueryExpression.hpp
@@ -23,6 +23,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/expressions/AttributeReference.hpp"
@@ -87,7 +88,9 @@ class SubqueryExpression : public Scalar {
   }
 
   ::quickstep::Scalar* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   /**
    * @brief Creates a subquery expression.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/UnaryExpression.cpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/UnaryExpression.cpp b/query_optimizer/expressions/UnaryExpression.cpp
index b448553..4d91e03 100644
--- a/query_optimizer/expressions/UnaryExpression.cpp
+++ b/query_optimizer/expressions/UnaryExpression.cpp
@@ -22,6 +22,7 @@
 #include <cstddef>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "expressions/scalar/ScalarUnaryExpression.hpp"
@@ -53,9 +54,11 @@ ExpressionPtr UnaryExpression::copyWithNewChildren(
 }
 
 ::quickstep::Scalar* UnaryExpression::concretize(
-    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const {
+    const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+    const std::unordered_set<ExprId> &left_expr_ids,
+    const std::unordered_set<ExprId> &right_expr_ids) const {
   return new ::quickstep::ScalarUnaryExpression(
-      operation_, operand_->concretize(substitution_map));
+      operation_, operand_->concretize(substitution_map, left_expr_ids, right_expr_ids));
 }
 
 std::size_t UnaryExpression::computeHash() const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/expressions/UnaryExpression.hpp
----------------------------------------------------------------------
diff --git a/query_optimizer/expressions/UnaryExpression.hpp b/query_optimizer/expressions/UnaryExpression.hpp
index 9b99377..314ad5d 100644
--- a/query_optimizer/expressions/UnaryExpression.hpp
+++ b/query_optimizer/expressions/UnaryExpression.hpp
@@ -24,6 +24,7 @@
 #include <memory>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include "query_optimizer/expressions/AttributeReference.hpp"
@@ -84,7 +85,9 @@ class UnaryExpression : public Scalar {
   }
 
   ::quickstep::Scalar* concretize(
-      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override;
+      const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map,
+      const std::unordered_set<ExprId> &left_expr_ids = std::unordered_set<ExprId>(),
+      const std::unordered_set<ExprId> &right_expr_ids = std::unordered_set<ExprId>()) const override;
 
   bool equals(const ScalarPtr &other) const override;
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/query_optimizer/tests/execution_generator/Select.test
----------------------------------------------------------------------
diff --git a/query_optimizer/tests/execution_generator/Select.test b/query_optimizer/tests/execution_generator/Select.test
index 494e759..ee9c18e 100644
--- a/query_optimizer/tests/execution_generator/Select.test
+++ b/query_optimizer/tests/execution_generator/Select.test
@@ -269,7 +269,6 @@ WHERE int_col < 10
 +-----------+--------------------+
 ==
 
-# The execution engine currently does not support self-join.
 SELECT a.int_col,
        a.int_col*b.int_col,
        b.long_col
@@ -277,7 +276,32 @@ FROM test AS a,
      test AS b
 WHERE a.int_col*b.int_col = b.long_col;
 --
-ERROR: NestedLoopsJoin does not support self-join yet
++-----------+---------------------+--------------------+
+|int_col    |(a.int_col*b.int_col)|long_col            |
++-----------+---------------------+--------------------+
+|         -1|                    1|                   1|
+|          2|                    4|                   4|
+|         -3|                    9|                   9|
+|          4|                   16|                  16|
+|         -5|                   25|                  25|
+|          6|                   36|                  36|
+|         -7|                   49|                  49|
+|          8|                   64|                  64|
+|         -9|                   81|                  81|
+|        -11|                  121|                 121|
+|         12|                  144|                 144|
+|        -13|                  169|                 169|
+|         14|                  196|                 196|
+|        -15|                  225|                 225|
+|         16|                  256|                 256|
+|        -17|                  289|                 289|
+|         18|                  324|                 324|
+|        -19|                  361|                 361|
+|        -21|                  441|                 441|
+|         22|                  484|                 484|
+|        -23|                  529|                 529|
+|         24|                  576|                 576|
++-----------+---------------------+--------------------+
 ==
 
 # The nested loops join is not a self-join, because the predicate "a.int_col<10" is pushed under the join, which results
@@ -305,14 +329,38 @@ WHERE a.long_col < 100
 +-----------+---------------------+--------------------+
 ==
 
-# Hash join does not support the self-join.
 SELECT a.int_col,
        b.int_col
 FROM test AS a,
      test AS b
 WHERE a.int_col = b.int_col;
 --
-ERROR: Self-join is not supported
++-----------+-----------+
+|int_col    |int_col    |
++-----------+-----------+
+|         -1|         -1|
+|          2|          2|
+|         -3|         -3|
+|          4|          4|
+|         -5|         -5|
+|          6|          6|
+|         -7|         -7|
+|          8|          8|
+|         -9|         -9|
+|        -11|        -11|
+|         12|         12|
+|        -13|        -13|
+|         14|         14|
+|        -15|        -15|
+|         16|         16|
+|        -17|        -17|
+|         18|         18|
+|        -19|        -19|
+|        -21|        -21|
+|         22|         22|
+|        -23|        -23|
+|         24|         24|
++-----------+-----------+
 ==
 
 # This is not a self-join, because there is a Select under the HashJoin for "a.long_col < 50".

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/relational_operators/HashJoinOperator.cpp
----------------------------------------------------------------------
diff --git a/relational_operators/HashJoinOperator.cpp b/relational_operators/HashJoinOperator.cpp
index 4083bd3..f08de9d 100644
--- a/relational_operators/HashJoinOperator.cpp
+++ b/relational_operators/HashJoinOperator.cpp
@@ -72,7 +72,7 @@ typedef std::pair<std::vector<tuple_id>, std::vector<tuple_id>> PairOfTupleIdVec
 // Functor passed to HashTable::getAllFromValueAccessor() to collect matching
 // tuples from the inner relation. It stores matching tuple ID pairs
 // in an unordered_map keyed by inner block ID and a vector of
-// pairs of (build-tupleID, probe-tuple-ID).
+// pairs of (probe-tupleID, build-tuple-ID).
 class VectorsOfPairsJoinedTuplesCollector {
  public:
   VectorsOfPairsJoinedTuplesCollector() {
@@ -81,7 +81,7 @@ class VectorsOfPairsJoinedTuplesCollector {
   template <typename ValueAccessorT>
   inline void operator()(const ValueAccessorT &accessor,
                          const TupleReference &tref) {
-    joined_tuples_[tref.block].emplace_back(tref.tuple, accessor.getCurrentPosition());
+    joined_tuples_[tref.block].emplace_back(accessor.getCurrentPosition(), tref.tuple);
   }
 
   // Get a mutable pointer to the collected map of joined tuple ID pairs. The
@@ -102,7 +102,7 @@ class VectorsOfPairsJoinedTuplesCollector {
 };
 
 // Another collector using an unordered_map keyed on inner block just like above,
-// except that it uses of a pair of (build-tupleIDs-vector, probe-tuple-IDs-vector).
+// except that it uses of a pair of (probe-tupleIDs-vector, build-tuple-IDs-vector).
 class PairsOfVectorsJoinedTuplesCollector {
  public:
   PairsOfVectorsJoinedTuplesCollector() {
@@ -112,8 +112,8 @@ class PairsOfVectorsJoinedTuplesCollector {
   inline void operator()(const ValueAccessorT &accessor,
                          const TupleReference &tref) {
     auto &entry = joined_tuples_[tref.block];
-    entry.first.emplace_back(tref.tuple);
-    entry.second.emplace_back(accessor.getCurrentPosition());
+    entry.first.emplace_back(accessor.getCurrentPosition());
+    entry.second.emplace_back(tref.tuple);
   }
 
   // Get a mutable pointer to the collected map of joined tuple ID pairs. The
@@ -151,7 +151,8 @@ class OuterJoinTupleCollector {
   template <typename ValueAccessorT>
   inline void operator()(const ValueAccessorT &accessor,
                          const TupleReference &tref) {
-    joined_tuples_[tref.block].emplace_back(tref.tuple, accessor.getCurrentPosition());
+    // <probe-tid, build-tid>.
+    joined_tuples_[tref.block].emplace_back(accessor.getCurrentPosition(), tref.tuple);
   }
 
   template <typename ValueAccessorT>
@@ -165,7 +166,7 @@ class OuterJoinTupleCollector {
   }
 
  private:
-  std::unordered_map<block_id, std::vector<std::pair<tuple_id, tuple_id>>> joined_tuples_;
+  std::unordered_map<block_id, VectorOfTupleIdPair> joined_tuples_;
   // BitVector on the probe relation. 1 if the corresponding tuple has no match.
   TupleIdSequence *filter_;
 };
@@ -490,9 +491,6 @@ void HashInnerJoinWorkOrder::executeWithoutCopyElision(ValueAccessor *probe_acce
         &collector);
   }
 
-  const relation_id build_relation_id = build_relation_.getID();
-  const relation_id probe_relation_id = probe_relation_.getID();
-
   for (std::pair<const block_id, VectorOfTupleIdPair>
            &build_block_entry : *collector.getJoinedTuples()) {
     BlockReference build_block =
@@ -515,11 +513,9 @@ void HashInnerJoinWorkOrder::executeWithoutCopyElision(ValueAccessor *probe_acce
 
       for (const std::pair<tuple_id, tuple_id> &hash_match
            : build_block_entry.second) {
-        if (residual_predicate_->matchesForJoinedTuples(*build_accessor,
-                                                        build_relation_id,
+        if (residual_predicate_->matchesForJoinedTuples(*probe_accessor,
                                                         hash_match.first,
-                                                        *probe_accessor,
-                                                        probe_relation_id,
+                                                        *build_accessor,
                                                         hash_match.second)) {
           filtered_matches.emplace_back(hash_match);
         }
@@ -533,10 +529,8 @@ void HashInnerJoinWorkOrder::executeWithoutCopyElision(ValueAccessor *probe_acce
     for (auto selection_cit = selection_.begin();
          selection_cit != selection_.end();
          ++selection_cit) {
-      temp_result.addColumn((*selection_cit)->getAllValuesForJoin(build_relation_id,
+      temp_result.addColumn((*selection_cit)->getAllValuesForJoin(probe_accessor,
                                                                   build_accessor.get(),
-                                                                  probe_relation_id,
-                                                                  probe_accessor,
                                                                   build_block_entry.second,
                                                                   cv_cache.get()));
     }
@@ -562,9 +556,6 @@ void HashInnerJoinWorkOrder::executeWithCopyElision(ValueAccessor *probe_accesso
         &collector);
   }
 
-  const relation_id build_relation_id = build_relation_.getID();
-  const relation_id probe_relation_id = probe_relation_.getID();
-
   constexpr std::size_t kNumIndexes = 3u;
   constexpr std::size_t kBuildIndex = 0, kProbeIndex = 1u, kTempIndex = 2u;
 
@@ -584,11 +575,15 @@ void HashInnerJoinWorkOrder::executeWithCopyElision(ValueAccessor *probe_accesso
       accessor_attribute_map[kTempIndex].second[dest_attr] = non_trivial_expressions.size();
       non_trivial_expressions.emplace_back(scalar.get());
     } else {
-      const CatalogAttribute &attr = static_cast<const ScalarAttribute *>(scalar.get())->getAttribute();
-      const attribute_id attr_id = attr.getID();
-      if (attr.getParent().getID() == build_relation_id) {
+      const Scalar::JoinSide join_side = scalar->join_side();
+      DCHECK(join_side != Scalar::kNone);
+
+      const attribute_id attr_id =
+          static_cast<const ScalarAttribute *>(scalar.get())->getAttribute().getID();
+      if (join_side == Scalar::kRightSide) {
         accessor_attribute_map[kBuildIndex].second[dest_attr] = attr_id;
       } else {
+        DCHECK(join_side == Scalar::kLeftSide);
         accessor_attribute_map[kProbeIndex].second[dest_attr] = attr_id;
       }
     }
@@ -601,8 +596,8 @@ void HashInnerJoinWorkOrder::executeWithCopyElision(ValueAccessor *probe_accesso
         storage_manager_->getBlock(build_block_entry.first, build_relation_);
     const TupleStorageSubBlock &build_store = build_block->getTupleStorageSubBlock();
     std::unique_ptr<ValueAccessor> build_accessor(build_store.createValueAccessor());
-    const std::vector<tuple_id> &build_tids = build_block_entry.second.first;
-    const std::vector<tuple_id> &probe_tids = build_block_entry.second.second;
+    const std::vector<tuple_id> &build_tids = build_block_entry.second.second;
+    const std::vector<tuple_id> &probe_tids = build_block_entry.second.first;
 
     // Evaluate '*residual_predicate_', if any.
     //
@@ -618,14 +613,12 @@ void HashInnerJoinWorkOrder::executeWithCopyElision(ValueAccessor *probe_accesso
       PairOfTupleIdVector filtered_matches;
 
       for (std::size_t i = 0; i < build_tids.size(); ++i) {
-        if (residual_predicate_->matchesForJoinedTuples(*build_accessor,
-                                                        build_relation_id,
-                                                        build_tids[i],
-                                                        *probe_accessor,
-                                                        probe_relation_id,
-                                                        probe_tids[i])) {
-          filtered_matches.first.emplace_back(build_tids[i]);
-          filtered_matches.second.emplace_back(probe_tids[i]);
+        if (residual_predicate_->matchesForJoinedTuples(*probe_accessor,
+                                                        probe_tids[i],
+                                                        *build_accessor,
+                                                        build_tids[i])) {
+          filtered_matches.first.emplace_back(probe_tids[i]);
+          filtered_matches.second.emplace_back(build_tids[i]);
         }
       }
 
@@ -646,15 +639,13 @@ void HashInnerJoinWorkOrder::executeWithCopyElision(ValueAccessor *probe_accesso
       // zip our two vectors together.
       VectorOfTupleIdPair zipped_joined_tuple_ids;
       for (std::size_t i = 0; i < build_tids.size(); ++i) {
-        zipped_joined_tuple_ids.emplace_back(build_tids[i], probe_tids[i]);
+        zipped_joined_tuple_ids.emplace_back(probe_tids[i], build_tids[i]);
       }
 
       ColumnVectorCache cv_cache;
       for (const Scalar *scalar : non_trivial_expressions) {
-        temp_result.addColumn(scalar->getAllValuesForJoin(build_relation_id,
+        temp_result.addColumn(scalar->getAllValuesForJoin(probe_accessor,
                                                           build_accessor.get(),
-                                                          probe_relation_id,
-                                                          probe_accessor,
                                                           zipped_joined_tuple_ids,
                                                           &cv_cache));
       }
@@ -690,9 +681,6 @@ void HashSemiJoinWorkOrder::execute() {
 }
 
 void HashSemiJoinWorkOrder::executeWithResidualPredicate() {
-  const relation_id build_relation_id = build_relation_.getID();
-  const relation_id probe_relation_id = probe_relation_.getID();
-
   BlockReference probe_block = storage_manager_->getBlock(block_id_,
                                                           probe_relation_);
   const TupleStorageSubBlock &probe_store = probe_block->getTupleStorageSubBlock();
@@ -752,11 +740,9 @@ void HashSemiJoinWorkOrder::executeWithResidualPredicate() {
         // probe side, skip it.
         continue;
       }
-      if (residual_predicate_->matchesForJoinedTuples(*build_accessor,
-                                                      build_relation_id,
+      if (residual_predicate_->matchesForJoinedTuples(*probe_accessor,
                                                       hash_match.first,
-                                                      *probe_accessor,
-                                                      probe_relation_id,
+                                                      *build_accessor,
                                                       hash_match.second)) {
         filter.set(hash_match.second);
       }
@@ -910,9 +896,6 @@ void HashAntiJoinWorkOrder::executeWithoutResidualPredicate() {
 }
 
 void HashAntiJoinWorkOrder::executeWithResidualPredicate() {
-  const relation_id build_relation_id = build_relation_.getID();
-  const relation_id probe_relation_id = probe_relation_.getID();
-
   BlockReference probe_block = storage_manager_->getBlock(block_id_,
                                                           probe_relation_);
   const TupleStorageSubBlock &probe_store = probe_block->getTupleStorageSubBlock();
@@ -970,11 +953,9 @@ void HashAntiJoinWorkOrder::executeWithResidualPredicate() {
         // We have already seen this tuple, skip it.
         continue;
       }
-      if (residual_predicate_->matchesForJoinedTuples(*build_accessor,
-                                                      build_relation_id,
+      if (residual_predicate_->matchesForJoinedTuples(*probe_accessor,
                                                       hash_match.first,
-                                                      *probe_accessor,
-                                                      probe_relation_id,
+                                                      *build_accessor,
                                                       hash_match.second)) {
         // Note that the existence map marks a match as false, as needed by the
         // anti join definition.
@@ -1008,9 +989,6 @@ void HashAntiJoinWorkOrder::executeWithResidualPredicate() {
 void HashOuterJoinWorkOrder::execute() {
   output_destination_->setInputPartitionId(partition_id_);
 
-  const relation_id build_relation_id = build_relation_.getID();
-  const relation_id probe_relation_id = probe_relation_.getID();
-
   const BlockReference probe_block = storage_manager_->getBlock(block_id_,
                                                                 probe_relation_);
   const TupleStorageSubBlock &probe_store = probe_block->getTupleStorageSubBlock();
@@ -1061,10 +1039,8 @@ void HashOuterJoinWorkOrder::execute() {
          ++selection_it) {
       temp_result.addColumn(
           (*selection_it)->getAllValuesForJoin(
-              build_relation_id,
-              build_accessor.get(),
-              probe_relation_id,
               probe_accessor.get(),
+              build_accessor.get(),
               build_block_entry.second,
               cv_cache.get()));
     }

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/relational_operators/NestedLoopsJoinOperator.cpp
----------------------------------------------------------------------
diff --git a/relational_operators/NestedLoopsJoinOperator.cpp b/relational_operators/NestedLoopsJoinOperator.cpp
index 658f84b..8be9cb3 100644
--- a/relational_operators/NestedLoopsJoinOperator.cpp
+++ b/relational_operators/NestedLoopsJoinOperator.cpp
@@ -407,9 +407,6 @@ serialization::WorkOrder* NestedLoopsJoinOperator::createWorkOrderProto(const pa
 template <bool LEFT_PACKED, bool RIGHT_PACKED>
 void NestedLoopsJoinWorkOrder::executeHelper(const TupleStorageSubBlock &left_store,
                                              const TupleStorageSubBlock &right_store) {
-  const relation_id left_input_relation_id = left_input_relation_.getID();
-  const relation_id right_input_relation_id = right_input_relation_.getID();
-
   const tuple_id left_max_tid = left_store.getMaxTupleID();
   const tuple_id right_max_tid = right_store.getMaxTupleID();
 
@@ -428,10 +425,8 @@ void NestedLoopsJoinWorkOrder::executeHelper(const TupleStorageSubBlock &left_st
         if (RIGHT_PACKED || right_store.hasTupleWithID(right_tid)) {
           // For each tuple in the right block...
           if (join_predicate_->matchesForJoinedTuples(*left_accessor,
-                                                      left_input_relation_id,
                                                       left_tid,
                                                       *right_accessor,
-                                                      right_input_relation_id,
                                                       right_tid)) {
             joined_tuple_ids.emplace_back(left_tid, right_tid);
           }
@@ -460,9 +455,7 @@ void NestedLoopsJoinWorkOrder::executeHelper(const TupleStorageSubBlock &left_st
     for (vector<unique_ptr<const Scalar>>::const_iterator selection_cit = selection_.begin();
          selection_cit != selection_.end();
          ++selection_cit) {
-      temp_result.addColumn((*selection_cit)->getAllValuesForJoin(left_input_relation_id,
-                                                                  left_accessor.get(),
-                                                                  right_input_relation_id,
+      temp_result.addColumn((*selection_cit)->getAllValuesForJoin(left_accessor.get(),
                                                                   right_accessor.get(),
                                                                   joined_tuple_ids,
                                                                   cv_cache.get()));

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/8b7c3801/relational_operators/tests/HashJoinOperator_unittest.cpp
----------------------------------------------------------------------
diff --git a/relational_operators/tests/HashJoinOperator_unittest.cpp b/relational_operators/tests/HashJoinOperator_unittest.cpp
index eeeca4b..1ea1a37 100644
--- a/relational_operators/tests/HashJoinOperator_unittest.cpp
+++ b/relational_operators/tests/HashJoinOperator_unittest.cpp
@@ -432,7 +432,7 @@ TEST_P(HashJoinOperatorTest, LongKeyHashJoinTest) {
 
   // Create the prober operator with one selection attribute.
   const QueryContext::scalar_group_id selection_index = query_context_proto.scalar_groups_size();
-  ScalarAttribute scalar_attr(dim_col_long);
+  ScalarAttribute scalar_attr(dim_col_long, Scalar::kRightSide);
   query_context_proto.add_scalar_groups()->add_scalars()->MergeFrom(scalar_attr.getProto());
 
   // Create result_table, owned by db_.
@@ -581,9 +581,9 @@ TEST_P(HashJoinOperatorTest, IntDuplicateKeyHashJoinTest) {
   const QueryContext::scalar_group_id selection_index = query_context_proto.scalar_groups_size();
   serialization::QueryContext::ScalarGroup *scalar_group_proto = query_context_proto.add_scalar_groups();
 
-  ScalarAttribute scalar_attr_dim(dim_col_long);
+  ScalarAttribute scalar_attr_dim(dim_col_long, Scalar::kRightSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_dim.getProto());
-  ScalarAttribute scalar_attr_fact(fact_col_long);
+  ScalarAttribute scalar_attr_fact(fact_col_long, Scalar::kLeftSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_fact.getProto());
 
   // Create result_table, owned by db_.
@@ -745,7 +745,7 @@ TEST_P(HashJoinOperatorTest, CharKeyCartesianProductHashJoinTest) {
 
   // Create prober operator with one selection attribute.
   const QueryContext::scalar_group_id selection_index = query_context_proto.scalar_groups_size();
-  ScalarAttribute scalar_attr(dim_col_long);
+  ScalarAttribute scalar_attr(dim_col_long, Scalar::kRightSide);
   query_context_proto.add_scalar_groups()->add_scalars()->MergeFrom(scalar_attr.getProto());
 
   // Create result_table, owned by db_.
@@ -887,9 +887,9 @@ TEST_P(HashJoinOperatorTest, VarCharDuplicateKeyHashJoinTest) {
   const QueryContext::scalar_group_id selection_index = query_context_proto.scalar_groups_size();
   serialization::QueryContext::ScalarGroup *scalar_group_proto = query_context_proto.add_scalar_groups();
 
-  ScalarAttribute scalar_attr_dim(dim_col_long);
+  ScalarAttribute scalar_attr_dim(dim_col_long, Scalar::kRightSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_dim.getProto());
-  ScalarAttribute scalar_attr_fact(fact_col_long);
+  ScalarAttribute scalar_attr_fact(fact_col_long, Scalar::kLeftSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_fact.getProto());
 
   // Create result_table, owned by db_.
@@ -1063,9 +1063,9 @@ TEST_P(HashJoinOperatorTest, CompositeKeyHashJoinTest) {
   const QueryContext::scalar_group_id selection_index = query_context_proto.scalar_groups_size();
   serialization::QueryContext::ScalarGroup *scalar_group_proto = query_context_proto.add_scalar_groups();
 
-  ScalarAttribute scalar_attr_dim(dim_col_long);
+  ScalarAttribute scalar_attr_dim(dim_col_long, Scalar::kRightSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_dim.getProto());
-  ScalarAttribute scalar_attr_fact(fact_col_long);
+  ScalarAttribute scalar_attr_fact(fact_col_long, Scalar::kLeftSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_fact.getProto());
 
   // Create result_table, owned by db_.
@@ -1244,9 +1244,9 @@ TEST_P(HashJoinOperatorTest, CompositeKeyHashJoinWithResidualPredicateTest) {
   const QueryContext::scalar_group_id selection_index = query_context_proto.scalar_groups_size();
   serialization::QueryContext::ScalarGroup *scalar_group_proto = query_context_proto.add_scalar_groups();
 
-  ScalarAttribute scalar_attr_dim(dim_col_long);
+  ScalarAttribute scalar_attr_dim(dim_col_long, Scalar::kRightSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_dim.getProto());
-  ScalarAttribute scalar_attr_fact(fact_col_long);
+  ScalarAttribute scalar_attr_fact(fact_col_long, Scalar::kLeftSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_fact.getProto());
 
   // Create result_table, owned by db_.
@@ -1269,7 +1269,7 @@ TEST_P(HashJoinOperatorTest, CompositeKeyHashJoinWithResidualPredicateTest) {
   unique_ptr<Predicate> residual_pred(new ComparisonPredicate(
       ComparisonFactory::GetComparison(
           ComparisonID::kLess),
-          new ScalarAttribute(dim_col_long),
+          new ScalarAttribute(dim_col_long, Scalar::kRightSide),
           new ScalarLiteral(TypedValue(static_cast<std::int64_t>(15)), LongType::InstanceNonNullable())));
 
   std::vector<attribute_id> fact_key_attrs;
@@ -1436,7 +1436,7 @@ TEST_P(HashJoinOperatorTest, SingleAttributePartitionedLongKeyHashJoinTest) {
 
   // Create the prober operator with one selection attribute.
   const QueryContext::scalar_group_id selection_index = query_context_proto.scalar_groups_size();
-  ScalarAttribute scalar_attr(dim_col_long);
+  ScalarAttribute scalar_attr(dim_col_long, Scalar::kRightSide);
   query_context_proto.add_scalar_groups()->add_scalars()->MergeFrom(scalar_attr.getProto());
 
   // Create result_table, owned by db_.
@@ -1580,9 +1580,9 @@ TEST_P(HashJoinOperatorTest, SingleAttributePartitionedCompositeKeyHashJoinTest)
   const QueryContext::scalar_group_id selection_index = query_context_proto.scalar_groups_size();
   serialization::QueryContext::ScalarGroup *scalar_group_proto = query_context_proto.add_scalar_groups();
 
-  ScalarAttribute scalar_attr_dim(dim_col_long);
+  ScalarAttribute scalar_attr_dim(dim_col_long, Scalar::kRightSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_dim.getProto());
-  ScalarAttribute scalar_attr_fact(fact_col_long);
+  ScalarAttribute scalar_attr_fact(fact_col_long, Scalar::kLeftSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_fact.getProto());
 
   // Create result_table, owned by db_.
@@ -1752,9 +1752,9 @@ TEST_P(HashJoinOperatorTest, SingleAttributePartitionedCompositeKeyHashJoinWithR
   const QueryContext::scalar_group_id selection_index = query_context_proto.scalar_groups_size();
   serialization::QueryContext::ScalarGroup *scalar_group_proto = query_context_proto.add_scalar_groups();
 
-  ScalarAttribute scalar_attr_dim(dim_col_long);
+  ScalarAttribute scalar_attr_dim(dim_col_long, Scalar::kRightSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_dim.getProto());
-  ScalarAttribute scalar_attr_fact(fact_col_long);
+  ScalarAttribute scalar_attr_fact(fact_col_long, Scalar::kLeftSide);
   scalar_group_proto->add_scalars()->MergeFrom(scalar_attr_fact.getProto());
 
   // Create result_table, owned by db_.
@@ -1777,7 +1777,7 @@ TEST_P(HashJoinOperatorTest, SingleAttributePartitionedCompositeKeyHashJoinWithR
   unique_ptr<Predicate> residual_pred(new ComparisonPredicate(
       ComparisonFactory::GetComparison(
           ComparisonID::kLess),
-          new ScalarAttribute(dim_col_long),
+          new ScalarAttribute(dim_col_long, Scalar::kRightSide),
           new ScalarLiteral(TypedValue(static_cast<std::int64_t>(15)), LongType::InstanceNonNullable())));
 
   const QueryContext::predicate_id residual_pred_index = query_context_proto.predicates_size();


Mime
View raw message