DynamicTypes
The dynamic_dto types this client knows, and what you do with them: register, and - where strategy or the class leaves the question open - wrap.
Registration is explicit and states the name, rather than deriving it from the class. A discriminator is stored in the data: derived from the class, renaming the class would change it silently and every row written before the rename would stop being readable, at runtime, on whichever query reached one first. The name can come from DynamicallyMappable instead, which is a declaration rather than a derivation and moves with the class rather than tracking it.
What registration buys is both directions. A dynamic_dto column carrying a registered name comes back as that class, and a column carrying several different names comes back as whatever supertype was asked for - which is how one column holds a sealed hierarchy. Going the other way, an instance of a registered class is written as a dynamic_dto without being wrapped, on the terms strategy sets.
db.dynamicTypes.install() // or put DYNAMIC_DTO_DDL in a migration
db.dynamicTypes.register<LandGrant>("land_grant")
db.dynamicTypes.register<MilitaryPension>("military_pension")
db.insertInto("veterans").values(listOf("id", "benefit"))
.executeUpdate("id" to 1, "benefit" to LandGrant("Gallia", 120))
val benefits: List<Benefit> = db.select("benefit").from("veterans").fetchFields()Registration is global to the database the client is connected to, the driver keeping one type catalog per database, so it belongs at startup and not per request. Every client on that database reads the same names, and a class registered through this one is written and read on this one's json and strategy whichever client the query goes through.
Constructors
Properties
The contextual serializers writing each registered enum under the label PostgreSQL holds, rather than under the Kotlin constant's own name.
How payloads of the classes registered here are read and written. The default is octaviusJson, which is strict - a payload carrying a field the class does not declare is an error rather than something dropped - and carries octaviusSerializersModule, so a @Contextual BigDecimal or date keeps in JSON what it would have kept in a column. Where the payload is built in SQL with jsonb_build_object, its keys have to match the Kotlin property names - supply a Json with JsonNamingStrategy.SnakeCase if the SQL side names them the way SQL usually does, and put that module on it too.
When an unwrapped instance of a class registered here is written as a dynamic_dto.
Functions
A write converter for the database's registrations that encodes payloads with json rather than with the one each class was registered with, and the mirror of resultConverter.
Registers T under the name its DynamicallyMappable declares.
Registers kClass under the name its DynamicallyMappable declares.
Registers kClass by looking its serializer up from its own type.
Registers kClass with a serializer supplied by the caller.
A read converter for the database's registrations that decodes payloads with json rather than with the one each class was registered with.
Wraps value for writing, saying that the dynamic_dto form is the one meant.