@@ -96,10 +96,41 @@ JoinAssociativity::JoinAssociativity() {
96
96
bool JoinAssociativity::Check (std::shared_ptr<OperatorExpression> expr,
97
97
OptimizeContext *context) const {
98
98
(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
+ */
99
111
auto parent_join = expr->Op ().As <LogicalJoin>();
100
112
std::vector<std::shared_ptr<OperatorExpression>> children = expr->Children ();
101
113
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 ;
103
134
}
104
135
105
136
void JoinAssociativity::Transform (
@@ -164,8 +195,8 @@ void JoinAssociativity::Transform(
164
195
165
196
JoinType new_parent_join_type;
166
197
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 ;
169
200
// Construct new child join operator
170
201
std::shared_ptr<OperatorExpression> new_child_join =
171
202
std::make_shared<OperatorExpression>(
@@ -183,6 +214,15 @@ void JoinAssociativity::Transform(
183
214
transformed.push_back (new_parent_join);
184
215
}
185
216
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
+
186
226
// ===--------------------------------------------------------------------===//
187
227
// Implementation rules
188
228
// ===--------------------------------------------------------------------===//
0 commit comments