Skip to content

Browse: elements-less array column named like a table is mis-rendered as a relationship #1487

Description

@dawsontoth

Summary

In the database browse view, a plain array column can be mis-rendered as a to-many relationship (a Table → reverse-link chip) when it has no element type in describe_table and happens to be named like a sibling table. Flagged by @DavidCockerill in review of #1438 as low-priority / non-blocking.

Where

src/features/instance/databases/functions/relationshipAttributes.tsrelatedTableNameOf()findSiblingTableByName(). For an attribute reported by describe_table as { type: 'array' } with no elements, we match its name (and simple singular/plural variants) against sibling table names and treat it as a to-many relationship. Regression coverage that pins the current behavior: the "legacy elements-less relationships and reverse foreign keys" block in relationshipAttributes.test.ts.

Only elements-less arrays are affected. Typed scalar arrays (elements: 'String') and typed to-many relationships (elements: '<Table>') are unambiguous and unaffected.

Why it's a false positive (analysis)

Walking the two server regimes, an elements-less array in describe_table is never a Harper-modeled relationship:

  • Harper 5.1+: relationship attributes are omitted from describe_table entirely (see feat(databases): render, protect, and filter relationship attributes in browse #1438 / the describe regression). So anything that does appear as { type: 'array' } is a persisted plain/legacy array column, not a relationship → name match = false positive.
  • Harper 4.x: to-many relationships appear in describe with elements typed (e.g. reviews: [Review]{ type: 'array', elements: 'Review' }, verified against 4.7.28). A real to-many is therefore caught by the typed path, not the elements-less name heuristic.

So the elements-less name heuristic has no regime where it catches a relationship Harper actually models — it only ever fires on plain array data. The data.Albums.tracks case that motivated it "worked" by luck: Tracks.albumId lined up by convention, but tracks was not a declared @relationship.

Real relationships are already covered without the heuristic: schema-declared ones via schemaRelationships.ts (exact from:/to:, the only source on 5.1) and typed to-many via describe on 4.x.

Options

  1. Remove the elements-less name heuristic (findSiblingTableByName) — rely solely on schema-declared relationships + elements-typed describe. Removes the false positive at the root. Only behavior change: an un-declared elements-less array named like a table renders as plain JSON instead of a guessed reverse-link. Schema-declared to-many (e.g. Category.products) is unaffected (detected via schema, not this heuristic). Recommended.
  2. Gate on schema presence — apply the heuristic only to tables absent from all parsed component schemas. More conservative but keeps a guess for truly schema-less data.
  3. Corroborate — only treat an elements-less array as a relationship if the sibling table has a plausible reverse foreign key back-referencing this table. Narrows but doesn't eliminate false positives; couples detection to reverse-key inference.

Recommendation: option 1. If we want to keep a best-effort link for schema-less legacy data, option 2.

Not urgent

The column def, header, and data are all still present either way; the only impact is a plain array being shown as a link chip instead of JSON. No data correctness or write-path impact.

Metadata

Metadata

Assignees

No one assigned

    Labels

    admin & dataAdmin Panel & Other Data Enhancements (Jira STUDIO-494)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions