"""Guard against CREATE TABLE / INSERT column mismatches — catch them in-memory, at validate_bundle() time, instead of ~10 minutes later as a cryptic Snowflake 'invalid identifier' error deep inside an executemany (see the Gap e2e failure: FACT_CAMPAIGN_PERFORMANCE's row loader referenced a CHECKOUT_INITIATED column CREATE TABLE never declared). """ from __future__ import annotations from demoprep_app.dataset.contracts import DatasetBundle, DatasetColumn, DatasetTable from demoprep_app.dataset.validator import ValidationReport, _check_schema_consistency from demoprep_app.scenario.contract import ScenarioContract def _scenario() -> ScenarioContract: return ScenarioContract( company_name="Acme", company_url="https://example.com", use_case="Marketing Funnel", scenario_type="campaign_performance", fact_grain="campaign-day", ) def test_schema_consistency_passes_for_a_clean_bundle(): bundle = DatasetBundle( scenario=_scenario(), tables=[ DatasetTable( name="FACT_CAMPAIGN_PERFORMANCE", grain="campaign-day", columns=[ DatasetColumn("FACT_CAMPAIGN_PERFORMANCE_KEY", "fact_key", "NUMBER", nullable=False), DatasetColumn("IMPRESSIONS", "impressions", "NUMBER", nullable=False), DatasetColumn("CLICKS", "clicks", "NUMBER", nullable=False), ], rows=[{"FACT_CAMPAIGN_PERFORMANCE_KEY": 1, "IMPRESSIONS": 100, "CLICKS": 5}], is_fact=True, ) ], ) report = ValidationReport() _check_schema_consistency(bundle, report) assert report.integrity_errors == [] def test_schema_consistency_catches_a_row_key_with_no_declared_column(): # Mirrors the Gap failure: the row loader would INSERT a column # (CHECKOUT_INITIATED) that CREATE TABLE never declared for this table. bundle = DatasetBundle( scenario=_scenario(), tables=[ DatasetTable( name="FACT_CAMPAIGN_PERFORMANCE", grain="campaign-day", columns=[ DatasetColumn("FACT_CAMPAIGN_PERFORMANCE_KEY", "fact_key", "NUMBER", nullable=False), DatasetColumn("ADD_TO_CART", "add_to_cart", "NUMBER", nullable=False), DatasetColumn("CONVERSIONS", "conversions", "NUMBER", nullable=False), ], rows=[ { "FACT_CAMPAIGN_PERFORMANCE_KEY": 1, "ADD_TO_CART": 10, "CONVERSIONS": 2, "CHECKOUT_INITIATED": 6, # not a declared column } ], is_fact=True, ) ], ) report = ValidationReport() _check_schema_consistency(bundle, report) assert len(report.integrity_errors) == 1 assert "FACT_CAMPAIGN_PERFORMANCE" in report.integrity_errors[0] assert "CHECKOUT_INITIATED" in report.integrity_errors[0] def test_schema_consistency_catches_column_names_that_collide_after_normalization(): # Two distinct Python-level names that normalize to the same SQL identifier # would make CREATE TABLE emit a duplicate column. bundle = DatasetBundle( scenario=_scenario(), tables=[ DatasetTable( name="FACT_CAMPAIGN_PERFORMANCE", grain="campaign-day", columns=[ DatasetColumn("Checkout Initiated", "checkout_initiated", "NUMBER", nullable=False), DatasetColumn("Checkout-Initiated", "checkout_initiated_2", "NUMBER", nullable=False), ], rows=[{"Checkout Initiated": 1, "Checkout-Initiated": 2}], is_fact=True, ) ], ) report = ValidationReport() _check_schema_consistency(bundle, report) assert len(report.integrity_errors) == 1 assert "CHECKOUT_INITIATED" in report.integrity_errors[0] assert "duplicate column" in report.integrity_errors[0] def test_schema_consistency_ignores_empty_tables(): bundle = DatasetBundle( scenario=_scenario(), tables=[ DatasetTable( name="EMPTY_DIM", grain="empty", columns=[DatasetColumn("EMPTY_DIM_KEY", "dimension_key", "NUMBER", nullable=False)], rows=[], ) ], ) report = ValidationReport() _check_schema_consistency(bundle, report) assert report.integrity_errors == []