Skip to content

Trap detection: a CTE that shadows a declared table name still over-reports the fan #200

Description

@sandeep-agami

Found during ACE-083 review (#199), measured identical on main @ 439ecd1, so this predates that change and is not a regression.

WITH order_items AS (SELECT order_id, SUM(quantity) q FROM order_items GROUP BY order_id)
SELECT SUM(orders.total_amount) FROM orders JOIN order_items ON order_items.order_id = orders.id

Reports multiplied naming orders (1) <- order_items (N). The truth is not_multiplied: the CTE is grouped to order_id, so it joins 1:1 and nothing fans.

Cause. ACE-083's _resolve_cte_scope derives a one_to_one edge for the grain-changing CTE and appends it to a copy of the relationship list, but the model's own order_items -> orders many_to_one edge is still in that list and wins. The two edges are about different entities that happen to share a name.

Direction is safe (an over-report, never a false clean), which is why ACE-083 left it. But it is one name collision away from the defect class ACE-083's S3 exists to close, and shadowing a table name in a CTE is ordinary SQL.

Why it was not fixed there. Deciding which edge outranks the other is a cardinality-resolution question, not a scope-resolution one, and ACE-083 was already five slices and two review rounds deep.

Repro is _sales_org in tests/test_semantic_model_runtime.py plus the statement above through pre_flight_check.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions