use super::data_evolution_reader::DataEvolutionReader;
use super::data_file_reader::DataFileReader;
use super::kv_file_reader::{KeyValueFileReader, KeyValueReadConfig};
use super::read_builder::split_scan_predicates;
use super::{ArrowRecordBatchStream, Table};
use crate::arrow::filtering::reader_pruning_predicates;
use crate::spec::{CoreOptions, DataField, MergeEngine, Predicate};
use crate::DataSplit;
#[derive(Debug, Clone)]
pub struct TableRead<'a> {
table: &'a Table,
read_type: Vec<DataField>,
data_predicates: Vec<Predicate>,
}
impl<'a> TableRead<'a> {
pub fn new(
table: &'a Table,
read_type: Vec<DataField>,
data_predicates: Vec<Predicate>,
) -> Self {
Self {
table,
read_type,
data_predicates,
}
}
pub fn read_type(&self) -> &[DataField] {
&self.read_type
}
pub fn data_predicates(&self) -> &[Predicate] {
&self.data_predicates
}
pub fn table(&self) -> &Table {
self.table
}
pub fn with_filter(mut self, filter: Predicate) -> Self {
let (_, data_predicates) = split_scan_predicates(self.table, filter);
self.data_predicates = reader_pruning_predicates(data_predicates);
self
}
pub fn to_arrow(&self, data_splits: &[DataSplit]) -> crate::Result<ArrowRecordBatchStream> {
let has_primary_keys = !self.table.schema.primary_keys().is_empty();
let core_options = CoreOptions::new(self.table.schema.options());
let merge_engine = core_options.merge_engine()?;
if has_primary_keys
&& matches!(
merge_engine,
MergeEngine::Deduplicate | MergeEngine::PartialUpdate
)
{
return self.read_pk(data_splits, &core_options);
}
if core_options.data_evolution_enabled() {
self.read_with_evolution(data_splits, &core_options)
} else {
self.read_raw(data_splits)
}
}
fn read_pk(
&self,
data_splits: &[DataSplit],
core_options: &CoreOptions,
) -> crate::Result<ArrowRecordBatchStream> {
if core_options.merge_engine()? == MergeEngine::PartialUpdate {
return self.read_kv(data_splits, core_options);
}
let mut kv_splits = Vec::new();
let mut raw_splits = Vec::new();
for split in data_splits {
if split.data_files().iter().any(|f| f.level == 0) {
kv_splits.push(split.clone());
} else {
raw_splits.push(split.clone());
}
}
if raw_splits.is_empty() {
return self.read_kv(&kv_splits, core_options);
}
if kv_splits.is_empty() {
return self.read_raw(&raw_splits);
}
let kv_stream = self.read_kv(&kv_splits, core_options)?;
let raw_stream = self.read_raw(&raw_splits)?;
Ok(Box::pin(futures::stream::select_all([
kv_stream, raw_stream,
])))
}
fn read_kv(
&self,
splits: &[DataSplit],
core_options: &CoreOptions,
) -> crate::Result<ArrowRecordBatchStream> {
let reader = KeyValueFileReader::new(
self.table.file_io.clone(),
KeyValueReadConfig {
table_name: self.table.identifier().full_name(),
table_options: self.table.schema().options().clone(),
schema_manager: self.table.schema_manager().clone(),
table_schema_id: self.table.schema().id(),
table_fields: self.table.schema.fields().to_vec(),
read_type: self.read_type().to_vec(),
predicates: self.data_predicates.clone(),
primary_keys: self.table.schema.trimmed_primary_keys(),
merge_engine: core_options.merge_engine()?,
sequence_fields: core_options
.sequence_fields()
.iter()
.map(|s| s.to_string())
.collect(),
},
);
reader.read(splits)
}
fn read_with_evolution(
&self,
data_splits: &[DataSplit],
core_options: &CoreOptions,
) -> crate::Result<ArrowRecordBatchStream> {
let reader = DataEvolutionReader::new(
self.table.file_io.clone(),
self.table.schema_manager().clone(),
self.table.schema().id(),
self.table.schema.fields().to_vec(),
self.read_type().to_vec(),
core_options.blob_as_descriptor(),
core_options.blob_descriptor_fields(),
)?;
reader.read(data_splits)
}
fn read_raw(&self, data_splits: &[DataSplit]) -> crate::Result<ArrowRecordBatchStream> {
self.new_data_file_reader().read(data_splits)
}
fn new_data_file_reader(&self) -> DataFileReader {
DataFileReader::new(
self.table.file_io.clone(),
self.table.schema_manager().clone(),
self.table.schema().id(),
self.table.schema.fields().to_vec(),
self.read_type().to_vec(),
self.data_predicates.clone(),
)
}
}