Skip to content

Advise Ref on high-join entities: query-time join-ceiling guard + opt-in join analysis #325

Description

@zantvoort

Selecting an entity expands its eager @FK graph into JOINs (a non-null @FK produces an INNER JOIN, a @Nullable @FK a LEFT JOIN; Ref fields are not joined and load lazily). Deep or wide entity graphs can therefore produce large join counts. Ref is exactly the lever to cut a join subtree, but nothing surfaces when a graph is getting expensive or which field would help most — new users often don't discover Ref as that lever until they hit a wall.

Non-goal (deliberate)

No pre-emptive boot/validation warning on a subjective "too many joins" threshold. A large join over indexed keys is frequently intentional and fine; a boot-time warning on an arbitrary number is noise and false positives, against the fail-fast / no-boot-warnings stance. Any advice must be objective at query time or explicitly opt-in.

Proposal — two parts

1. Query-time fail-fast on the dialect join ceiling (framework).
When a select would exceed the database's hard join limit (e.g. SQLite ~64 tables, MySQL 61), fail fast at query build with a message clearer than the raw driver error: name the entity, the join count, the limit, and the highest-win Ref field to apply. This is objective, query-time, and fail-fast — consistent with how ambiguity is already handled. Likely adds a maxJoins()-style capability to SqlDialect, defaulting to unknown/unbounded.

2. Opt-in join analysis (CLI / on-demand).
A storm analyze (or doctor) command over the compile-time metamodel index reports, per entity: the eager-select join count and a ranked list of Ref candidates by how many joins each cut would save. Zero boot noise, run on demand. Ties into the CLI work in #213. A DEBUG-level log when a real query crosses a configurable threshold is a possible third tier, off by default.

The "win" computation

Eager @FK edges form an acyclic graph rooted at the entity (eager cycles are impossible — they must already be broken with a Ref), which Storm expands into join aliases. The win of Ref-ing field f = the number of join nodes made unreachable by cutting edge f (the size of f's dominated subtree). A table reached via multiple paths is joined once per path, so path count is what is actually cut, which makes Ref-ing a shared hub especially valuable. Rank fields by win.

Notes

  • Advisory framing only ("here is the shape of your graph"), never prescriptive.
  • Prototypable locally first: pure static analysis over ModelImpl / the join builder, no database required.

Tasks

  • SqlDialect join-ceiling capability + query-time fail-fast that names the highest-win Ref field
  • Static join-graph analyzer (per-entity eager join count + ranked Ref candidates by win)
  • Expose the analysis via the storm CLI (opt-in), reusing the metamodel index
  • Docs: Ref as the join-cutting lever and when to reach for it

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    corestorm-core and foundation workenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions