Skip to content

[Deferred] Revisit: null-propagation semantics for complex-property navigation (#221 decision) #233

Description

@savasp-agent

Type: Task · Status: deferred (tracked for future revisit, not scheduled)

Purpose

@savasp decided (#221, 2026-07-10) to ratify the null-propagation semantics for complex-property navigation — p.Address.City == null matches owners with no Address node as well as owners whose City is literally null; projections/orderings through a missing navigation yield null rather than dropping rows — with the explicit proviso that the decision be revisited later. This issue is that tracker. It is deliberately unscheduled; do not dispatch it as work.

What was decided and why (snapshot for the future reader)

  • Implemented via the W6-1 PR (Complete GraphQueryModel semantics required for planner parity #210 group), which pins the semantics with translation snapshots, the contract tests NavigationEquality_NullMatchesMissingComplexProperty and NavigationProjection_MissingComplexPropertyYieldsNull, and a "null semantics of complex-property navigation" subsection in docs/core-concepts.md.
  • Rationale at decision time: the strict-MATCH alternative silently dropped rows from OR-predicates/projections/orderings (the bug fixed in the PR-213 review); LINQ-to-objects parity is unachievable (p.Address.City on a null Address throws NRE in memory); strictness remains expressible opt-in (p.Address != null && p.Address.City == null).

When to reopen the question

Signals that should trigger the revisit: user confusion reports about == null matching missing navigations; a future explicit-existence operator (e.g. a Has()/Exists() surface in #96's operator track) making stricter defaults ergonomic; dialect divergence (#85/#86) where a provider can't honor null-propagation cheaply; or the in-memory provider (#112) surfacing a semantics mismatch between LINQ-to-objects and the graph translation that this decision papers over.

If/when revisited

Any change is breaking for query results — it needs a migration entry, updated pins (the named tests above are the contract), and a fresh decision comment from @savasp superseding the #221 record.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions