Skip to content

fix(codegen-kotlin): generated controller filters @filterable field.enum columns (#179)#181

Merged
dmealing merged 1 commit into
mainfrom
fix/kotlin-enum-filter-controller
Jul 6, 2026
Merged

fix(codegen-kotlin): generated controller filters @filterable field.enum columns (#179)#181
dmealing merged 1 commit into
mainfrom
fix/kotlin-enum-filter-controller

Conversation

@dmealing

@dmealing dmealing commented Jul 6, 2026

Copy link
Copy Markdown
Member

Closes #179.

Bug

An Exposed enum column is typed Column<Enum>, but the generated Kotlin Spring controller emitted Table.col eq (p.value as <BareEnum>) for a @filterable field.enumtwo compile/runtime defects:

  1. the enum type name was un-prefixed (Tier instead of <Owner>Tier) → unresolved reference;
  2. even fixed, the filter-value coercer produces a String, so as <Enum>ClassCastException.

So any entity with a filterable enum column produced a non-compiling controller. Pre-existing; the TPH subtype-fold work (#180) was the first filterable enum to reach a Kotlin controller.

Fix

Filter an enum column by its stored string via CAST(col AS text) (col.castTo<String>(TextColumnType())) — matching every other port's string-band enum-filter semantics (FilterOps grants enum the string ops eq/ne/in/like/isNull; the Exposed column stores the member name as VARCHAR, so the cast compares exactly what the other ports compare).

  • columnElementType returns "String" for an enum (the predicate value type the coercer already produces).
  • The WHERE arm wraps the column in the cast for eq/ne/in/like; isNull stays on the raw column.
  • castTo / TextColumnType imports are added conditionally — on both the vanilla and the TPH controller import blocks — only when a filterable enum column is present, so enum-free controllers stay byte-identical.

Gating

  • EnumFilterControllerRunTest — compiles the generated controller and runs eq/ne/in/like filters against H2 (PostgreSQL mode) over MockMvc, asserting the correct rows (not just that it compiles).
  • TphFullSuiteCompilesTest — gains a non-discriminator @filterable enum on a subtype (folds into the union), compile-gating the TPH controller's enum-import block (the reviewer's CONFIRMED gap — the TPH path shares emitFilterPipeline but has its own import set).

All green: codegen-kotlin 271/0, api-contract 21/0, TPH 6/0, no snapshot drift (non-enum controllers unchanged).

Two rounds of code review + simplify informed this change.

🤖 Generated with Claude Code

…num columns (#179)

An Exposed enum column is typed `Column<Enum>`, but the generated Spring controller
emitted `Table.col eq (p.value as <BareEnum>)` for a @filterable field.enum — an
unresolved un-prefixed enum type name AND a String→enum cast (the filter-value coercer
produces a String). So any entity with a filterable enum column produced a
non-compiling controller. Pre-existing; surfaced by the TPH subtype-fold work (#180),
which is the first filterable enum to reach a Kotlin controller.

Fix: filter an enum column by its STORED STRING via `CAST(col AS text)`
(`col.castTo<String>(TextColumnType())`) — matching every other port's string-band
enum-filter semantics (FilterOps grants enum the string ops eq/ne/in/like/isNull; the
column stores the member name as VARCHAR). columnElementType returns "String" for an
enum (the predicate value type the coercer already produces); the WHERE arm wraps the
column in the cast for eq/ne/in/like (isNull stays on the raw column); the castTo /
TextColumnType imports are added conditionally — on BOTH the vanilla and the TPH
controller import blocks — only when a filterable enum column is present, so enum-free
controllers stay byte-identical.

Gated:
- EnumFilterControllerRunTest compiles the generated controller AND runs eq/ne/in/like
  filters against H2 (PostgreSQL mode) over MockMvc, asserting the right rows.
- TphFullSuiteCompilesTest gains a non-discriminator @filterable enum on a subtype
  (folds into the union), compile-gating the TPH controller's enum-import block.

Two rounds of code review + simplify informed this change (the second caught the TPH
import block, which shares emitFilterPipeline but has its own import set).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ew1XfYSbEAezxjs9opynAe
@dmealing
dmealing merged commit 7cc6a54 into main Jul 6, 2026
1 check passed
@dmealing
dmealing deleted the fix/kotlin-enum-filter-controller branch July 6, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

codegen-kotlin: generated Spring controller emits non-compiling enum-filter code for @filterable field.enum columns

1 participant