jOOQ не использует привязку пользовательских данных - PullRequest
0 голосов
/ 13 декабря 2018

Я пытаюсь написать привязку пользовательского типа данных для PGInterval и Duration, чтобы использовать jOOQ вместе с TimescaleDB.К сожалению, jOOQ не использует его при создании функций для подпрограмм базы данных.

Вот мой класс привязки:

import org.jooq.*
import org.jooq.conf.ParamType
import org.jooq.impl.DSL
import org.postgresql.util.PGInterval
import java.sql.SQLFeatureNotSupportedException
import java.sql.Types
import java.time.Duration
import java.util.*

class PostgresIntervalDurationBinding: Binding<Any, Duration> {
    override fun converter(): Converter<Any, Duration> {
        return object : Converter<Any, Duration> {
            override fun from(t: Any?): Duration {
                return if (t == null) Duration.ZERO else Duration.ofSeconds(pgIntervalToSeconds(t as PGInterval))
            }

            override fun to(u: Duration?): Any? {
                return if (u == null || u === Duration.ZERO) null else PGInterval().seconds = u.seconds.toDouble()
            }

            override fun fromType(): Class<Any> {
                return Any::class.java
            }

            override fun toType(): Class<Duration> {
                return Duration::class.java
            }
        }

    }

    override fun sql(ctx: BindingSQLContext<Duration>?) {
        if (ctx?.render()?.paramType() == ParamType.INLINED)
            ctx.render()?.visit(DSL.inline(ctx.convert(converter()).value()))?.sql("::interval")
        else
            ctx?.render()?.sql("?::interval")
    }

    override fun register(ctx: BindingRegisterContext<Duration>?) {
        ctx?.statement()?.registerOutParameter(ctx.index(), Types.VARCHAR)
    }

    override fun set(ctx: BindingSetStatementContext<Duration>?) {
        ctx?.statement()?.setString(ctx.index(), Objects.toString(ctx.convert(converter()).value(), null))
    }

    override fun get(ctx: BindingGetResultSetContext<Duration>?) {
        ctx?.convert(converter())?.value(ctx.resultSet().getString(ctx.index()))
    }

    override fun get(ctx: BindingGetStatementContext<Duration>?) {
        ctx?.convert(converter())?.value(ctx.statement().getString(ctx.index()))
    }

    override fun set(ctx: BindingSetSQLOutputContext<Duration>?) {
        throw SQLFeatureNotSupportedException()
    }

    override fun get(ctx: BindingGetSQLInputContext<Duration>?) {
        throw SQLFeatureNotSupportedException()
    }

    companion object {
        fun pgIntervalToSeconds(t: PGInterval): Long {
            var seconds = 0L
            with(t){
                seconds += Duration.ofSeconds(this.seconds.toLong()).seconds
                seconds += Duration.ofMinutes(this.minutes.toLong()).seconds
                seconds += Duration.ofHours(this.hours.toLong()).seconds
                seconds += Duration.ofDays(this.days.toLong()).seconds
                if (months > 0 || years > 0) throw SQLFeatureNotSupportedException()
            }
            return seconds
        }
    }
}

Это моя конфигурация в pom:

<database>
<name>org.jooq.meta.postgres.PostgresDatabase</name>
<includes>.*</includes>
<inputSchema>public</inputSchema>
<excludes>set_adaptive_chunking
    | flyway_schema_history
</excludes>
<forcedTypes>
    <forcedType>
        <userType>java.time.Duration</userType>

        <binding>de.ninjaneers.dmc.jooq.databindings.PostgresIntervalDurationBinding
        </binding>
        <expression>.*interval.*</expression>

        <types>.*</types>
    </forcedType>
</forcedTypes>
</database>

Например, я ожидаю, что jOOQ сгенерирует подпрограмму

time_bucket(bucket_with interval, ts timestamp with time zone) 

как

timeBucket(Field<Duration> bucketWidth, Field<Timestamp> ts) 

, но я получу

timeBucket(Field<Object> bucketWidth, Field<Timestamp> ts)

1 Ответ

0 голосов
/ 13 декабря 2018

Вы путаете два флага конфигурации:

<expression>.*interval.*</expression>
<types>.*</types>

<expression> - это регулярное выражение, совпадающее с идентификатором столбца / атрибута / параметра, тип которого вы хотите заменить.<types> соответствует типам данных.Это то, что вы хотите:

<types>.*interval.*</types>
<expression>.*</expression>
...