fix(codegen-kotlin): generated controller filters @filterable field.enum columns (#179)#181
Merged
Merged
Conversation
…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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #179.
Bug
An Exposed enum column is typed
Column<Enum>, but the generated Kotlin Spring controller emittedTable.col eq (p.value as <BareEnum>)for a@filterable field.enum— two compile/runtime defects:Tierinstead of<Owner>Tier) → unresolved reference;String, soas <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 (FilterOpsgrants enum the string opseq/ne/in/like/isNull; the Exposed column stores the member name as VARCHAR, so the cast compares exactly what the other ports compare).columnElementTypereturns"String"for an enum (the predicate value type the coercer already produces).eq/ne/in/like;isNullstays on the raw column.castTo/TextColumnTypeimports 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 runseq/ne/in/likefilters against H2 (PostgreSQL mode) over MockMvc, asserting the correct rows (not just that it compiles).TphFullSuiteCompilesTest— gains a non-discriminator@filterableenum on a subtype (folds into the union), compile-gating the TPH controller's enum-import block (the reviewer's CONFIRMED gap — the TPH path sharesemitFilterPipelinebut 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