Skip to content

Inverse relation metadata uses the primary identity instead of the referenced alternate unique key #30214

Description

@JoeRoddy

Type: native contract-builder relation anchor deficiency. Target: @prisma/orm-postgres@8.0.0-rc.8.

The standalone native-only reproduction exports reproduceNativeAlternateUnique(). It needs no PostgreSQL connection and imports only Node assertions and Prisma's public contract builder.

A parent has a primary key id and a separate unique externalKey. A child declares owner: rel.belongsTo(Parent, { from: "ownerKey", to: "externalKey" }). That direction correctly emits ownerKey → externalKey. Adding child: rel.hasOne(Child, { by: "ownerKey" }) to the parent emits the inverse join as id → ownerKey, although the referenced relation targets externalKey. The reproduction asserts both emitted tuples so a native change prompts review.

For a parent whose id is record-1 and externalKey is account-1, a child's ownerKey should contain account-1. The inverse relation must therefore join the parent's externalKey, not its id. The pinned native lowerHasOwnershipRelation resolves the parent anchor from its identity; the hasOne and hasMany options provide the child by fields without a corresponding parent-field choice.

Expected behavior: the inverse metadata should join externalKey to ownerKey, matching the declared owning relation. Composite alternate unique keys should preserve the complete referenced tuple.

Public native contract metadata can represent the correct join if constructed directly with the inverse relation's on.localFields set to ["externalKey"]; that is a manual contract-level workaround. It does not correct contract-builder emission, and the generated inverse remains wrong when primary and alternate unique values differ.

Environment

  • @prisma/orm-postgres: 8.0.0-rc.8 (the live latest tag when reverified September 6, 2026)
  • Prisma CLI: 8.0.0-rc.13
  • TypeScript: 5.9.3
  • Node: 26.5.0
  • npm: 11.17.0
  • OS: macOS 26.6.2 arm64
  • PostgreSQL: 14.23 for database-backed cases

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions