Skip to content

feat(codegen-kotlin)!: native arrays + text default by derivation (dbColumnType slim-and-derive Phase 1)#119

Closed
dmealing wants to merge 1 commit into
mainfrom
feat/kotlin-dbcolumntype-slim-derive-phase1
Closed

feat(codegen-kotlin)!: native arrays + text default by derivation (dbColumnType slim-and-derive Phase 1)#119
dmealing wants to merge 1 commit into
mainfrom
feat/kotlin-dbcolumntype-slim-derive-phase1

Conversation

@dmealing

Copy link
Copy Markdown
Member

Kotlin (Exposed) port of dbColumnType slim-and-derive — Phase 1. Derives what the metadata already says (field.subType + isArray + maxLength) instead of declaring it via @dbColumnType, aligning the Exposed output with the canonical TS Postgres DDL.

What changed (KotlinTypeMapper + Exposed table codegen)

text is the no-maxLength default

  • field.string with no @maxLength now derives Exposed text(...) — matching the canonical TS text — instead of the old varchar(255).
  • field.string with @maxLength: Nvarchar(N) (the >4000 → text cutoff is preserved).
  • stringMaxLength (which defaulted to 255) is replaced by stringMaxLengthOrNull (absent ⇒ null ⇒ text).

@kind:text hack removed

  • The unregistered @kind attribute (KIND_TEXT / ATTR_KIND) that forced text(...) is gone. It was an unregistered attr that fails strict verify; with text now the no-maxLength default, the hack is unnecessary.

Native arrays are the DEFAULT (derived from isArray)

  • field.string + isArray:truearray<String>("col", TextColumnType()) (native text[]).
  • field.uuid + isArray:truearray<java.util.UUID>("col", UUIDColumnType()) (native uuid[]) — previously field.uuid + isArray fell through to the scalar uuid() column.
  • The uuid_array / text_array / text @dbColumnType branches are removed (they derived the same thing the default now produces).
  • isArrayResolved resolves array-ness through the extends super chain, so an object.projection field keeps inheriting its base field's array-ness (the projection-inheritance contract the regression test guards).
  • kotlinTypeName stays the scalar/element mapper; the List<…> wrapping is applied by the entity/payload generators per isArray (avoids a List<List<…>> double-wrap). The native-array column DDL is emitted only in exposedColumnSpec.

Unchanged

Test evidence

  • codegen-kotlin: 255 / 0 / 0. Updated KotlinTypeMapperTest (no-maxLength→text; string/uuid isArray→native array; @kind:text path removed; +maxLengthvarchar), KotlinProjectionExtendsInheritanceTest (tags uses isArray:true instead of @dbColumnType:text_array), KotlinExposedTableGeneratorTest.
  • integration-tests-kotlin: 92 / 0 / 0 — the Exposed write codec round-trips against Testcontainers Postgres.
  • Snapshot single-entity-primitives/.../AuthorTable.kt regenerated: bio (no @maxLength) → text("bio"), proving the derived output.

Dependency on the Java agent

The shared CoreDBMetaDataProvider.java value-set is intentionally NOT modified here — removing the DB_COLUMN_TYPE_UUID_ARRAY / _TEXT_ARRAY / _TEXT constants from the cross-port provider is the Java agent's task. The Kotlin mapper no longer references those constants, so it compiles whether or not they've been removed yet. Once the Java agent removes them, an author can no longer write @dbColumnType: uuid_array/text_array/text (loader-rejected); until then those values are simply ignored by the Kotlin generator (arrays/text derive correctly regardless).

Part of dbColumnType slim-and-derive Phase 1

🤖 Generated with Claude Code

…move @kind:text hack + array/text dbColumnType (phase 1)

dbColumnType slim-and-derive Phase 1 for the Kotlin (Exposed) port. Derives
what the metadata already says (field.subType + isArray + maxLength) instead of
declaring it via @dbColumnType, aligning Exposed output with the canonical
TS Postgres DDL.

- text default: field.string with no @maxlength now derives Exposed `text(...)`
  (matching the canonical TS `text`), not the old `varchar(255)`. With @maxlength N
  → `varchar(N)` (>4000 still → text). `stringMaxLength` (defaulted 255) is replaced
  by `stringMaxLengthOrNull`.
- @kind:text hack removed: the unregistered `@kind` attr (KIND_TEXT/ATTR_KIND) that
  forced `text(...)` is gone — `text` is now the no-maxLength default, so the hack
  (which failed strict verify) is unnecessary.
- native arrays are the DEFAULT, derived from `isArray` (no @dbColumnType):
  field.string + isArray → `array<String>("col", TextColumnType())` (native text[]);
  field.uuid + isArray → `array<java.util.UUID>("col", UUIDColumnType())` (native
  uuid[]) — previously field.uuid+isArray fell through to scalar `uuid()`. The
  `uuid_array`/`text_array`/`text` dbColumnType branches are removed (they derived the
  same thing). `isArrayResolved` resolves array-ness through the `extends` super chain
  so an object.projection field keeps inheriting its base field's array-ness.
- kotlinTypeName stays the SCALAR/element mapper; List<…> wrapping is applied by the
  entity/payload generators per isArray (avoids List<List<…>> double-wrap). The native
  array column DDL is emitted only in exposedColumnSpec.
- uuid (string→uuid column) and jsonb (#98) escape hatches are unchanged; timestamp
  is untouched (Phase 2).

Shared `CoreDBMetaDataProvider.java` value-set is intentionally NOT modified — removing
`DB_COLUMN_TYPE_UUID_ARRAY`/`_TEXT_ARRAY`/`_TEXT` from the cross-port provider is the
Java agent's task. The Kotlin mapper no longer references those constants, so it
compiles whether or not they have been removed yet.

Tests: codegen-kotlin 255/0/0; integration-tests-kotlin 92/0/0 (Exposed write codec
vs Testcontainers Postgres). Snapshot AuthorTable.kt regenerated (bio: no-maxLength
string → text, proving the derived output).

Part of dbColumnType slim-and-derive Phase 1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LuZWKnWzYGVnESijL7uuky
@dmealing

Copy link
Copy Markdown
Member Author

Folded into the integrated Phase-1 PR (feat/dbcolumntype-slim-derive) which merges all five ports atomically — that's the one that lands. Keeping this open for per-port review history.

@dmealing

Copy link
Copy Markdown
Member Author

Landed via the integrated Phase-1 PR #121 (squash-merged to main).

@dmealing dmealing closed this Jun 30, 2026
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.

1 participant