uqa-execution 0.4.5

Volcano physical operators with row-batch pipelines
//
// Unified Query Algebra
//
// Copyright (c) 2023-2026 Cognica, Inc.
//

//! Select newly allocated physical indexes and preserve their catalog/build ordering.

use super::{
    index_definition, BTreeMap, BTreeSet, CatalogIndexRow, IndexRegistryContext, RelationIdentity,
    StorageBackendError, StorageBackendResult,
};

pub(in crate::schema::indexes) fn new_physical_indexes(
    previous: &BTreeMap<RelationIdentity, CatalogIndexRow>,
    rows: &BTreeMap<RelationIdentity, CatalogIndexRow>,
) -> StorageBackendResult<Vec<CatalogIndexRow>> {
    let identities = previous
        .values()
        .map(|row| {
            Ok(index_definition(row)?
                .catalog
                .map(|identity| identity.identity.object_id))
        })
        .collect::<StorageBackendResult<BTreeSet<_>>>()?;
    let mut builds = Vec::new();
    for row in rows.values() {
        let definition = index_definition(row)?;
        if (definition.relationships.parent_index.is_some()
            || row.index_type.eq_ignore_ascii_case("diskann"))
            && !identities.contains(
                &definition
                    .catalog
                    .map(|identity| identity.identity.object_id),
            )
        {
            builds.push(row.clone());
        }
    }
    Ok(builds)
}

pub(super) fn build(
    context: &IndexRegistryContext<'_>,
    row: &CatalogIndexRow,
) -> StorageBackendResult<()> {
    if row.index_type.eq_ignore_ascii_case("diskann") {
        return super::super::diskann::build(context.vectors, context.builds, row);
    }
    let statement = uqa_sql::catalog::index::stored::declaration(row)?;
    super::super::creation::build_physical_index(
        context.vectors,
        context.builds,
        &statement,
        &row.index_type,
    )
    .map_err(|error| StorageBackendError::backend("partition index build", error))
}