Declares that all rows of an interface (or union) live on a single jOOQ table and that one column tells the generator which subtype each row belongs to. Implementing objects pin themselves to that column’s value via @discriminator. The pair drives a single-table polymorphic fetcher: one SELECT against the shared table, branching by discriminator value at row-mapping time.

Use @discriminator together with this directive on every implementing type. For multi-table polymorphism (different tables per implementer), omit @discriminate entirely — the rewrite emits a multi-table fetcher when the interface has no discriminator column.

SDL signature

directive @discriminate(on: String!) on INTERFACE | UNION

Parameters

Name Type Default Description

on

String!

(required)

Name of the column on the interface’s @table that carries the discriminator value. Each implementing type’s @discriminator(value:) is matched against this column at row-mapping time.

Canonical example

The example schema’s Content interface is single-table polymorphic: all rows live in content, and CONTENT_TYPE selects the subtype.

interface Content @table(name: "content") @discriminate(on: "CONTENT_TYPE") {
    contentId: Int!    @field(name: "CONTENT_ID")
    title:     String! @field(name: "TITLE")
}

type FilmContent implements Content @table(name: "content") @discriminator(value: "FILM") {
    contentId: Int!       @field(name: "CONTENT_ID")
    title:     String!    @field(name: "TITLE")
    length:    Int        @field(name: "LENGTH")
    rating:    MpaaRating @reference(path: [{key: "content_film_id_fkey"}]) @field(name: "RATING")
}

type ShortContent implements Content @table(name: "content") @discriminator(value: "SHORT") {
    contentId:   Int!    @field(name: "CONTENT_ID")
    title:       String! @field(name: "TITLE")
    description: String  @field(name: "SHORT_DESCRIPTION")
}

A query selecting …​ on FilmContent { length } and …​ on ShortContent { description } produces a single SELECT content.content_id, content.title, content.length, content.short_description, content.content_type FROM content; the row mapper inspects content_type per row and dispatches to the matching type. Subtype-only fields are read as nullable from the unified projection (the row mapper ignores them on the wrong subtype).

Subtype-specific fields may pull from another table. FilmContent.rating reaches into film via content_film_id_fkey; the generator projects it as a correlated subquery capped at one row, gated by content_type = 'FILM', so non-FILM rows read as NULL and the projection can never multiply the rows the query returns.

Constraints

  • The interface (or union) must carry @table; without it there is no shared table to branch on.

  • The on column must exist on that table. The build fails if it does not resolve, listing the table’s columns as candidates.

  • The column may be of any type the catalog resolves, a PostgreSQL enum included. Values are bound through the column’s own type, so an enum-typed discriminator compares correctly without any cast of your own.

  • When the column is a PostgreSQL enum, each @discriminator(value:) must be one of that enum’s literals. The build fails otherwise, naming the enum type and its literal set; a value outside the enum would otherwise bind as NULL and silently match no rows. A varchar column’s values are not checked, because there is nothing to check them against.

  • Every implementing object must declare @discriminator(value:). Implementers without one are rejected at classify time.

  • All implementers must share the interface’s @table (single-table polymorphism). Implementers on a different table are rejected; for cross-table polymorphism, omit @discriminate and use the multi-table fetcher instead.

  • @discriminate cannot be combined with disjoint-table union members. The same single-table requirement applies.

See also

  • @discriminator is the per-implementer pair: it names the discriminator value that places a row in this subtype.

  • @table establishes the shared table the discriminator column resolves against.

  • @reference for subtype-specific fields that pull from joined tables (such as FilmContent.rating in the example).

  • How-to: Polymorphic types for the choice between single-table and multi-table fetchers.