@@ -96,10 +96,41 @@ JoinAssociativity::JoinAssociativity() {
9696bool JoinAssociativity::Check (std::shared_ptr<OperatorExpression> expr,
9797 OptimizeContext *context) const {
9898 (void )context;
99+ // Associativity rules taken from
100+ // http://15721.courses.cs.cmu.edu/spring2017/papers/14-optimizer1/p539-moerkotte.pdf
101+ /*
102+ * (A inner B) inner C = A inner (B inner C)
103+ * (A right B) inner C = A right (B inner C)
104+ * (A inner B) left C = A inner (B left C)
105+ * (A left B) left C = A left (B left C) with Strong Predicates PBC
106+ * (A full B) left C = A full (B left C) with Strong Predicate PBC
107+ * (A right B) right C = A right (B right C) with Strong Predicate PAB
108+ * (A right B) full C = A right (B full C) with Strong Predicate PAB
109+ * (A full B) full C = A full (B full C) with Strong Predicate PAB & PBC
110+ */
99111 auto parent_join = expr->Op ().As <LogicalJoin>();
100112 std::vector<std::shared_ptr<OperatorExpression>> children = expr->Children ();
101113 auto child_join = children[0 ]->Op ().As <LogicalJoin>();
102- return (parent_join->type == child_join->type );
114+ if (parent_join->type == JoinType::INNER) {
115+ if (child_join->type == JoinType::INNER || child_join->type == JoinType::RIGHT) {
116+ return true ;
117+ }
118+ } else if (parent_join->type == JoinType::LEFT) {
119+ if (child_join->type == JoinType::INNER) {
120+ return true ;
121+ } else if (child_join->type == JoinType::LEFT || child_join->type == JoinType::OUTER) {
122+ return StrongPredicate (expr, context);
123+ }
124+ } else if (parent_join->type == JoinType::RIGHT) {
125+ if (child_join->type == JoinType::RIGHT) {
126+ return StrongPredicate (expr, context);
127+ }
128+ } else if (parent_join->type == JoinType::OUTER) {
129+ if (child_join->type == JoinType::RIGHT || child_join->type == JoinType::OUTER) {
130+ return StrongPredicate (expr, context);
131+ }
132+ }
133+ return false ;
103134}
104135
105136void JoinAssociativity::Transform (
@@ -164,8 +195,8 @@ void JoinAssociativity::Transform(
164195
165196 JoinType new_parent_join_type;
166197 JoinType new_child_join_type;
167- new_parent_join_type = parent_join ->type ;
168- new_child_join_type = child_join ->type ;
198+ new_parent_join_type = child_join ->type ;
199+ new_child_join_type = parent_join ->type ;
169200 // Construct new child join operator
170201 std::shared_ptr<OperatorExpression> new_child_join =
171202 std::make_shared<OperatorExpression>(
@@ -183,6 +214,15 @@ void JoinAssociativity::Transform(
183214 transformed.push_back (new_parent_join);
184215}
185216
217+ // TODO: some associativity rules can only be applied when the predicate is strong
218+ // To check if the predicate is strong or not is non-trivial
219+ bool JoinAssociativity::StrongPredicate (std::shared_ptr<OperatorExpression> expr,
220+ OptimizeContext *context) const {
221+ (void )context;
222+ (void )expr;
223+ return false ;
224+ }
225+
186226// ===--------------------------------------------------------------------===//
187227// Implementation rules
188228// ===--------------------------------------------------------------------===//
0 commit comments