1use crate::{ChildrenPropertiesMode, ReplaceChildrenOptions};
21use crate::{
22 DisplayAs, DisplayFormatType, ExecutionPlan, Partitioning, PlanProperties,
23 RecordBatchStream, SendableRecordBatchStream, Statistics, common,
24 execution_plan::Boundedness, statistics::StatisticsArgs,
25};
26use crate::{
27 execution_plan::EmissionType,
28 stream::{RecordBatchReceiverStream, RecordBatchStreamAdapter},
29};
30use std::sync::atomic::{AtomicUsize, Ordering};
31use std::{
32 pin::Pin,
33 sync::{Arc, Weak},
34 task::{Context, Poll},
35};
36
37use arrow::datatypes::{DataType, Field, Schema, SchemaRef};
38use arrow::record_batch::RecordBatch;
39use datafusion_common::tree_node::TreeNodeRecursion;
40use datafusion_common::{DataFusionError, Result, internal_err};
41use datafusion_execution::TaskContext;
42use datafusion_physical_expr::{EquivalenceProperties, PhysicalExpr};
43
44use futures::Stream;
45use tokio::sync::Barrier;
46
47#[derive(Debug, Default, Clone)]
49pub struct BatchIndex {
50 inner: Arc<std::sync::Mutex<usize>>,
51}
52
53impl BatchIndex {
54 pub fn value(&self) -> usize {
56 let inner = self.inner.lock().unwrap();
57 *inner
58 }
59
60 pub fn incr(&self) {
62 let mut inner = self.inner.lock().unwrap();
63 *inner += 1;
64 }
65}
66
67#[derive(Debug, Default)]
69pub struct TestStream {
70 data: Vec<RecordBatch>,
72 index: BatchIndex,
74}
75
76impl TestStream {
77 pub fn new(data: Vec<RecordBatch>) -> Self {
80 Self {
81 data,
82 ..Default::default()
83 }
84 }
85
86 pub fn index(&self) -> BatchIndex {
88 self.index.clone()
89 }
90}
91
92impl Stream for TestStream {
93 type Item = Result<RecordBatch>;
94
95 fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>> {
96 let next_batch = self.index.value();
97
98 Poll::Ready(if next_batch < self.data.len() {
99 let next_batch = self.index.value();
100 self.index.incr();
101 Some(Ok(self.data[next_batch].clone()))
102 } else {
103 None
104 })
105 }
106
107 fn size_hint(&self) -> (usize, Option<usize>) {
108 (self.data.len(), Some(self.data.len()))
109 }
110}
111
112impl RecordBatchStream for TestStream {
113 fn schema(&self) -> SchemaRef {
115 self.data[0].schema()
116 }
117}
118
119#[derive(Debug)]
122pub struct MockExec {
123 data: Vec<Result<RecordBatch>>,
125 schema: SchemaRef,
126 use_task: bool,
129 unknown_statistics: bool,
132 cache: Arc<PlanProperties>,
133}
134
135impl MockExec {
136 pub fn new(data: Vec<Result<RecordBatch>>, schema: SchemaRef) -> Self {
144 let cache = Self::compute_properties(Arc::clone(&schema));
145 Self {
146 data,
147 schema,
148 use_task: true,
149 unknown_statistics: false,
150 cache: Arc::new(cache),
151 }
152 }
153
154 pub fn with_use_task(mut self, use_task: bool) -> Self {
158 self.use_task = use_task;
159 self
160 }
161
162 pub fn with_unknown_statistics(mut self) -> Self {
169 self.unknown_statistics = true;
170 self
171 }
172
173 fn compute_properties(schema: SchemaRef) -> PlanProperties {
175 PlanProperties::new(
176 EquivalenceProperties::new(schema),
177 Partitioning::UnknownPartitioning(1),
178 EmissionType::Incremental,
179 Boundedness::Bounded,
180 )
181 }
182}
183
184impl DisplayAs for MockExec {
185 fn fmt_as(
186 &self,
187 t: DisplayFormatType,
188 f: &mut std::fmt::Formatter,
189 ) -> std::fmt::Result {
190 match t {
191 DisplayFormatType::Default | DisplayFormatType::Verbose => {
192 write!(f, "MockExec")
193 }
194 DisplayFormatType::TreeRender => {
195 write!(f, "")
197 }
198 }
199 }
200}
201
202impl ExecutionPlan for MockExec {
203 fn name(&self) -> &'static str {
204 Self::static_name()
205 }
206
207 fn properties(&self) -> &Arc<PlanProperties> {
208 &self.cache
209 }
210
211 fn children(&self) -> Vec<&Arc<dyn ExecutionPlan>> {
212 vec![]
213 }
214
215 fn apply_expressions(
216 &self,
217 _f: &mut dyn FnMut(&Arc<dyn PhysicalExpr>) -> Result<TreeNodeRecursion>,
218 ) -> Result<TreeNodeRecursion> {
219 Ok(TreeNodeRecursion::Continue)
220 }
221
222 fn replace_children(
223 self: Arc<Self>,
224 _: Vec<Arc<dyn ExecutionPlan>>,
225 _: ReplaceChildrenOptions,
226 ) -> Result<Arc<dyn ExecutionPlan>> {
227 unimplemented!()
228 }
229
230 fn with_new_children(
231 self: Arc<Self>,
232 children: Vec<Arc<dyn ExecutionPlan>>,
233 ) -> Result<Arc<dyn ExecutionPlan>> {
234 self.replace_children(
235 children,
236 ReplaceChildrenOptions::new(ChildrenPropertiesMode::Recompute),
237 )
238 }
239
240 fn execute(
242 &self,
243 partition: usize,
244 _context: Arc<TaskContext>,
245 ) -> Result<SendableRecordBatchStream> {
246 assert_eq!(partition, 0);
247
248 let data: Vec<_> = self
250 .data
251 .iter()
252 .map(|r| match r {
253 Ok(batch) => Ok(batch.clone()),
254 Err(e) => Err(clone_error(e)),
255 })
256 .collect();
257
258 if self.use_task {
259 let mut builder = RecordBatchReceiverStream::builder(self.schema(), 2);
260 let tx = builder.tx();
264 builder.spawn(async move {
265 for batch in data {
266 println!("Sending batch via delayed stream");
267 if let Err(e) = tx.send(batch).await {
268 println!("ERROR batch via delayed stream: {e}");
269 }
270 }
271
272 Ok(())
273 });
274 Ok(builder.build())
276 } else {
277 let stream = futures::stream::iter(data);
279 Ok(Box::pin(RecordBatchStreamAdapter::new(
280 self.schema(),
281 stream,
282 )))
283 }
284 }
285
286 fn statistics_from_inputs(
289 &self,
290 _input_stats: &[Arc<Statistics>],
291 args: &StatisticsArgs,
292 ) -> Result<Arc<Statistics>> {
293 if self.unknown_statistics || args.partition().is_some() {
294 return Ok(Arc::new(Statistics::new_unknown(&self.schema)));
295 }
296 let data: Result<Vec<_>> = self
297 .data
298 .iter()
299 .map(|r| match r {
300 Ok(batch) => Ok(batch.clone()),
301 Err(e) => Err(clone_error(e)),
302 })
303 .collect();
304
305 let data = data?;
306
307 Ok(Arc::new(common::compute_record_batch_statistics(
308 &[data],
309 &self.schema,
310 None,
311 )))
312 }
313}
314
315fn clone_error(e: &DataFusionError) -> DataFusionError {
316 use DataFusionError::*;
317 match e {
318 Execution(msg) => Execution(msg.to_string()),
319 _ => unimplemented!(),
320 }
321}
322
323#[derive(Debug)]
326pub struct BarrierExec {
327 data: Vec<Vec<RecordBatch>>,
329 schema: SchemaRef,
330
331 start_data_barrier: Option<Arc<Barrier>>,
333
334 finish_barrier: Option<Arc<(Barrier, AtomicUsize)>>,
336
337 cache: Arc<PlanProperties>,
338
339 log: bool,
340}
341
342impl BarrierExec {
343 pub fn new(data: Vec<Vec<RecordBatch>>, schema: SchemaRef) -> Self {
345 let barrier = Some(Arc::new(Barrier::new(data.len() + 1)));
347 let cache = Self::compute_properties(Arc::clone(&schema), &data);
348 Self {
349 data,
350 schema,
351 start_data_barrier: barrier,
352 cache: Arc::new(cache),
353 finish_barrier: None,
354 log: true,
355 }
356 }
357
358 pub fn with_log(mut self, log: bool) -> Self {
359 self.log = log;
360 self
361 }
362
363 pub fn without_start_barrier(mut self) -> Self {
364 self.start_data_barrier = None;
365 self
366 }
367
368 pub fn with_finish_barrier(mut self) -> Self {
369 let barrier = Arc::new((
370 Barrier::new(self.data.len() + 1),
372 AtomicUsize::new(0),
373 ));
374
375 self.finish_barrier = Some(barrier);
376 self
377 }
378
379 pub async fn wait(&self) {
381 let barrier = &self
382 .start_data_barrier
383 .as_ref()
384 .expect("Must only be called when having a start barrier");
385 if self.log {
386 println!("BarrierExec::wait waiting on barrier");
387 }
388 barrier.wait().await;
389 if self.log {
390 println!("BarrierExec::wait done waiting");
391 }
392 }
393
394 pub async fn wait_finish(&self) {
395 let (barrier, _) = &self
396 .finish_barrier
397 .as_deref()
398 .expect("Must only be called when having a finish barrier");
399
400 if self.log {
401 println!("BarrierExec::wait_finish waiting on barrier");
402 }
403 barrier.wait().await;
404 if self.log {
405 println!("BarrierExec::wait_finish done waiting");
406 }
407 }
408
409 pub fn is_finish_barrier_reached(&self) -> bool {
411 let (_, reached_finish) = self
412 .finish_barrier
413 .as_deref()
414 .expect("Must only be called when having finish barrier");
415
416 reached_finish.load(Ordering::Relaxed) == self.data.len()
417 }
418
419 fn compute_properties(
421 schema: SchemaRef,
422 data: &[Vec<RecordBatch>],
423 ) -> PlanProperties {
424 PlanProperties::new(
425 EquivalenceProperties::new(schema),
426 Partitioning::UnknownPartitioning(data.len()),
427 EmissionType::Incremental,
428 Boundedness::Bounded,
429 )
430 }
431}
432
433impl DisplayAs for BarrierExec {
434 fn fmt_as(
435 &self,
436 t: DisplayFormatType,
437 f: &mut std::fmt::Formatter,
438 ) -> std::fmt::Result {
439 match t {
440 DisplayFormatType::Default | DisplayFormatType::Verbose => {
441 write!(f, "BarrierExec")
442 }
443 DisplayFormatType::TreeRender => {
444 write!(f, "")
446 }
447 }
448 }
449}
450
451impl ExecutionPlan for BarrierExec {
452 fn name(&self) -> &'static str {
453 Self::static_name()
454 }
455
456 fn properties(&self) -> &Arc<PlanProperties> {
457 &self.cache
458 }
459
460 fn children(&self) -> Vec<&Arc<dyn ExecutionPlan>> {
461 unimplemented!()
462 }
463
464 fn replace_children(
465 self: Arc<Self>,
466 _: Vec<Arc<dyn ExecutionPlan>>,
467 _: ReplaceChildrenOptions,
468 ) -> Result<Arc<dyn ExecutionPlan>> {
469 unimplemented!()
470 }
471
472 fn apply_expressions(
473 &self,
474 _f: &mut dyn FnMut(&Arc<dyn PhysicalExpr>) -> Result<TreeNodeRecursion>,
475 ) -> Result<TreeNodeRecursion> {
476 Ok(TreeNodeRecursion::Continue)
477 }
478
479 fn with_new_children(
480 self: Arc<Self>,
481 children: Vec<Arc<dyn ExecutionPlan>>,
482 ) -> Result<Arc<dyn ExecutionPlan>> {
483 self.replace_children(
484 children,
485 ReplaceChildrenOptions::new(ChildrenPropertiesMode::Recompute),
486 )
487 }
488
489 fn execute(
491 &self,
492 partition: usize,
493 _context: Arc<TaskContext>,
494 ) -> Result<SendableRecordBatchStream> {
495 assert!(partition < self.data.len());
496
497 let mut builder = RecordBatchReceiverStream::builder(self.schema(), 2);
498
499 let data = self.data[partition].clone();
501 let start_barrier = self.start_data_barrier.as_ref().map(Arc::clone);
502 let finish_barrier = self.finish_barrier.as_ref().map(Arc::clone);
503 let log = self.log;
504 let tx = builder.tx();
505 builder.spawn(async move {
506 if let Some(barrier) = start_barrier {
507 if log {
508 println!("Partition {partition} waiting on barrier");
509 }
510 barrier.wait().await;
511 }
512 for batch in data {
513 if log {
514 println!("Partition {partition} sending batch");
515 }
516 if let Err(e) = tx.send(Ok(batch)).await {
517 println!("ERROR batch via barrier stream stream: {e}");
518 }
519 }
520 if let Some((barrier, reached_finish)) = finish_barrier.as_deref() {
521 if log {
522 println!("Partition {partition} waiting on finish barrier");
523 }
524 reached_finish.fetch_add(1, Ordering::Relaxed);
525 barrier.wait().await;
526 }
527
528 Ok(())
529 });
530
531 Ok(builder.build())
533 }
534
535 fn statistics_from_inputs(
536 &self,
537 _input_stats: &[Arc<Statistics>],
538 args: &StatisticsArgs,
539 ) -> Result<Arc<Statistics>> {
540 if args.partition().is_some() {
541 return Ok(Arc::new(Statistics::new_unknown(&self.schema)));
542 }
543 Ok(Arc::new(common::compute_record_batch_statistics(
544 &self.data,
545 &self.schema,
546 None,
547 )))
548 }
549}
550
551#[derive(Debug)]
553pub struct ErrorExec {
554 cache: Arc<PlanProperties>,
555}
556
557impl Default for ErrorExec {
558 fn default() -> Self {
559 Self::new()
560 }
561}
562
563impl ErrorExec {
564 pub fn new() -> Self {
565 let schema = Arc::new(Schema::new(vec![Field::new(
566 "dummy",
567 DataType::Int64,
568 true,
569 )]));
570 let cache = Self::compute_properties(schema);
571 Self {
572 cache: Arc::new(cache),
573 }
574 }
575
576 fn compute_properties(schema: SchemaRef) -> PlanProperties {
578 PlanProperties::new(
579 EquivalenceProperties::new(schema),
580 Partitioning::UnknownPartitioning(1),
581 EmissionType::Incremental,
582 Boundedness::Bounded,
583 )
584 }
585}
586
587impl DisplayAs for ErrorExec {
588 fn fmt_as(
589 &self,
590 t: DisplayFormatType,
591 f: &mut std::fmt::Formatter,
592 ) -> std::fmt::Result {
593 match t {
594 DisplayFormatType::Default | DisplayFormatType::Verbose => {
595 write!(f, "ErrorExec")
596 }
597 DisplayFormatType::TreeRender => {
598 write!(f, "")
600 }
601 }
602 }
603}
604
605impl ExecutionPlan for ErrorExec {
606 fn name(&self) -> &'static str {
607 Self::static_name()
608 }
609
610 fn properties(&self) -> &Arc<PlanProperties> {
611 &self.cache
612 }
613
614 fn children(&self) -> Vec<&Arc<dyn ExecutionPlan>> {
615 unimplemented!()
616 }
617
618 fn replace_children(
619 self: Arc<Self>,
620 _: Vec<Arc<dyn ExecutionPlan>>,
621 _: ReplaceChildrenOptions,
622 ) -> Result<Arc<dyn ExecutionPlan>> {
623 unimplemented!()
624 }
625
626 fn apply_expressions(
627 &self,
628 _f: &mut dyn FnMut(&Arc<dyn PhysicalExpr>) -> Result<TreeNodeRecursion>,
629 ) -> Result<TreeNodeRecursion> {
630 Ok(TreeNodeRecursion::Continue)
631 }
632
633 fn with_new_children(
634 self: Arc<Self>,
635 children: Vec<Arc<dyn ExecutionPlan>>,
636 ) -> Result<Arc<dyn ExecutionPlan>> {
637 self.replace_children(
638 children,
639 ReplaceChildrenOptions::new(ChildrenPropertiesMode::Recompute),
640 )
641 }
642
643 fn execute(
645 &self,
646 partition: usize,
647 _context: Arc<TaskContext>,
648 ) -> Result<SendableRecordBatchStream> {
649 internal_err!("ErrorExec, unsurprisingly, errored in partition {partition}")
650 }
651}
652
653#[derive(Debug, Clone)]
655pub struct StatisticsExec {
656 stats: Statistics,
657 schema: Arc<Schema>,
658 cache: Arc<PlanProperties>,
659}
660impl StatisticsExec {
661 pub fn new(stats: Statistics, schema: Schema) -> Self {
662 assert_eq!(
663 stats.column_statistics.len(),
664 schema.fields().len(),
665 "if defined, the column statistics vector length should be the number of fields"
666 );
667 let cache = Self::compute_properties(Arc::new(schema.clone()));
668 Self {
669 stats,
670 schema: Arc::new(schema),
671 cache: Arc::new(cache),
672 }
673 }
674
675 fn compute_properties(schema: SchemaRef) -> PlanProperties {
677 PlanProperties::new(
678 EquivalenceProperties::new(schema),
679 Partitioning::UnknownPartitioning(2),
680 EmissionType::Incremental,
681 Boundedness::Bounded,
682 )
683 }
684}
685
686impl DisplayAs for StatisticsExec {
687 fn fmt_as(
688 &self,
689 t: DisplayFormatType,
690 f: &mut std::fmt::Formatter,
691 ) -> std::fmt::Result {
692 match t {
693 DisplayFormatType::Default | DisplayFormatType::Verbose => {
694 write!(
695 f,
696 "StatisticsExec: col_count={}, row_count={:?}",
697 self.schema.fields().len(),
698 self.stats.num_rows,
699 )
700 }
701 DisplayFormatType::TreeRender => {
702 write!(f, "")
704 }
705 }
706 }
707}
708
709impl ExecutionPlan for StatisticsExec {
710 fn name(&self) -> &'static str {
711 Self::static_name()
712 }
713
714 fn properties(&self) -> &Arc<PlanProperties> {
715 &self.cache
716 }
717
718 fn children(&self) -> Vec<&Arc<dyn ExecutionPlan>> {
719 vec![]
720 }
721
722 fn apply_expressions(
723 &self,
724 _f: &mut dyn FnMut(&Arc<dyn PhysicalExpr>) -> Result<TreeNodeRecursion>,
725 ) -> Result<TreeNodeRecursion> {
726 Ok(TreeNodeRecursion::Continue)
727 }
728
729 fn replace_children(
730 self: Arc<Self>,
731 _: Vec<Arc<dyn ExecutionPlan>>,
732 _: ReplaceChildrenOptions,
733 ) -> Result<Arc<dyn ExecutionPlan>> {
734 Ok(self)
735 }
736
737 fn with_new_children(
738 self: Arc<Self>,
739 children: Vec<Arc<dyn ExecutionPlan>>,
740 ) -> Result<Arc<dyn ExecutionPlan>> {
741 self.replace_children(
742 children,
743 ReplaceChildrenOptions::new(ChildrenPropertiesMode::Recompute),
744 )
745 }
746
747 fn execute(
748 &self,
749 _partition: usize,
750 _context: Arc<TaskContext>,
751 ) -> Result<SendableRecordBatchStream> {
752 unimplemented!("This plan only serves for testing statistics")
753 }
754
755 fn statistics_from_inputs(
756 &self,
757 _input_stats: &[Arc<Statistics>],
758 args: &StatisticsArgs,
759 ) -> Result<Arc<Statistics>> {
760 Ok(Arc::new(if args.partition().is_some() {
761 Statistics::new_unknown(&self.schema)
762 } else {
763 self.stats.clone()
764 }))
765 }
766}
767
768#[derive(Debug)]
772pub struct BlockingExec {
773 schema: SchemaRef,
775
776 refs: Arc<()>,
778 cache: Arc<PlanProperties>,
779}
780
781impl BlockingExec {
782 pub fn new(schema: SchemaRef, n_partitions: usize) -> Self {
784 let cache = Self::compute_properties(Arc::clone(&schema), n_partitions);
785 Self {
786 schema,
787 refs: Default::default(),
788 cache: Arc::new(cache),
789 }
790 }
791
792 pub fn refs(&self) -> Weak<()> {
798 Arc::downgrade(&self.refs)
799 }
800
801 fn compute_properties(schema: SchemaRef, n_partitions: usize) -> PlanProperties {
803 PlanProperties::new(
804 EquivalenceProperties::new(schema),
805 Partitioning::UnknownPartitioning(n_partitions),
806 EmissionType::Incremental,
807 Boundedness::Bounded,
808 )
809 }
810}
811
812impl DisplayAs for BlockingExec {
813 fn fmt_as(
814 &self,
815 t: DisplayFormatType,
816 f: &mut std::fmt::Formatter,
817 ) -> std::fmt::Result {
818 match t {
819 DisplayFormatType::Default | DisplayFormatType::Verbose => {
820 write!(f, "BlockingExec",)
821 }
822 DisplayFormatType::TreeRender => {
823 write!(f, "")
825 }
826 }
827 }
828}
829
830impl ExecutionPlan for BlockingExec {
831 fn name(&self) -> &'static str {
832 Self::static_name()
833 }
834
835 fn properties(&self) -> &Arc<PlanProperties> {
836 &self.cache
837 }
838
839 fn children(&self) -> Vec<&Arc<dyn ExecutionPlan>> {
840 vec![]
842 }
843
844 fn replace_children(
845 self: Arc<Self>,
846 _: Vec<Arc<dyn ExecutionPlan>>,
847 _: ReplaceChildrenOptions,
848 ) -> Result<Arc<dyn ExecutionPlan>> {
849 internal_err!("Children cannot be replaced in {self:?}")
850 }
851
852 fn apply_expressions(
853 &self,
854 _f: &mut dyn FnMut(&Arc<dyn PhysicalExpr>) -> Result<TreeNodeRecursion>,
855 ) -> Result<TreeNodeRecursion> {
856 Ok(TreeNodeRecursion::Continue)
857 }
858
859 fn with_new_children(
860 self: Arc<Self>,
861 children: Vec<Arc<dyn ExecutionPlan>>,
862 ) -> Result<Arc<dyn ExecutionPlan>> {
863 self.replace_children(
864 children,
865 ReplaceChildrenOptions::new(ChildrenPropertiesMode::Recompute),
866 )
867 }
868
869 fn execute(
870 &self,
871 _partition: usize,
872 _context: Arc<TaskContext>,
873 ) -> Result<SendableRecordBatchStream> {
874 Ok(Box::pin(BlockingStream {
875 schema: Arc::clone(&self.schema),
876 _refs: Arc::clone(&self.refs),
877 }))
878 }
879}
880
881#[derive(Debug)]
883pub struct BlockingStream {
884 schema: SchemaRef,
886
887 _refs: Arc<()>,
889}
890
891impl Stream for BlockingStream {
892 type Item = Result<RecordBatch>;
893
894 fn poll_next(
895 self: Pin<&mut Self>,
896 _cx: &mut Context<'_>,
897 ) -> Poll<Option<Self::Item>> {
898 Poll::Pending
899 }
900}
901
902impl RecordBatchStream for BlockingStream {
903 fn schema(&self) -> SchemaRef {
904 Arc::clone(&self.schema)
905 }
906}
907
908pub async fn assert_strong_count_converges_to_zero<T>(refs: Weak<T>) {
912 tokio::time::timeout(std::time::Duration::from_secs(10), async {
913 loop {
914 if dbg!(Weak::strong_count(&refs)) == 0 {
915 break;
916 }
917 tokio::time::sleep(std::time::Duration::from_millis(10)).await;
918 }
919 })
920 .await
921 .unwrap();
922}
923
924#[derive(Debug)]
928pub struct PanicExec {
929 schema: SchemaRef,
931
932 batches_until_panics: Vec<usize>,
935 cache: Arc<PlanProperties>,
936}
937
938impl PanicExec {
939 pub fn new(schema: SchemaRef, n_partitions: usize) -> Self {
942 let batches_until_panics = vec![0; n_partitions];
943 let cache = Self::compute_properties(Arc::clone(&schema), &batches_until_panics);
944 Self {
945 schema,
946 batches_until_panics,
947 cache: Arc::new(cache),
948 }
949 }
950
951 pub fn with_partition_panic(mut self, partition: usize, count: usize) -> Self {
953 self.batches_until_panics[partition] = count;
954 self
955 }
956
957 fn compute_properties(
959 schema: SchemaRef,
960 batches_until_panics: &[usize],
961 ) -> PlanProperties {
962 let num_partitions = batches_until_panics.len();
963 PlanProperties::new(
964 EquivalenceProperties::new(schema),
965 Partitioning::UnknownPartitioning(num_partitions),
966 EmissionType::Incremental,
967 Boundedness::Bounded,
968 )
969 }
970}
971
972impl DisplayAs for PanicExec {
973 fn fmt_as(
974 &self,
975 t: DisplayFormatType,
976 f: &mut std::fmt::Formatter,
977 ) -> std::fmt::Result {
978 match t {
979 DisplayFormatType::Default | DisplayFormatType::Verbose => {
980 write!(f, "PanicExec",)
981 }
982 DisplayFormatType::TreeRender => {
983 write!(f, "")
985 }
986 }
987 }
988}
989
990impl ExecutionPlan for PanicExec {
991 fn name(&self) -> &'static str {
992 Self::static_name()
993 }
994
995 fn properties(&self) -> &Arc<PlanProperties> {
996 &self.cache
997 }
998
999 fn children(&self) -> Vec<&Arc<dyn ExecutionPlan>> {
1000 vec![]
1002 }
1003
1004 fn apply_expressions(
1005 &self,
1006 _f: &mut dyn FnMut(&Arc<dyn PhysicalExpr>) -> Result<TreeNodeRecursion>,
1007 ) -> Result<TreeNodeRecursion> {
1008 Ok(TreeNodeRecursion::Continue)
1009 }
1010
1011 fn replace_children(
1012 self: Arc<Self>,
1013 _: Vec<Arc<dyn ExecutionPlan>>,
1014 _: ReplaceChildrenOptions,
1015 ) -> Result<Arc<dyn ExecutionPlan>> {
1016 internal_err!("Children cannot be replaced in {:?}", self)
1017 }
1018
1019 fn with_new_children(
1020 self: Arc<Self>,
1021 children: Vec<Arc<dyn ExecutionPlan>>,
1022 ) -> Result<Arc<dyn ExecutionPlan>> {
1023 self.replace_children(
1024 children,
1025 ReplaceChildrenOptions::new(ChildrenPropertiesMode::Recompute),
1026 )
1027 }
1028
1029 fn execute(
1030 &self,
1031 partition: usize,
1032 _context: Arc<TaskContext>,
1033 ) -> Result<SendableRecordBatchStream> {
1034 Ok(Box::pin(PanicStream {
1035 partition,
1036 batches_until_panic: self.batches_until_panics[partition],
1037 schema: Arc::clone(&self.schema),
1038 ready: false,
1039 }))
1040 }
1041}
1042
1043#[derive(Debug)]
1048struct PanicStream {
1049 partition: usize,
1051 batches_until_panic: usize,
1053 schema: SchemaRef,
1055 ready: bool,
1057}
1058
1059impl Stream for PanicStream {
1060 type Item = Result<RecordBatch>;
1061
1062 fn poll_next(
1063 mut self: Pin<&mut Self>,
1064 cx: &mut Context<'_>,
1065 ) -> Poll<Option<Self::Item>> {
1066 if self.batches_until_panic > 0 {
1067 if self.ready {
1068 self.batches_until_panic -= 1;
1069 self.ready = false;
1070 let batch = RecordBatch::new_empty(Arc::clone(&self.schema));
1071 return Poll::Ready(Some(Ok(batch)));
1072 } else {
1073 self.ready = true;
1074 cx.waker().wake_by_ref();
1076 return Poll::Pending;
1077 }
1078 }
1079 panic!("PanickingStream did panic: {}", self.partition)
1080 }
1081}
1082
1083impl RecordBatchStream for PanicStream {
1084 fn schema(&self) -> SchemaRef {
1085 Arc::clone(&self.schema)
1086 }
1087}