rust-ef 1.5.1

Rust Entity Framework - An EFCore-inspired ORM for Rust
Documentation
//! Entity type trait and state definitions.

use crate::error::EFResult;
use crate::metadata::EntityTypeMeta;
use crate::provider::DbValue;
use std::collections::HashMap;

// ---------------------------------------------------------------------------
// Entity materialization ?converts raw rows into entity instances
// ---------------------------------------------------------------------------

/// Materializes entities from raw database row data using the `IFromRow` trait.
pub fn materialize_entities<T: IEntityType + IFromRow>(rows: &[Vec<DbValue>]) -> EFResult<Vec<T>> {
    let mut entities = Vec::with_capacity(rows.len());
    for row in rows {
        let entity = T::from_row(row)?;
        entities.push(entity);
    }
    Ok(entities)
}

/// Represents the state of an entity in the change tracker.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EntityState {
    Detached,
    Added,
    Unchanged,
    Modified,
    Deleted,
}

/// The core trait that every entity type must implement.
pub trait IEntityType: Send + Sync + 'static {
    fn entity_meta() -> EntityTypeMeta
    where
        Self: Sized;

    fn entity_meta_instance(&self) -> EntityTypeMeta
    where
        Self: Sized,
    {
        Self::entity_meta()
    }
}

/// Trait for materializing an entity from a database row.
///
/// Used by [`materialize_entities`] to deserialize query results.
/// Auto-generated by `#[derive(EntityType)]`.
pub trait IFromRow: IEntityType + Sized {
    fn from_row(values: &[DbValue]) -> EFResult<Self>;
}

/// Extracts primary key values from an entity for SaveChanges WHERE clauses.
///
/// Auto-generated by `#[derive(EntityType)]`.
pub trait IGetKeyValues: IEntityType {
    fn key_values(&self) -> HashMap<String, DbValue>;
}

/// Extracts all scalar property values from an entity for INSERT/UPDATE.
///
/// Auto-generated by `#[derive(EntityType)]`.
pub trait IEntitySnapshot: IEntityType {
    fn snapshot(&self) -> HashMap<String, DbValue>;
}

/// Attaches lazy-loading contexts to navigation properties.
///
/// Auto-generated by `#[derive(EntityType)]`. Called by `QueryBuilder::to_list()`
/// when lazy loading is enabled on the `DbContext`. For each navigation field,
/// the macro implementation constructs a `LazyContextImpl` and calls
/// `set_lazy_context` on the corresponding container.
///
/// Entities without navigation properties get a no-op implementation.
pub trait ILazyInit: IEntityType {
    /// Attaches lazy contexts to all navigation properties on this entity.
    ///
    /// `depth` is the current recursion depth (0 for top-level entities
    /// materialized by `to_list`). Each lazy `load()` call increments the
    /// depth when attaching contexts to child entities.
    fn attach_lazy_contexts(
        &mut self,
        provider: std::sync::Arc<dyn crate::provider::IDatabaseProvider>,
        filter_map: Option<
            std::sync::Arc<std::collections::HashMap<String, crate::query::CompiledFilter>>,
        >,
        depth: usize,
    );
}

/// Applies eagerly-loaded navigation data to an entity.
///
/// Auto-generated by `#[derive(EntityType)]` for types with navigation properties.
#[async_trait::async_trait]
pub trait INavigationSetter: IEntityType {
    fn apply_has_many(&mut self, field: &str, rows: &[Vec<DbValue>]) -> EFResult<()> {
        let _ = (field, rows);
        Ok(())
    }

    fn apply_reference(&mut self, field: &str, row: &[DbValue]) -> EFResult<()> {
        let _ = (field, row);
        Ok(())
    }

    /// Loads nested includes after the parent navigation was populated.
    ///
    /// `filter_map` carries per-table query filters (e.g. tenant isolation)
    /// so that nested navigation loading respects the same filters as
    /// top-level loading.
    async fn load_nested_includes(
        &mut self,
        parent_navigation: &str,
        nested: &[crate::query::IncludePath],
        provider: &dyn crate::provider::IDatabaseProvider,
        filter_map: Option<&std::collections::HashMap<String, crate::query::CompiledFilter>>,
    ) -> EFResult<()> {
        let _ = (parent_navigation, nested, provider, filter_map);
        Ok(())
    }
}