athena_rs 3.26.1

Hyper performant polyglot Database driver
Documentation
//! Expected-vs-observed table comparison helpers for `/debug/schema`.
//!
//! This module preserves a stable comparison entrypoint while policy ownership
//! is split by concern:
//! - `debug_table_comparison_relation`
//! - `debug_table_comparison_columns`
//! - `debug_table_comparison_contracts`
//! - `debug_table_comparison_output_assembly`

use super::debug_observed_tables::LoggingSchemaObservedTable;
use super::debug_table_comparison_columns::compare_column_delta;
use super::debug_table_comparison_contracts::LoggingSchemaTableComparison;
use super::debug_table_comparison_output_assembly::build_logging_schema_table_comparison_output;
use super::debug_table_comparison_relation::relation_type_matches;

/// Compares one observed table against expected relation-type and column rules.
pub(super) fn compare_observed_expected_table(
    observed: &LoggingSchemaObservedTable,
    expected_relation_type: &str,
    expected_columns: &[String],
) -> LoggingSchemaTableComparison {
    let column_delta = compare_column_delta(&observed.columns, expected_columns);
    let relation_matches = relation_type_matches(&observed.relation_type, expected_relation_type);

    build_logging_schema_table_comparison_output(
        relation_matches,
        column_delta.missing_columns,
        column_delta.unexpected_columns,
    )
}

#[cfg(test)]
mod tests {
    use super::*;

    /// Builds an observed-table fixture for comparison tests.
    fn observed_table(relation_type: &str, columns: Vec<&str>) -> LoggingSchemaObservedTable {
        LoggingSchemaObservedTable {
            table_schema: "public".to_string(),
            table_name: "gateway_request_log".to_string(),
            relation_type: relation_type.to_string(),
            columns: columns.into_iter().map(|value| value.to_string()).collect(),
        }
    }

    #[test]
    /// Reports relation-type mismatches and both missing/unexpected columns.
    fn comparison_reports_relation_and_column_deltas() {
        let observed = observed_table("VIEW", vec!["request_id", "extra_col"]);
        let expected_columns = vec!["request_id".to_string(), "status_code".to_string()];

        let comparison =
            compare_observed_expected_table(&observed, "BASE TABLE", &expected_columns);

        assert!(!comparison.relation_type_matches);
        assert_eq!(comparison.missing_columns, vec!["status_code".to_string()]);
        assert_eq!(comparison.unexpected_columns, vec!["extra_col".to_string()]);
    }
}