@@ -35,7 +35,9 @@ use databend_common_pipeline::core::Pipe;
3535use databend_common_pipeline:: core:: PipeItem ;
3636use databend_common_pipeline:: core:: ProcessorPtr ;
3737use databend_common_sql:: optimizer:: ir:: SExpr ;
38+ use databend_common_sql:: plans:: FunctionCall ;
3839use databend_common_sql:: plans:: Join ;
40+ use databend_common_sql:: plans:: JoinEquiCondition ;
3941use databend_common_sql:: plans:: JoinType ;
4042use databend_common_sql:: ColumnEntry ;
4143use databend_common_sql:: ColumnSet ;
@@ -52,6 +54,7 @@ use crate::physical_plans::format::PhysicalFormat;
5254use crate :: physical_plans:: physical_plan:: IPhysicalPlan ;
5355use crate :: physical_plans:: physical_plan:: PhysicalPlan ;
5456use crate :: physical_plans:: physical_plan:: PhysicalPlanMeta ;
57+ use crate :: physical_plans:: resolve_scalar;
5558use crate :: physical_plans:: runtime_filter:: build_runtime_filter;
5659use crate :: physical_plans:: Exchange ;
5760use crate :: physical_plans:: PhysicalPlanBuilder ;
@@ -99,6 +102,12 @@ type MergedFieldsResult = (
99102 Vec < ( usize , ( bool , bool ) ) > ,
100103) ;
101104
105+ #[ derive( Clone , Debug , serde:: Serialize , serde:: Deserialize ) ]
106+ pub struct NestedLoopFilterInfo {
107+ pub predicates : Vec < RemoteExpr > ,
108+ pub projection : Vec < usize > ,
109+ }
110+
102111#[ derive( Clone , Debug , serde:: Serialize , serde:: Deserialize ) ]
103112pub struct HashJoin {
104113 pub meta : PhysicalPlanMeta ,
@@ -140,6 +149,7 @@ pub struct HashJoin {
140149
141150 pub runtime_filter : PhysicalRuntimeFilters ,
142151 pub broadcast_id : Option < u32 > ,
152+ pub nested_loop_filter : NestedLoopFilterInfo ,
143153}
144154
145155#[ typetag:: serde]
@@ -261,6 +271,7 @@ impl IPhysicalPlan for HashJoin {
261271 build_side_cache_info : self . build_side_cache_info . clone ( ) ,
262272 runtime_filter : self . runtime_filter . clone ( ) ,
263273 broadcast_id : self . broadcast_id ,
274+ nested_loop_filter : self . nested_loop_filter . clone ( ) ,
264275 } )
265276 }
266277
@@ -1184,6 +1195,25 @@ impl PhysicalPlanBuilder {
11841195 . collect :: < Result < _ > > ( )
11851196 }
11861197
1198+ fn build_nested_loop_filter_info (
1199+ & self ,
1200+ join : & Join ,
1201+ merged_schema : & DataSchemaRef ,
1202+ ) -> Result < NestedLoopFilterInfo > {
1203+ let predicates = join
1204+ . non_equi_conditions
1205+ . iter ( )
1206+ . map ( |c| Ok ( c. clone ( ) ) )
1207+ . chain ( join. equi_conditions . iter ( ) . map ( condition_to_expr) )
1208+ . map ( |scalar| resolve_scalar ( & scalar?, merged_schema) )
1209+ . collect :: < Result < _ > > ( ) ?;
1210+
1211+ Ok ( NestedLoopFilterInfo {
1212+ predicates,
1213+ projection : vec ! [ ] ,
1214+ } )
1215+ }
1216+
11871217 pub async fn build_hash_join (
11881218 & mut self ,
11891219 join : & Join ,
@@ -1256,6 +1286,8 @@ impl PhysicalPlanBuilder {
12561286 // Step 10: Process non-equi conditions
12571287 let non_equi_conditions = self . process_non_equi_conditions ( join, & merged_schema) ?;
12581288
1289+ let nested_loop_filter = self . build_nested_loop_filter_info ( join, & merged_schema) ?;
1290+
12591291 // Step 11: Build runtime filter
12601292 let runtime_filter = build_runtime_filter (
12611293 self . ctx . clone ( ) ,
@@ -1300,6 +1332,32 @@ impl PhysicalPlanBuilder {
13001332 build_side_cache_info,
13011333 runtime_filter,
13021334 broadcast_id,
1335+ nested_loop_filter,
13031336 } ) )
13041337 }
13051338}
1339+
1340+ fn condition_to_expr ( condition : & JoinEquiCondition ) -> Result < ScalarExpr > {
1341+ let left_type = condition. left . data_type ( ) ?;
1342+ let right_type = condition. right . data_type ( ) ?;
1343+
1344+ let arguments = match ( & left_type, & right_type) {
1345+ ( DataType :: Nullable ( left) , right) if * * left == * right => vec ! [
1346+ condition. left. clone( ) ,
1347+ condition. right. clone( ) . unify_to_data_type( & left_type) ,
1348+ ] ,
1349+ ( left, DataType :: Nullable ( right) ) if * left == * * right => vec ! [
1350+ condition. left. clone( ) . unify_to_data_type( & right_type) ,
1351+ condition. right. clone( ) ,
1352+ ] ,
1353+ _ => vec ! [ condition. left. clone( ) , condition. right. clone( ) ] ,
1354+ } ;
1355+
1356+ Ok ( FunctionCall {
1357+ span : condition. left . span ( ) ,
1358+ func_name : "eq" . to_string ( ) ,
1359+ params : vec ! [ ] ,
1360+ arguments,
1361+ }
1362+ . into ( ) )
1363+ }
0 commit comments