use arrow_array::RecordBatch;
use lance_core::Result;
use lance_core::datatypes::Schema;
use lance_file::version::ConcreteFileVersion;
use lance_index::scalar::seed::IndexSeedWriter;
use super::GenericWriter;
use crate::Dataset;
use crate::index::scalar::{IndexDetails, fetch_index_details};
use crate::index::{index_is_usable, load_all_indices};
#[derive(Debug, Default)]
pub struct SeedCollector {
writers: Vec<Box<dyn IndexSeedWriter>>,
}
impl SeedCollector {
pub fn disabled() -> Self {
Self::default()
}
pub async fn for_write(
version: ConcreteFileVersion,
dataset: Option<&Dataset>,
write_schema: &Schema,
consult_indices: bool,
) -> Result<Self> {
if version == ConcreteFileVersion::V1 || !consult_indices {
return Ok(Self::disabled());
}
let Some(dataset) = dataset else {
return Ok(Self::disabled());
};
let indices = load_all_indices(dataset).await?;
let mut writers: Vec<Box<dyn IndexSeedWriter>> = Vec::new();
for index in indices.iter().filter(|index| index_is_usable(index)) {
let Some(field_id) = index.keyed_field() else {
continue;
};
let Some(field) = write_schema.fields.iter().find(|f| f.id == field_id) else {
continue;
};
let Ok(index_details) = fetch_index_details(dataset, &field.name, index).await else {
continue;
};
let details = IndexDetails(index_details.clone());
let Ok(plugin) = details.get_plugin() else {
continue;
};
if let Some(writer) = plugin
.create_seed_writer(&field.name, &field.data_type(), &index_details)
.await?
{
writers.push(writer);
}
}
Ok(Self { writers })
}
#[cfg(test)]
pub fn len(&self) -> usize {
self.writers.len()
}
#[cfg(test)]
pub fn is_empty(&self) -> bool {
self.writers.is_empty()
}
pub fn observe(&mut self, batch: &RecordBatch) -> Result<()> {
for writer in self.writers.iter_mut() {
if let Some(column) = batch.column_by_name(writer.column_name()) {
writer.observe_batch(column)?;
}
}
Ok(())
}
pub async fn flush(&mut self, writer: &mut dyn GenericWriter) -> Result<()> {
for seed_writer in self.writers.iter_mut() {
if let Some(bytes) = seed_writer.finish()? {
let buf_index = writer.add_global_buffer(bytes).await?;
let key = seed_writer.schema_metadata_key();
let value = seed_writer.schema_metadata_value(buf_index);
writer.add_schema_metadata(key, value);
}
}
Ok(())
}
}