postgresql - 如何在 Jetbrains Exposed 中添加数组列类型

标签 postgresql kotlin kotlin-exposed

我正在尝试使用exported 将一列数组类型添加到我的Postgres 表中。目标是得到如下语句:

UPDATE posts
              SET like_user_id = like_user_id || $1, likes = likes + 1
              WHERE NOT (like_user_id @> $1)
              AND pid = ($2) 

帖子表:

CREATE TABLE posts (
  pid SERIAL PRIMARY KEY,
  title VARCHAR(255),
  body VARCHAR,
  user_id INT REFERENCES users(uid),
  author VARCHAR REFERENCES users(username),
  date_created TIMESTAMP
  like_user_id INT[] DEFAULT ARRAY[]::INT[],
  likes INT DEFAULT 0
);

最佳答案

Kotlin Exposited 框架本身不支持列类型的数组,需要您自己实现。这是我在尝试做同样的事情时发现的通用版本 https://github.com/LorittaBot/Loritta/blob/db577852a76266d207361b7d8257d24b4ee0b947/platforms/discord/legacy/src/main/java/com/mrpowergamerbr/loritta/utils/exposed/array.kt

fun <T> Table.array(name: String, columnType: ColumnType): Column<Array<T>> = registerColumn(name, ArrayColumnType(columnType))

class ArrayColumnType(private val type: ColumnType) : ColumnType() {

    private fun supportsArrays() = !loritta.config.database.type.startsWith("SQLite")

    override fun sqlType(): String = buildString {
        if (!supportsArrays()) {
            append("TEXT")
        } else {
            append(type.sqlType())
            append(" ARRAY")
        }
    }

    override fun valueToDB(value: Any?): Any? {
        if (!supportsArrays())
            return "'NOT SUPPORTED'"

        if (value is Array<*>) {
            val columnType = type.sqlType().split("(")[0]
            val jdbcConnection = (TransactionManager.current().connection as JdbcConnectionImpl).connection
            return jdbcConnection.createArrayOf(columnType, value)
        } else {
            return super.valueToDB(value)
        }
    }

    override fun valueFromDB(value: Any): Any {
        if (!supportsArrays()) {
            val clazz = type::class
            val clazzName = clazz.simpleName
            if (clazzName == "LongColumnType")
                return arrayOf<Long>()
            if (clazzName == "TextColumnType")
                return arrayOf<String>()
            error("Unsupported Column Type")
        }

        if (value is java.sql.Array) {
            return value.array
        }
        if (value is Array<*>) {
            return value
        }
        error("Array does not support for this database")
    }

    override fun notNullValueToDB(value: Any): Any {
        if (!supportsArrays())
            return "'NOT SUPPORTED'"

        if (value is Array<*>) {
            if (value.isEmpty())
                return "'{}'"

            val columnType = type.sqlType().split("(")[0]
            val jdbcConnection = (TransactionManager.current().connection as JdbcConnectionImpl).connection
            return jdbcConnection.createArrayOf(columnType, value) ?: error("Can't create non null array for $value")
        } else {
            return super.notNullValueToDB(value)
        }
    }
}

关于postgresql - 如何在 Jetbrains Exposed 中添加数组列类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60802669/

相关文章:

postgresql - 我如何判断酒保是否在白天接收 WAL 流?

sql - 在 Postgresql 中选择以字符串形式存储的分数作为十进制值

java - PostgreSQL 应用访问

android - 恢复应用程序时如何禁用DialogFragment过渡动画?

android - 如何使用 CRONET 在 Android 中发送 “multipart/form-data” POST?

postgresql - PSQL 使用 Exposed 进行不区分大小写的搜索

python-3.x - SQLAlchemy scoped_session 没有从数据库获取最新数据

unit-testing - 在 Kotlin 中模拟 "global"属性

kotlin - 如何避免 kotlin Exposed 上的 N+1 查询问题。 (当通过 DAO 的 Reference.id.value 字段获取值时)

Kotlin 暴露 : How to create prepared statement or avoid SQL Injection?