Skip to content

DX improvements: RowCodec.of(), insertIntoGeneratedKeys, cross-DB RoutineAnalyzer, Oracle fixes#32

Open
oyvindberg wants to merge 9 commits intomainfrom
fix/dx-report-api-improvements
Open

DX improvements: RowCodec.of(), insertIntoGeneratedKeys, cross-DB RoutineAnalyzer, Oracle fixes#32
oyvindberg wants to merge 9 commits intomainfrom
fix/dx-report-api-improvements

Conversation

@oyvindberg
Copy link
Contributor

@oyvindberg oyvindberg commented Mar 15, 2026

Summary

  • RowCodec.of() tuple factories: Codegen RowCodec.of(t0, t1, ...) for arities 2-22 returning Tuple types (Java, Kotlin with native tuples, Scala with native tuples)
  • Fragment.insertIntoGeneratedKeys(): New INSERT helper for databases without RETURNING (Oracle, SQL Server, MariaDB, DB2) — uses JDBC getGeneratedKeys()
  • Cross-DB RoutineAnalyzer: analyzeFunction() now uses CAST(NULL AS type) on non-PG/DuckDB databases instead of PG-only null::type; adds FROM DUAL for Oracle/DB2; retries uppercase procedure name lookup for Oracle
  • Oracle CHAR alias: char_ now includes varchar2 as vendor alias for query analysis matching
  • Oracle nullability docs: Documents Oracle's empty-string-as-NULL behavior
  • OBJECT/VARRAY/NESTED TABLE docs: Compile-checked snippets in all 3 languages showing OracleObject builder, OracleVArray.of(), OracleNestedTable.of()
  • DB2 vendor type aliases: Fix query analyzer false positives for int_, numeric, dec, float_, character by adding withVendorTypeNames() to match canonical JDBC metadata names
  • Document executeVoid(): Add compile-checked snippets (Java/Kotlin/Scala) to operations.md for void operations (DDL, schema setup)
  • Document Tuple accessors: Clarify ._1(), ._2(), ._3() pattern applies to RowCodec.of(), .combine(), and .joined() — not just joins
  • Document insertIntoGeneratedKeys: New "Generated Keys Inserts" section in row-codecs.md with compile-checked snippets for DB2/Oracle/SQL Server/MariaDB

Commits

  1. Fix DX report: query analyzer bugs, API renames, Transactor.create(), RoutineDef, PG procedure CALL
  2. Add Query Analysis database behavior docs page
  3. Eliminate unchecked casts from Kotlin Procedure, Bijection, and generated code
  4. Fix Mapped.opt() null detection, add columnList(alias), fix Kotlin wrapper bugs, support Scala types in scanner
  5. RowCodec.of() tuple factories, insertIntoGeneratedKeys, cross-DB RoutineAnalyzer, Oracle fixes
  6. Fix DB2 vendor type aliases, document executeVoid, Tuple accessors, insertIntoGeneratedKeys

Test plan

  • All core modules compile (foundations-jdbc, hikari, spring, kotlin, scala)
  • Documentation examples compile-checked in Java, Kotlin, Scala
  • Oracle OBJECT/VARRAY/NESTED TABLE snippets compile across all languages
  • DB2 example project exercises 35+ query patterns and validates query analyzer

🤖 Generated with Claude Code

oyvindberg and others added 4 commits March 13, 2026 22:58
…apper bugs, support Scala types in scanner

- Fix Mapped.opt() in all 5 DbRead implementations (DuckDb, Pg, Maria, SqlServer, Db2)
  to delegate null detection to the underlying reader instead of wrapping the
  already-mapped value with Optional.ofNullable(). This fixes LEFT/FULL JOIN
  codecs that use transformed types (e.g. Scala Option, Kotlin nullable).

- Add RowCodecNamed.columnList(String alias) in Java, Kotlin, and Scala for
  generating alias-prefixed column lists in JOIN queries (e.g. "v.id, v.name").

- Fix Kotlin Transactor.execute() to run operations through Kotlin-side wrappers
  (Combine→Pair, IfEmpty→nullable) instead of bypassing them via Java underlying.

- Fix Kotlin Operation.Configured.run() to delegate to Kotlin inner operation
  instead of casting Java underlying result.

- Add Scala type support (Option, List, Seq, Map) to AnalyzableScanner.constructDummy()
  using class name matching to avoid hard dependency on Scala runtime.

- Change Scala DuckDbType.mapTo() to return scala.collection.immutable.Map instead
  of java.util.Map, consistent with how list already returns scala List.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ated code

- Redesign ProcedureOp to use typed closures (direct/mapped factory methods)
  instead of Operation<Any?> + (Any?) -> Out, eliminating all casts in
  Procedure.call(), fromVoid(), and fromJava().

- Update DbProcedure/DbFunction sourcegen to use ProcedureOp.direct() and
  ProcedureOp.mapped() instead of casting to Operation<Any?>, removing all
  @Suppress("UNCHECKED_CAST") from generated procedure/function builders.

- Delete Bijection.optionalToNullableUnchecked() and unused nullableToOptional().
  Remove : Any bound from optionalToNullable() so all DbType.opt() callers
  use it directly. One narrow cast remains (Optional<T & Any> -> Optional<T>)
  which is a known Kotlin type system limitation with no stdlib workaround.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document the exact JDBC metadata behavior for all six supported
databases based on empirical testing. Covers column types, column
nullability, outer join nullability, parameter types, expressions,
aggregates, CTEs, and UNIONs. Links from the main query analysis
page, reference page, and landing page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… RoutineDef, PG procedure CALL

- Fix query analyzer serial/bigserial/smallserial aliases and schema-qualified enum quoting
- Add Operation.Execute using stmt.execute() for Fragment.execute() (works with any SQL)
- PostgreSQL procedures use CALL with PreparedStatement instead of {call} with CallableStatement
- Rename streamingInsert → StreamingInsert, thenIgnore → productL
- Kotlin/Scala transform() accepts native language functions instead of SqlFunction
- Move transactor() from DatabaseConfig/Builders to Transactor.create(config) static factories
- Add RoutineDef interface with procedure(), checkRoutine(RoutineDef) on QueryChecker
- Sourcegen: Def interfaces extend RoutineDef, build() returns implementations with procedure()
- Update all docs, examples, and regenerate snippets.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@oyvindberg oyvindberg force-pushed the fix/dx-report-api-improvements branch from 767d524 to 2561bf3 Compare March 15, 2026 10:43
…ineAnalyzer, Oracle fixes

- Codegen RowCodec.of(t0, t1, ...) for arities 2-22 returning Tuple types (Java, Kotlin, Scala)
- Add Fragment.insertIntoGeneratedKeys() for Oracle/SQL Server/MariaDB/DB2 INSERT + generated keys
- Fix RoutineAnalyzer.analyzeFunction() to use CAST(NULL AS type) on non-PG/DuckDB databases
- Fix RoutineAnalyzer.analyzeProcedure() to retry with uppercase name for Oracle
- Add FROM DUAL suffix for Oracle/DB2 function analysis
- Add CHAR→VARCHAR2 vendor alias in OracleTypes for query analysis
- Document Oracle nullability behavior (empty string = NULL)
- Add compile-checked OBJECT/VARRAY/NESTED TABLE doc snippets in Java/Kotlin/Scala

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@oyvindberg oyvindberg changed the title Fix DX report: query analyzer bugs, API renames, RoutineDef DX improvements: RowCodec.of(), insertIntoGeneratedKeys, cross-DB RoutineAnalyzer, Oracle fixes Mar 15, 2026
oyvindberg and others added 4 commits March 16, 2026 23:12
…nsertIntoGeneratedKeys

- Fix DB2 query analyzer false positives: add withVendorTypeNames() to int_, numeric, dec,
  float_, character, and numeric(p,s) aliases so they match canonical JDBC metadata names
- Document executeVoid() in operations.md with compile-checked snippets (Java/Kotlin/Scala)
- Expand Tuple documentation in row-codecs.md: clarify _1()/_2()/_3() accessors apply to
  RowCodec.of(), combine(), and joined() — not just joins
- Add "Generated Keys Inserts" section to row-codecs.md documenting Fragment.insertIntoGeneratedKeys()
  for databases without RETURNING (DB2, Oracle, SQL Server, MariaDB)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New foundations-jdbc-otel module with OpenTelemetry instrumentation:
- DatabaseSystem enum mapping DatabaseKind to OTel db.system.name
- TelemetryConfig with builder and JDBC URL auto-parsing
- OtelQueryListener using backdated spans (no ThreadLocal, virtual-thread safe)
- PoolMetrics for HikariCP connection pool gauges
- Pre-built Grafana dashboard (latency, errors, throughput, pool metrics)

MariaDB VECTOR type for 11.7+ (MariaTypes.vector(dimension)):
- MariaRead/Write/Json/OutParam support via connector FloatArrayCodec

Documentation: OTel setup guide with compile-checked snippets (Java/Kotlin/Scala),
updated observability page, sidebar entry.

Fix Scala doc examples: scala.Map vs java.util.Map mismatch in MapTypes/TypeSafeDbTypes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- UUID type (MariaDB 10.7+): maps to java.util.UUID via string read/write
- VECTOR type wrappers added to Kotlin/Scala (Java was in prior commit)
- Test cases for UUID (standard, nil, max) and VECTOR (1/3/5 dimensions)
- Bump test container from MariaDB 11.4 to 11.7 for VECTOR support
- Fix test project to discover Java tests (sources, testFrameworks config)
- Documentation snippets for UUID and VECTOR across Java/Kotlin/Scala

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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