icydb-core 0.69.0

IcyDB — A type-safe, embedded ORM and schema system for the Internet Computer
Documentation
//! Module: query::explain::nodes
//! Responsibility: execution-node family ownership and node-level observability helpers.
//! Does not own: text/JSON rendering orchestration or logical-plan projection.
//! Boundary: shared helper surface consumed by explain renderers and execution DTOs.

mod aggregate;
mod pipeline;
mod scan;
mod terminal;

use crate::{
    db::query::explain::{
        ExplainExecutionMode, ExplainExecutionNodeDescriptor, ExplainExecutionNodeType,
    },
    value::Value,
};

pub(in crate::db::query::explain) const fn layer_label(
    node_type: ExplainExecutionNodeType,
) -> &'static str {
    if scan::owns(node_type) {
        return "scan";
    }
    if pipeline::owns(node_type) {
        return "pipeline";
    }
    if aggregate::owns(node_type) {
        return "aggregate";
    }
    if terminal::owns(node_type) {
        return "terminal";
    }

    "unknown"
}

pub(in crate::db::query::explain) const fn execution_mode_detail_label(
    mode: ExplainExecutionMode,
) -> &'static str {
    match mode {
        ExplainExecutionMode::Streaming => "streaming",
        ExplainExecutionMode::Materialized => "materialized",
    }
}

pub(in crate::db::query::explain) fn predicate_pushdown_mode(
    node: &ExplainExecutionNodeDescriptor,
) -> &'static str {
    match node.predicate_pushdown().as_ref() {
        None => "none",
        Some(pushdown) if *pushdown == "strict_all_or_none" => "full",
        Some(_) => {
            if node.residual_predicate().is_some() {
                "partial"
            } else {
                "full"
            }
        }
    }
}

pub(in crate::db::query::explain) fn fast_path_selected(
    node: &ExplainExecutionNodeDescriptor,
) -> Option<bool> {
    let selected = node.node_properties().get("fast_path_selected")?;
    match selected {
        Value::Text(path) => Some(path.as_str() != "none"),
        _ => None,
    }
}

pub(in crate::db::query::explain) fn fast_path_reason(
    node: &ExplainExecutionNodeDescriptor,
) -> Option<&str> {
    let reason = node.node_properties().get("fast_path_selected_reason")?;
    match reason {
        Value::Text(reason) => Some(reason.as_str()),
        _ => None,
    }
}