feat(java)!: native text[]/uuid[] OMDB binding + text default; drop uuid_array/text_array dbColumnType (phase 1)#120
Closed
dmealing wants to merge 1 commit into
Closed
feat(java)!: native text[]/uuid[] OMDB binding + text default; drop uuid_array/text_array dbColumnType (phase 1)#120dmealing wants to merge 1 commit into
dmealing wants to merge 1 commit into
Conversation
…uid_array/text_array/text dbColumnType (phase 1) dbColumnType slim-and-derive — Phase 1 (Java port). Applies ADR-0023 to the @dbColumnType escape hatch: native array columns and the text default are now DERIVED from field.subType + isArray + maxLength, not declared. Vocabulary (shared JVM value-set in CoreDBMetaDataProvider — also consumed by the Kotlin port; see coordination note below): - Remove uuid_array / text_array from VALID_DB_COLUMN_TYPES + the ValidationPhase legal-pairing table. Keep uuid, jsonb, timestamp_with_tz. (The vestigial `text` value never existed in the Java value-set — a no-maxLength field.string already defaults to a text column.) - A uuid_array / text_array / text @dbColumnType now FAILS the loader with ERR_BAD_ATTR_VALUE. OMDB native array binding (NEW — OMDB previously had no text[]/uuid[] support): - field.string + isArray:true → Postgres text[]; field.uuid + isArray:true → uuid[]. The element type is derived from the field subtype via a new per-driver nativeArrayElementType() hook (base returns null = no native arrays; PostgresDriver overrides → "text"/"uuid"). bindNativeArrayParameter() writes via Connection.createArrayOf + setArray; readNativeArrayInto() reads via ResultSet.getArray. uuid[] elements bind as java.util.UUID and read back lowercase-canonical (the cross-port wire contract, dialect-independent). - Root-cause fix in MetaField: getObjectValue/setObjectAttribute were scalar-typed (getValueClass()/dataType), which comma-joined an array field's List into a String. Now use the array-aware getEffectiveValueClass()/getEffectiveDataType() — for a scalar field these equal the base class/type, so non-array behavior is unchanged. field.string default → text: - SimpleMappingHandlerDB.readStringMaxLength no longer hardcodes 50 for a no-maxLength string; returns an UNBOUNDED_TEXT_LENGTH sentinel aligned with the canonical TS-owned text column. OMDB does no DDL (ADR-0015), so the runtime string bind is unbounded regardless; this only corrects ColumnDef metadata. DTO (SpringTypeMapper / SpringDtoGenerator): field.uuid isArray → List<UUID>, field.string isArray → List<String> (already wired via componentType; pinned by new tests). Tests (TDD): - DbColumnTypeValidationTest: uuid_array/text_array/text now ERR_BAD_ATTR_VALUE. - SpringTypeMapperTest: string/uuid isArray DTO components. - NativeArrayWriteRoundtripTest (integration-tests, Testcontainers PG): INSERT a text[] and a uuid[] through ObjectManagerDB (not raw SQL), read back, assert the Lists round-trip (uuid lowercase-canonical). Ran green against real Postgres. - Suites green: metadata 1058, omdb 46, codegen-spring 148, integration-tests 86. Java/Kotlin shared-file coordination: CoreDBMetaDataProvider's value-set is shared with the Kotlin port. This commit removes the uuid_array/text_array CONSTANTS there; KotlinTypeMapper.kt still references them and will be converted to the derived default by the parallel Kotlin port change. The two changes merge together. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LuZWKnWzYGVnESijL7uuky
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. |
Member
Author
|
Landed via the integrated Phase-1 PR #121 (squash-merged to main). |
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.
Part of dbColumnType slim-and-derive Phase 1 (Java port). Applies the project's own ADR-0023 principle to the
@dbColumnTypeescape hatch: native array columns and the no-maxLength text default are now derived fromfield.subType+isArray+maxLength, not declared.Spec:
docs/superpowers/specs/2026-06-29-dbcolumntype-slim-and-derive-design.md(onfeat/dbcolumntype-slim-derive).What changed
1. Vocabulary slim (shared JVM value-set)
CoreDBMetaDataProvider.VALID_DB_COLUMN_TYPESdropsuuid_array/text_array(+ theValidationPhaselegal-pairing table). Kept:uuid,jsonb,timestamp_with_tz. A no-maxLengthfield.stringalready defaults to a text column, so the vestigialtextvalue was never in the Java value-set.uuid_array/text_array/texton@dbColumnTypenow fail the loader withERR_BAD_ATTR_VALUE.2. NEW OMDB native array binding
OMDB previously had no
text[]/uuid[]JDBC support. Built it:nativeArrayElementType()hook: baseGenericSQLDriverreturnsnull(no native arrays — Derby et al. fall through to the scalar codec);PostgresDriveroverrides →"text"forfield.string isArray,"uuid"forfield.uuid isArray. The element type is derived from the field subtype (the removed declared values).bindNativeArrayParameter()→Connection.createArrayOf(...)+setArray.uuid[]elements bind asjava.util.UUID.readNativeArrayInto()→ResultSet.getArray.uuid[]elements read back lowercase-canonical (cross-port wire contract, dialect-independent).MetaField:getObjectValue/setObjectAttributewere scalar-typed (getValueClass()/dataType), which comma-joined an array field'sListinto aString. Now use the array-awaregetEffectiveValueClass()/getEffectiveDataType()— for a scalar field these equal the base class/type, so non-array behavior is byte-unchanged (proven by the full suites below).3.
field.stringdefault → textSimpleMappingHandlerDB.readStringMaxLengthno longer hardcodesVARCHAR(50)for a no-maxLength string; it returns anUNBOUNDED_TEXT_LENGTHsentinel aligned with the canonical TS-ownedtextcolumn. OMDB does no DDL (ADR-0015), so the runtime string bind was already unbounded — this correctsColumnDefmetadata only.4. DTO
field.uuid isArray→List<java.util.UUID>,field.string isArray→List<String>(already wired viaSpringDtoGenerator.componentType; pinned by newSpringTypeMapperTestcases — the spec's "uuid isArray DTO throws" was already resolved for the DTO path).Timestamp behavior untouched (Phase 2).
Test evidence
TDD. New tests:
DbColumnTypeValidationTest—uuid_array/text_array/text→ERR_BAD_ATTR_VALUE.SpringTypeMapperTest— string/uuidisArrayDTO components.NativeArrayWriteRoundtripTest(integration-tests) — Testcontainers Postgres ran (Docker available): INSERTs atext[]and auuid[]throughObjectManagerDB.createObject(NOT raw SQL), reads back, asserts the Lists round-trip (uuid lowercase-canonical). Green against real PG.Suites green: metadata 1058, omdb 46, codegen-spring 148, integration-tests 86 (full suite, incl. all persistence conformance — the core
MetaFieldchange caused zero regressions).Java/Kotlin shared-file coordination⚠️
CoreDBMetaDataProvider's value-set is shared with the Kotlin port. This PR removes theuuid_array/text_arrayconstants there.KotlinTypeMapper.ktstill references them and is converted to the derived default by the parallel Kotlin port change — the two PRs merge together.codegen-kotlinis not in this PR's tested reactor (metadata,omdb,codegen-spring), which builds and tests clean.Part of dbColumnType slim-and-derive Phase 1
🤖 Generated with Claude Code