1use arrow_array::{RecordBatch, RecordBatchIterator, RecordBatchReader};
4use arrow_schema::SchemaRef;
5
6use crate::Error;
7pub use crate::scandal::api::{SortColumn, WriteLayout, WriteProperties};
8
9pub trait IntoArrowStream {
14 fn into_arrow_stream(self) -> Result<Box<dyn RecordBatchReader + Send>, Error>;
16
17 fn into_write_input(self) -> Result<WriteInput, Error>
19 where
20 Self: Sized,
21 {
22 let reader = self.into_arrow_stream()?;
23 WriteInput::new(
24 reader.schema(),
25 vec![reader],
26 WriteProperties {
27 ordering: Vec::new(),
28 },
29 )
30 }
31}
32
33pub struct WriteInput {
38 pub(crate) schema: SchemaRef,
39 pub(crate) partitions: Vec<Box<dyn RecordBatchReader + Send>>,
40 pub(crate) properties: WriteProperties,
41}
42
43impl WriteInput {
44 pub fn new(
46 schema: SchemaRef,
47 partitions: Vec<Box<dyn RecordBatchReader + Send>>,
48 properties: WriteProperties,
49 ) -> Result<Self, Error> {
50 if partitions
51 .iter()
52 .any(|partition| partition.schema() != schema)
53 {
54 return Err(Error::invalid(
55 "write partitions must have the declared schema",
56 ));
57 }
58 Ok(Self {
59 schema,
60 partitions,
61 properties,
62 })
63 }
64 pub fn schema(&self) -> SchemaRef {
66 self.schema.clone()
67 }
68}
69
70impl IntoArrowStream for WriteInput {
71 fn into_arrow_stream(self) -> Result<Box<dyn RecordBatchReader + Send>, Error> {
72 Ok(Box::new(RecordBatchIterator::new(
73 self.partitions.into_iter().flatten(),
74 self.schema,
75 )))
76 }
77 fn into_write_input(self) -> Result<WriteInput, Error> {
78 Ok(self)
79 }
80}
81impl IntoArrowStream for RecordBatch {
82 fn into_arrow_stream(self) -> Result<Box<dyn RecordBatchReader + Send>, Error> {
83 let schema = self.schema();
84 Ok(Box::new(RecordBatchIterator::new([Ok(self)], schema)))
85 }
86}
87impl IntoArrowStream for Vec<RecordBatch> {
88 fn into_arrow_stream(self) -> Result<Box<dyn RecordBatchReader + Send>, Error> {
89 let schema = self
90 .first()
91 .ok_or_else(|| Error::invalid("an empty input needs an explicit schema"))?
92 .schema();
93 (schema, self).into_arrow_stream()
94 }
95}
96impl IntoArrowStream for (SchemaRef, Vec<RecordBatch>) {
97 fn into_arrow_stream(self) -> Result<Box<dyn RecordBatchReader + Send>, Error> {
98 Ok(Box::new(RecordBatchIterator::new(
99 self.1.into_iter().map(Ok),
100 self.0,
101 )))
102 }
103}
104impl IntoArrowStream for Box<dyn RecordBatchReader + Send> {
105 fn into_arrow_stream(self) -> Result<Box<dyn RecordBatchReader + Send>, Error> {
106 Ok(self)
107 }
108}
109impl<R: RecordBatchReader + Send + 'static> IntoArrowStream for Box<R> {
110 fn into_arrow_stream(self) -> Result<Box<dyn RecordBatchReader + Send>, Error> {
111 Ok(self)
112 }
113}