Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support range types for Postgres #1298

Closed
rsromanowski opened this issue Jul 15, 2021 · 4 comments · Fixed by #2213
Closed

Support range types for Postgres #1298

rsromanowski opened this issue Jul 15, 2021 · 4 comments · Fixed by #2213

Comments

@rsromanowski
Copy link
Contributor

rsromanowski commented Jul 15, 2021

Postgres has many built-in range types for fields: https://www.postgresql.org/docs/current/rangetypes.html

PostgreSQL comes with the following built-in range types:

  • int4range — Range of integer
  • int8range — Range of bigint
  • numrange — Range of numeric
  • tsrange — Range of timestamp without time zone
  • tstzrange — Range of timestamp with time zone
  • daterange — Range of date
@OlivierCavadenti
Copy link

I will take a look of this issue soon.

@pratikdotexe
Copy link

@OlivierCavadenti Did you take a look?

@philipchang-RL
Copy link

@OlivierCavadenti Was there ever a resolution for these supported range types in exposed? I tried implementing my own custom column types in exposed to support tstzrange however, the exposed JDBC driver complains when trying to insert a tstzrange formatted string into the tstzrange formatted column. Here is an example of the error: ERROR: column "_valid_period" is of type tstzrange but expression is of type character varying

@bog-walk
Copy link
Member

bog-walk commented May 2, 2024

Hi @philipchang-RL The casting exception you're seeing is most likely because you need to also override ColumnType.setParameter(). When setting an object in a prepared statement with JDBC, any unknown data type without a JDBC mapping is set as a varchar string. With PostgreSQL's stricter type system, this means needing to manually declare what the type of the set parameter should be, using a PGobject.

Here's a more detailed explanation of the error if you're interested.

Using current version 0.50.0, here's an example of how to implement a custom range type, specifically an int4range column that accepts IntRange input values:

class IntRangeColumnType : ColumnType<IntRange>() {
    override fun sqlType(): String = "int4range"

    override fun nonNullValueToString(value: IntRange): String = "[${value.first},${value.last}]"

    override fun setParameter(stmt: PreparedStatementApi, index: Int, value: Any?) {
        val parameterValue: PGobject? = value?.let {
            PGobject().apply {
                type = sqlType()
                this.value = nonNullValueToString(it as IntRange)
            }
        }
        super.setParameter(stmt, index, parameterValue)
    }

    override fun valueFromDB(value: Any): IntRange? = when (value) {
        is PGobject -> value.value?.let {
            val components = it.trim('[', ')').split(',')
            IntRange(components.first().toInt(), components.last().toInt() - 1)
        }
        else -> error("Retrieved unexpected value of type ${value::class.simpleName}")
    }
}

fun Table.intRange(name: String): Column<IntRange> = registerColumn(name, IntRangeColumnType())

// and how to use it
object Tester : Table("tester") {
    val amounts = intRange("amounts")
}

Tester.insert {
    it[amounts] = 10..<100
}

@bog-walk bog-walk linked a pull request Aug 23, 2024 that will close this issue
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants