use crate::format::key_existence::KeyExistenceFilter;
use crate::format::overlay::DataOverlayFile;
use crate::format::{BasePath, DataFile, Fragment, IndexFile, IndexMetadata};
use crate::system_index::mem_wal::CompactedSsTable;
use crate::transaction::UpdateMap;
use lance_core::datatypes::Schema;
use lance_core::deepsize::DeepSizeOf;
use roaring::RoaringBitmap;
use std::collections::HashMap;
use uuid::Uuid;
#[derive(Debug, Clone, DeepSizeOf, PartialEq)]
pub struct DataReplacementGroup(pub u64, pub DataFile);
#[derive(Debug, Clone, DeepSizeOf, PartialEq)]
pub struct DataOverlayGroup {
pub fragment_id: u64,
pub overlays: Vec<DataOverlayFile>,
}
#[derive(Debug, Clone, DeepSizeOf)]
pub enum Operation {
Append { fragments: Vec<Fragment> },
Delete {
updated_fragments: Vec<Fragment>,
deleted_fragment_ids: Vec<u64>,
predicate: String,
},
Overwrite {
fragments: Vec<Fragment>,
schema: Schema,
config_upsert_values: Option<HashMap<String, String>>,
initial_bases: Option<Vec<BasePath>>,
},
CreateIndex {
new_indices: Vec<IndexMetadata>,
removed_indices: Vec<IndexMetadata>,
},
Rewrite {
groups: Vec<RewriteGroup>,
rewritten_indices: Vec<RewrittenIndex>,
frag_reuse_index: Option<IndexMetadata>,
},
DataReplacement {
replacements: Vec<DataReplacementGroup>,
},
DataOverlay { groups: Vec<DataOverlayGroup> },
Merge {
fragments: Vec<Fragment>,
schema: Schema,
preserves_nullability: bool,
},
Restore { version: u64 },
ReserveFragments { num_fragments: u32 },
Update {
removed_fragment_ids: Vec<u64>,
updated_fragments: Vec<Fragment>,
new_fragments: Vec<Fragment>,
fields_modified: Vec<u32>,
compacted_sstables: Vec<CompactedSsTable>,
fields_for_preserving_frag_bitmap: Vec<u32>,
update_mode: Option<UpdateMode>,
inserted_rows_filter: Option<KeyExistenceFilter>,
updated_fragment_offsets: Option<UpdatedFragmentOffsets>,
},
Project {
schema: Schema,
preserves_nullability: bool,
},
UpdateConfig {
config_updates: Option<UpdateMap>,
table_metadata_updates: Option<UpdateMap>,
schema_metadata_updates: Option<UpdateMap>,
field_metadata_updates: HashMap<i32, UpdateMap>,
},
UpdateMemWalState {
compacted_sstables: Vec<CompactedSsTable>,
},
Clone {
is_shallow: bool,
ref_name: Option<String>,
ref_version: u64,
ref_path: String,
branch_name: Option<String>,
},
UpdateBases {
new_bases: Vec<BasePath>,
},
}
#[derive(Debug, Clone, PartialEq, DeepSizeOf)]
pub enum UpdateMode {
RewriteRows,
RewriteColumns,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct UpdatedFragmentOffsets(pub HashMap<u64, RoaringBitmap>);
impl DeepSizeOf for UpdatedFragmentOffsets {
fn deep_size_of_children(&self, context: &mut lance_core::deepsize::Context) -> usize {
self.0.iter().fold(0_usize, |acc, (frag_id, bitmap)| {
acc + frag_id.deep_size_of_children(context)
+ (bitmap.len() as usize).saturating_mul(std::mem::size_of::<u32>())
})
}
}
impl std::fmt::Display for Operation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Append { .. } => write!(f, "Append"),
Self::Delete { .. } => write!(f, "Delete"),
Self::Overwrite { .. } => write!(f, "Overwrite"),
Self::CreateIndex { .. } => write!(f, "CreateIndex"),
Self::Rewrite { .. } => write!(f, "Rewrite"),
Self::Merge { .. } => write!(f, "Merge"),
Self::Restore { .. } => write!(f, "Restore"),
Self::ReserveFragments { .. } => write!(f, "ReserveFragments"),
Self::Update { .. } => write!(f, "Update"),
Self::Project { .. } => write!(f, "Project"),
Self::UpdateConfig { .. } => write!(f, "UpdateConfig"),
Self::DataReplacement { .. } => write!(f, "DataReplacement"),
Self::DataOverlay { .. } => write!(f, "DataOverlay"),
Self::Clone { .. } => write!(f, "Clone"),
Self::UpdateMemWalState { .. } => write!(f, "UpdateMemWalState"),
Self::UpdateBases { .. } => write!(f, "UpdateBases"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct RewrittenIndex {
pub old_id: Uuid,
pub new_id: Uuid,
pub new_index_details: prost_types::Any,
pub new_index_version: u32,
pub new_index_files: Option<Vec<IndexFile>>,
}
impl DeepSizeOf for RewrittenIndex {
fn deep_size_of_children(&self, context: &mut lance_core::deepsize::Context) -> usize {
self.new_index_details
.type_url
.deep_size_of_children(context)
+ self.new_index_details.value.deep_size_of_children(context)
}
}
#[derive(Debug, Clone, DeepSizeOf)]
pub struct RewriteGroup {
pub old_fragments: Vec<Fragment>,
pub new_fragments: Vec<Fragment>,
}
impl PartialEq for RewriteGroup {
fn eq(&self, other: &Self) -> bool {
fn compare_vec<T: PartialEq>(a: &[T], b: &[T]) -> bool {
a.len() == b.len() && a.iter().all(|f| b.contains(f))
}
compare_vec(&self.old_fragments, &other.old_fragments)
&& compare_vec(&self.new_fragments, &other.new_fragments)
}
}
impl Operation {
pub fn name(&self) -> &str {
match self {
Self::Append { .. } => "Append",
Self::Delete { .. } => "Delete",
Self::Overwrite { .. } => "Overwrite",
Self::CreateIndex { .. } => "CreateIndex",
Self::Rewrite { .. } => "Rewrite",
Self::Merge { .. } => "Merge",
Self::ReserveFragments { .. } => "ReserveFragments",
Self::Restore { .. } => "Restore",
Self::Update { .. } => "Update",
Self::Project { .. } => "Project",
Self::UpdateConfig { .. } => "UpdateConfig",
Self::DataReplacement { .. } => "DataReplacement",
Self::DataOverlay { .. } => "DataOverlay",
Self::UpdateMemWalState { .. } => "UpdateMemWalState",
Self::Clone { .. } => "Clone",
Self::UpdateBases { .. } => "UpdateBases",
}
}
}