use std::sync::Arc;
use datafusion::arrow::datatypes::SchemaRef;
use datafusion::arrow::error::ArrowError;
use datafusion::datasource::listing::PartitionedFile;
use datafusion::datasource::physical_plan::{FileOpenFuture, FileOpener};
use datafusion::error::Result;
use datafusion::physical_plan::projection::ProjectionExprs;
use orc_rust::projection::ProjectionMask;
use orc_rust::ArrowReaderBuilder;
use futures_util::{StreamExt, TryStreamExt};
use object_store::ObjectStore;
use super::object_store_reader::ObjectStoreReader;
pub(crate) struct OrcOpener {
projection: ProjectionExprs,
batch_size: usize,
table_schema: SchemaRef,
object_store: Arc<dyn ObjectStore>,
}
impl OrcOpener {
pub(crate) fn try_new(
object_store: Arc<dyn ObjectStore>,
table_schema: SchemaRef,
batch_size: usize,
projection: ProjectionExprs,
) -> Result<Self> {
Ok(Self {
projection,
batch_size,
table_schema,
object_store,
})
}
}
impl FileOpener for OrcOpener {
fn open(&self, file: PartitionedFile) -> Result<FileOpenFuture> {
let object_meta = &file.object_meta;
let reader = ObjectStoreReader::new(self.object_store.clone(), object_meta.clone());
let batch_size = self.batch_size;
let projected_schema = self.projection.project_schema(&self.table_schema)?;
Ok(Box::pin(async move {
let mut builder = ArrowReaderBuilder::try_new_async(reader)
.await
.map_err(ArrowError::from)?;
let mut projection = Vec::with_capacity(projected_schema.fields().len());
for named_column in builder.file_metadata().root_data_type().children() {
if let Some((_table_idx, _table_field)) =
projected_schema.fields().find(named_column.name())
{
projection.push(named_column.data_type().column_index());
}
}
let projection_mask =
ProjectionMask::roots(builder.file_metadata().root_data_type(), projection);
if let Some(range) = file.range.clone() {
let range = range.start as usize..range.end as usize;
builder = builder.with_file_byte_range(range);
}
let reader = builder
.with_batch_size(batch_size)
.with_projection(projection_mask)
.build_async();
Ok(reader.map_err(Into::into).boxed())
}))
}
}