@@ -35,6 +35,7 @@ use super::{
35
35
use crate :: common:: SharedMemoryReservation ;
36
36
use crate :: execution_plan:: CardinalityEffect ;
37
37
use crate :: metrics:: { self , BaselineMetrics , MetricBuilder } ;
38
+ use crate :: projection:: { all_columns, make_with_child, ProjectionExec } ;
38
39
use crate :: repartition:: distributor_channels:: {
39
40
DistributionReceiver , DistributionSender ,
40
41
} ;
@@ -202,7 +203,7 @@ impl ExecutionPlan for OnDemandRepartitionExec {
202
203
}
203
204
204
205
fn benefits_from_input_partitioning ( & self ) -> Vec < bool > {
205
- vec ! [ matches! ( self . partitioning ( ) , Partitioning :: Hash ( _ , _ ) ) ]
206
+ vec ! [ false ]
206
207
}
207
208
208
209
fn maintains_input_order ( & self ) -> Vec < bool > {
@@ -247,10 +248,10 @@ impl ExecutionPlan for OnDemandRepartitionExec {
247
248
. get_or_init ( || async move {
248
249
let ( txs, rxs) = if preserve_order {
249
250
( 0 ..num_input_partitions)
250
- . map ( |_| async_channel:: bounded ( 2 ) )
251
+ . map ( |_| async_channel:: unbounded ( ) )
251
252
. unzip :: < _ , _ , Vec < _ > , Vec < _ > > ( )
252
253
} else {
253
- let ( tx, rx) = async_channel:: bounded ( 2 ) ;
254
+ let ( tx, rx) = async_channel:: unbounded ( ) ;
254
255
( vec ! [ tx] , vec ! [ rx] )
255
256
} ;
256
257
Mutex :: new ( ( txs, rxs) )
@@ -365,6 +366,30 @@ impl ExecutionPlan for OnDemandRepartitionExec {
365
366
fn cardinality_effect ( & self ) -> CardinalityEffect {
366
367
CardinalityEffect :: Equal
367
368
}
369
+
370
+ fn try_swapping_with_projection (
371
+ & self ,
372
+ projection : & ProjectionExec ,
373
+ ) -> Result < Option < Arc < dyn ExecutionPlan > > > {
374
+ // If the projection does not narrow the schema, we should not try to push it down.
375
+ if projection. expr ( ) . len ( ) >= projection. input ( ) . schema ( ) . fields ( ) . len ( ) {
376
+ return Ok ( None ) ;
377
+ }
378
+
379
+ // If pushdown is not beneficial or applicable, break it.
380
+ if projection. benefits_from_input_partitioning ( ) [ 0 ]
381
+ || !all_columns ( projection. expr ( ) )
382
+ {
383
+ return Ok ( None ) ;
384
+ }
385
+
386
+ let new_projection = make_with_child ( projection, self . input ( ) ) ?;
387
+
388
+ Ok ( Some ( Arc :: new ( OnDemandRepartitionExec :: try_new (
389
+ new_projection,
390
+ self . partitioning ( ) . clone ( ) ,
391
+ ) ?) ) )
392
+ }
368
393
}
369
394
370
395
impl OnDemandRepartitionExec {
@@ -396,7 +421,7 @@ impl OnDemandRepartitionExec {
396
421
async fn process_input (
397
422
input : Arc < dyn ExecutionPlan > ,
398
423
partition : usize ,
399
- buffer_tx : tokio :: sync :: mpsc :: Sender < RecordBatch > ,
424
+ buffer_tx : Sender < RecordBatch > ,
400
425
context : Arc < TaskContext > ,
401
426
fetch_time : metrics:: Time ,
402
427
send_buffer_time : metrics:: Time ,
@@ -452,7 +477,7 @@ impl OnDemandRepartitionExec {
452
477
context : Arc < TaskContext > ,
453
478
) -> Result < ( ) > {
454
479
// execute the child operator in a separate task
455
- let ( buffer_tx, mut buffer_rx) = tokio :: sync :: mpsc :: channel :: < RecordBatch > ( 2 ) ;
480
+ let ( buffer_tx, buffer_rx) = async_channel :: bounded :: < RecordBatch > ( 2 ) ;
456
481
let processing_task = SpawnedTask :: spawn ( Self :: process_input (
457
482
Arc :: clone ( & input) ,
458
483
partition,
@@ -467,8 +492,8 @@ impl OnDemandRepartitionExec {
467
492
while !output_channels. is_empty ( ) {
468
493
// When the input is done, break the loop
469
494
let batch = match buffer_rx. recv ( ) . await {
470
- Some ( result ) => result ,
471
- None => break ,
495
+ Ok ( batch ) => batch ,
496
+ _ => break ,
472
497
} ;
473
498
474
499
// Get the partition number from the output partition
@@ -595,13 +620,13 @@ impl Stream for OnDemandPerPartitionStream {
595
620
mut self : Pin < & mut Self > ,
596
621
cx : & mut Context < ' _ > ,
597
622
) -> Poll < Option < Self :: Item > > {
598
- if !self . is_requested {
599
- match self . sender . try_send ( self . partition ) {
600
- Ok ( _ ) => { }
601
- Err ( _ ) => {
602
- return Poll :: Ready ( None ) ;
603
- }
604
- }
623
+ if !self . is_requested && ! self . sender . is_closed ( ) {
624
+ self . sender . try_send ( self . partition ) . map_err ( |_| {
625
+ internal_datafusion_err ! (
626
+ "Error sending partition number to the receiver for partition {}" ,
627
+ self . partition
628
+ )
629
+ } ) ? ;
605
630
self . is_requested = true ;
606
631
}
607
632
@@ -667,13 +692,13 @@ impl Stream for OnDemandRepartitionStream {
667
692
) -> Poll < Option < Self :: Item > > {
668
693
loop {
669
694
// Send partition number to input partitions
670
- if !self . is_requested {
671
- match self . sender . try_send ( self . partition ) {
672
- Ok ( _ ) => { }
673
- Err ( _ ) => {
674
- return Poll :: Ready ( None ) ;
675
- }
676
- }
695
+ if !self . is_requested && ! self . sender . is_closed ( ) {
696
+ self . sender . try_send ( self . partition ) . map_err ( |_| {
697
+ internal_datafusion_err ! (
698
+ "Error sending partition number to the receiver for partition {}" ,
699
+ self . partition
700
+ )
701
+ } ) ? ;
677
702
self . is_requested = true ;
678
703
}
679
704
0 commit comments