22#include " binder/expression/property_expression.h"
33#include " binder/expression/subquery_expression.h"
44#include " binder/expression_visitor.h"
5+ #include " planner/join_order/cost_model.h"
56#include " planner/operator/factorization/flatten_resolver.h"
67#include " planner/planner.h"
78
@@ -100,6 +101,17 @@ void Planner::planOptionalMatch(const QueryGraphCollection& queryGraphCollection
100101 }
101102}
102103
104+ template <std::invocable<LogicalPlan&, LogicalPlan&, LogicalPlan&> AppendJoinFunc,
105+ std::invocable<LogicalPlan&, LogicalPlan&> EstimateJoinCostFunc>
106+ static void planRegularMatchJoinOrder (LogicalPlan& leftPlan, LogicalPlan& rightPlan,
107+ const AppendJoinFunc& appendJoinFunc, const EstimateJoinCostFunc& estimateJoinCostFunc) {
108+ if (estimateJoinCostFunc (leftPlan, rightPlan) <= estimateJoinCostFunc (rightPlan, leftPlan)) {
109+ appendJoinFunc (leftPlan, rightPlan, leftPlan);
110+ } else {
111+ appendJoinFunc (rightPlan, leftPlan, leftPlan);
112+ }
113+ }
114+
103115void Planner::planRegularMatch (const QueryGraphCollection& queryGraphCollection,
104116 const expression_vector& predicates, LogicalPlan& leftPlan) {
105117 expression_vector predicatesToPushDown, predicatesToPullUp;
@@ -124,7 +136,15 @@ void Planner::planRegularMatch(const QueryGraphCollection& queryGraphCollection,
124136 if (leftPlan.hasUpdate ()) {
125137 appendCrossProduct (*rightPlan, leftPlan, leftPlan);
126138 } else {
127- appendCrossProduct (leftPlan, *rightPlan, leftPlan);
139+ planRegularMatchJoinOrder (
140+ leftPlan, *rightPlan,
141+ [this ](LogicalPlan& leftPlan, LogicalPlan& rightPlan, LogicalPlan& resultPlan) {
142+ appendCrossProduct (leftPlan, rightPlan, resultPlan);
143+ },
144+ [](LogicalPlan&, LogicalPlan& rightPlan) {
145+ // we want to minimize the cardinality of the build plan
146+ return rightPlan.getCardinality ();
147+ });
128148 }
129149 } else {
130150 // TODO(Xiyang): there is a question regarding if we want to plan as a correlated subquery
@@ -137,7 +157,16 @@ void Planner::planRegularMatch(const QueryGraphCollection& queryGraphCollection,
137157 if (leftPlan.hasUpdate ()) {
138158 appendHashJoin (joinNodeIDs, JoinType::INNER, *rightPlan, leftPlan, leftPlan);
139159 } else {
140- appendHashJoin (joinNodeIDs, JoinType::INNER, leftPlan, *rightPlan, leftPlan);
160+ planRegularMatchJoinOrder (
161+ leftPlan, *rightPlan,
162+ [this , &joinNodeIDs](LogicalPlan& leftPlan, LogicalPlan& rightPlan,
163+ LogicalPlan& resultPlan) {
164+ appendHashJoin (joinNodeIDs, JoinType::INNER, leftPlan, rightPlan, resultPlan);
165+ },
166+ [&joinNodeIDs](LogicalPlan& leftPlan, LogicalPlan& rightPlan) {
167+ return CostModel::computeHashJoinCost (joinNodeIDs, leftPlan, rightPlan);
168+ });
169+ // appendHashJoin(joinNodeIDs, JoinType::INNER, leftPlan, *rightPlan, leftPlan);
141170 }
142171 }
143172 for (auto & predicate : predicatesToPullUp) {
0 commit comments