DynamicTypes

class DynamicTypes(client: OctaviusClient, val json: Json = octaviusJson, val strategy: DynamicWriteStrategy = DynamicWriteStrategy.AUTOMATIC_WHEN_UNAMBIGUOUS)

The dynamic_dto types this client knows: where they are registered, and where a value is wrapped for writing.

A dynamic_dto carrying a registered name reads as that class, several names read as the supertype asked for, and an instance of a registered class is written as a dynamic_dto unwrapped, on the terms strategy sets. The name is stated at registration or by DynamicallyMappable, never derived from the class: it is stored in the data, and a renamed class must still read it.

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()

A registration belongs to the database, not to this client, so it is done at startup: every client on the database reads the same names, and a class registered here is written and read with this client's json and strategy whichever client runs the query.

Constructors

Link copied to clipboard
internal constructor(client: OctaviusClient, json: Json = octaviusJson, strategy: DynamicWriteStrategy = DynamicWriteStrategy.AUTOMATIC_WHEN_UNAMBIGUOUS)

Properties

Link copied to clipboard
val enumSerializers: SerializersModule

Contextual serializers writing each registered enum in JSON under its PostgreSQL label, as the driver writes it in an enum column, instead of under the Kotlin constant's name.

Link copied to clipboard
val json: Json

How payloads of classes registered here are read and written. The default, octaviusJson, is strict and carries the serializers a @Contextual BigDecimal or date needs. A payload built in SQL with jsonb_build_object has to use the Kotlin property names, or be read with a Json using JsonNamingStrategy.SnakeCase - and carrying octaviusSerializersModule too.

Link copied to clipboard

When an unwrapped instance of a class registered here is written as a dynamic_dto.

Functions

Link copied to clipboard
fun install()

Creates the dynamic_dto type where the database lacks it, and reloads the driver's type catalog, which no fresh connection would. Where migrations manage the schema, put DYNAMIC_DTO_DDL in one instead.

Link copied to clipboard

The write-side mirror of resultConverter. toDynamicDto takes a Json of its own for the same purpose.

Link copied to clipboard
inline fun <T : Any> register()

Registers T, which has to be @Serializable, under the name its DynamicallyMappable declares. The overloads taking a name ignore the annotation.

inline fun <T : Any> register(typeName: String)

Registers T, which has to be @Serializable, under typeName.

fun register(kClass: KClass<*>)

Registers kClass, which has to be @Serializable, under the name its DynamicallyMappable declares.

fun register(kClass: KClass<*>, typeName: String)

Registers kClass, which has to be @Serializable, with the serializer its type resolves to.

fun <T : Any> register(kClass: KClass<T>, serializer: KSerializer<T>, typeName: String)

Registers kClass with serializer, for a caller that found the class rather than named it.

Link copied to clipboard
fun resultConverter(json: Json): ResultConverter<*, *>

A read converter for the registered types that decodes payloads with json instead of each class's own, for a query whose payloads are shaped differently - built with jsonb_build_object, or by another service. Register it on that query alone with registerResultConverter.

Link copied to clipboard
fun toDynamicDto(value: Any, json: Json = this.json): DynamicDto

Wraps value so it is written as a dynamic_dto whatever strategy says. Needed under EXPLICIT_ONLY, and for a class also registered as a composite under AUTOMATIC_WHEN_UNAMBIGUOUS.