@@ -18,7 +18,10 @@ use datafusion::{
18
18
} ;
19
19
use itertools:: Itertools ;
20
20
use optd_datafusion_repr:: {
21
- plan_nodes:: { ConstantType , OptRelNode , PlanNode } ,
21
+ plan_nodes:: {
22
+ ConstantType , OptRelNode , OptRelNodeRef , OptRelNodeTyp , PhysicalHashJoin ,
23
+ PhysicalNestedLoopJoin , PlanNode ,
24
+ } ,
22
25
properties:: schema:: Catalog ,
23
26
DatafusionOptimizer , MemoExt ,
24
27
} ;
@@ -193,6 +196,17 @@ impl OptdQueryPlanner {
193
196
} ,
194
197
join_orders. iter ( ) . map ( |x| x. to_string ( ) ) . join ( "\n " ) ,
195
198
) ) ;
199
+ let join_order = get_join_order ( optimized_rel. clone ( ) ) ;
200
+ explains. push ( StringifiedPlan :: new (
201
+ PlanType :: OptimizedPhysicalPlan {
202
+ optimizer_name : "optd-join-order" . to_string ( ) ,
203
+ } ,
204
+ if let Some ( join_order) = join_order {
205
+ join_order. to_string ( )
206
+ } else {
207
+ "None" . to_string ( )
208
+ } ,
209
+ ) ) ;
196
210
}
197
211
198
212
tracing:: trace!(
@@ -241,3 +255,54 @@ impl QueryPlanner for OptdQueryPlanner {
241
255
. unwrap ( ) )
242
256
}
243
257
}
258
+
259
+ #[ derive( Debug , Eq , PartialEq , Hash , PartialOrd , Ord ) ]
260
+ enum JoinOrder {
261
+ Table ( String ) ,
262
+ HashJoin ( Box < Self > , Box < Self > ) ,
263
+ NestedLoopJoin ( Box < Self > , Box < Self > ) ,
264
+ }
265
+
266
+ impl std:: fmt:: Display for JoinOrder {
267
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
268
+ match self {
269
+ JoinOrder :: Table ( name) => write ! ( f, "{}" , name) ,
270
+ JoinOrder :: HashJoin ( left, right) => {
271
+ write ! ( f, "(HashJoin {} {})" , left, right)
272
+ }
273
+ JoinOrder :: NestedLoopJoin ( left, right) => {
274
+ write ! ( f, "(NLJ {} {})" , left, right)
275
+ }
276
+ }
277
+ }
278
+ }
279
+
280
+ fn get_join_order ( rel_node : OptRelNodeRef ) -> Option < JoinOrder > {
281
+ match rel_node. typ {
282
+ OptRelNodeTyp :: PhysicalHashJoin ( _) => {
283
+ let join = PhysicalHashJoin :: from_rel_node ( rel_node. clone ( ) ) . unwrap ( ) ;
284
+ let left = get_join_order ( join. left ( ) . into_rel_node ( ) ) ?;
285
+ let right = get_join_order ( join. right ( ) . into_rel_node ( ) ) ?;
286
+ Some ( JoinOrder :: HashJoin ( Box :: new ( left) , Box :: new ( right) ) )
287
+ }
288
+ OptRelNodeTyp :: PhysicalNestedLoopJoin ( _) => {
289
+ let join = PhysicalNestedLoopJoin :: from_rel_node ( rel_node. clone ( ) ) . unwrap ( ) ;
290
+ let left = get_join_order ( join. left ( ) . into_rel_node ( ) ) ?;
291
+ let right = get_join_order ( join. right ( ) . into_rel_node ( ) ) ?;
292
+ Some ( JoinOrder :: NestedLoopJoin ( Box :: new ( left) , Box :: new ( right) ) )
293
+ }
294
+ OptRelNodeTyp :: PhysicalScan => {
295
+ let scan =
296
+ optd_datafusion_repr:: plan_nodes:: PhysicalScan :: from_rel_node ( rel_node) . unwrap ( ) ;
297
+ Some ( JoinOrder :: Table ( scan. table ( ) . to_string ( ) ) )
298
+ }
299
+ _ => {
300
+ for child in & rel_node. children {
301
+ if let Some ( res) = get_join_order ( child. clone ( ) ) {
302
+ return Some ( res) ;
303
+ }
304
+ }
305
+ None
306
+ }
307
+ }
308
+ }
0 commit comments