indexlake 0.4.0

An experimental table format with extensible index support.
Documentation
use crate::catalog::IndexRecord;
use crate::index::{IndexKind, IndexParams};
use crate::table::TableSchemaRef;
use crate::{ILError, ILResult};
use arrow::datatypes::FieldRef;
use std::collections::HashMap;
use std::sync::Arc;
use uuid::Uuid;

pub type IndexDefinitionRef = Arc<IndexDefinition>;

#[derive(Debug, Clone)]
pub struct IndexDefinition {
    pub index_id: Uuid,
    pub name: String,
    pub kind: String,
    pub table_id: Uuid,
    pub table_name: String,
    pub table_schema: TableSchemaRef,
    pub key_columns: Vec<String>,
    pub params: Arc<dyn IndexParams>,
}

impl IndexDefinition {
    pub fn key_fields(&self) -> ILResult<Vec<FieldRef>> {
        let mut key_fields = Vec::new();
        for name in self.key_columns.iter() {
            let index = self.table_schema.arrow_schema.index_of(name)?;
            let field = self
                .table_schema
                .arrow_schema
                .fields
                .get(index)
                .cloned()
                .ok_or_else(|| {
                    ILError::internal(format!(
                        "Key field {} not found in table schema {}",
                        name, self.table_schema.arrow_schema
                    ))
                })?;
            key_fields.push(field);
        }
        Ok(key_fields)
    }

    pub fn downcast_params<T: 'static>(&self) -> ILResult<&T> {
        self.params.as_any().downcast_ref::<T>().ok_or_else(|| {
            ILError::internal(format!(
                "Index params is not {}",
                std::any::type_name::<T>()
            ))
        })
    }

    pub(crate) fn from_index_record(
        index_record: &IndexRecord,
        table_name: &str,
        table_schema: &TableSchemaRef,
        index_kinds: &HashMap<String, Arc<dyn IndexKind>>,
    ) -> ILResult<Self> {
        let mut key_columns = Vec::new();
        for key_field_id in index_record.key_field_ids.iter() {
            key_columns.push(hex::encode(key_field_id));
        }

        let index_kind = index_kinds.get(&index_record.index_kind).ok_or_else(|| {
            ILError::internal(format!("Index kind {} not found", index_record.index_kind))
        })?;
        let params = index_kind.decode_params(&index_record.params)?;

        Ok(Self {
            index_id: index_record.index_id,
            name: index_record.index_name.clone(),
            kind: index_record.index_kind.clone(),
            table_id: index_record.table_id,
            table_name: table_name.to_string(),
            table_schema: table_schema.clone(),
            key_columns,
            params,
        })
    }
}