diff --git a/src/optimizer/robust_optimizer.cpp b/src/optimizer/robust_optimizer.cpp index 547754b..ee603e4 100644 --- a/src/optimizer/robust_optimizer.cpp +++ b/src/optimizer/robust_optimizer.cpp @@ -175,8 +175,29 @@ ColumnBinding RobustOptimizerContextState::ResolveColumnBinding(const ColumnBind return current; } +static idx_t TableUFFind(unordered_map &parent, idx_t x) { + if (parent.find(x) == parent.end()) { + parent[x] = x; + } + while (parent[x] != x) { + parent[x] = parent[parent[x]]; + x = parent[x]; + } + return x; +} + +static void TableUFUnion(unordered_map &parent, idx_t a, idx_t b) { + a = TableUFFind(parent, a); + b = TableUFFind(parent, b); + if (a != b) { + parent[a] = b; + } +} + vector RobustOptimizerContextState::CreateJoinEdges(vector &join_ops) { vector edges; + unordered_map table_parent; + set> seen_pairs; for (auto &op : join_ops) { auto &join = op->Cast(); @@ -215,6 +236,26 @@ vector RobustOptimizerContextState::CreateJoinEdges(vector v) { + std::swap(u, v); + } + if (!seen_pairs.count({u, v})) { + if (TableUFFind(table_parent, u) == TableUFFind(table_parent, v)) { + exist_cycle = true; + break; + } else { + seen_pairs.insert({u, v}); + TableUFUnion(table_parent, u, v); + } + } + } + if (exist_cycle) { + break; } } } @@ -1662,6 +1703,11 @@ unique_ptr RobustOptimizerContextState::Optimize(unique_ptr rename_col_bindings; + bool exist_cycle = false; + public: // extract all the join edges from the plan // vector ExtractOperators(LogicalOperator &plan, vector &join_ops); diff --git a/test/sql/plan_positive.test b/test/sql/plan_positive.test index 8dd1b04..7431a0f 100644 --- a/test/sql/plan_positive.test +++ b/test/sql/plan_positive.test @@ -84,26 +84,7 @@ WHERE t1.k12 = t2.k12 ---- physical_plan :.*PROBE_FILTER.* -# Correctness: triangle join -query II -EXPLAIN SELECT count(*) -FROM t2, t3, t4 -WHERE t2.k23 = t3.k23 - AND t3.k34 = t4.k34 - AND t2.k24 = t4.k24; ----- -physical_plan :.*CREATE_FILTER.* - -query II -EXPLAIN SELECT count(*) -FROM t2, t3, t4 -WHERE t2.k23 = t3.k23 - AND t3.k34 = t4.k34 - AND t2.k24 = t4.k24; ----- -physical_plan :.*PROBE_FILTER.* - -# Negative: four-table chain join +# Positive: four-table chain join query II EXPLAIN SELECT count(*) FROM t1, t2, t3, t4