Hello! Why ArrayColumnType cannot handle arrays? ...
# exposed
r
Hello! Why ArrayColumnType cannot handle arrays? In my request I combined array literal with array aggregate, something like this:
Copy code
SELECT
       array [ARRAY_AGG(object_information_translation."value"),ARRAY_AGG(CAST(object_information_translation.lang AS TEXT))]
It crashes on ArrayString which is not java.sql.Array type and cannot be casted to list I tried to create my own ListColumnType
Copy code
class ListColumnType<Type>(delegate: ColumnType<Type & Any>) : ColumnType<List<Type>>() {
    val arrayDelegate = ArrayColumnType(delegate)
    override fun sqlType(): String = arrayDelegate.sqlType()

    override fun valueFromDB(value: Any): List<Type> {
        val casted = (value as? Array<Type>)
        if (casted != null) {
            return casted.map { e -> e?.let { arrayDelegate.delegate.valueFromDB(it) } as Type }
        }
        return arrayDelegate.valueFromDB(value)
    }
}
But now it crashes on receiver side with java.lang.ClassCastException: class java.util.ArrayList cannot be cast to class [Ljava.util.List; (java.util.ArrayList and [Ljava.util.List; are in module java.base of loader 'bootstrap')
I managed to get it working with custom ListColumnType:
Copy code
class ArrayLiteral<T : Any>(private val expressions: List<ExpressionWithColumnType<T>>, columnType: ColumnType<T>) :
    Function<List<T>>(ListColumnType(columnType)) {
    override fun toQueryBuilder(queryBuilder: QueryBuilder) {
        queryBuilder.append("array[")
        expressions.forEachIndexed { index, expression ->
            queryBuilder.append(expression)
            if (index != expressions.lastIndex)
                queryBuilder.append(",")
        }
        queryBuilder.append("]")
    }
}

fun <T : Any> arrayLiteral(vararg expressions: ExpressionWithColumnType<T>,columnType: ColumnType<T>): ArrayLiteral<T> {
    return ArrayLiteral(expressions.toList(), columnType)
}

class ListColumnType<Type>(delegate: ColumnType<Type & Any>) : ColumnType<List<Type>>() {
    val arrayDelegate = ArrayColumnType(delegate)
    override fun sqlType(): String = arrayDelegate.sqlType()

    override fun valueFromDB(value: Any): List<Type> {
        val casted = (value as? Array<Type>)
        if (casted != null) {
            val asList = casted.asList()
            return asList
        }
        return arrayDelegate.valueFromDB(value)
    }
}
Is this possible to add check if value is java.util.Array in ArrayColumnType?
c
Hi @Rafał Kuźmiński If I'm understanding the end-goal correctly, does
array [ARRAY_AGG(...), ARRAY_AGG(...)]
result in essentially a multi-dimensional array? If so, Exposed is currently only set up for single-dimension arrays. Refactoring
ArrayColumnType
to support more than 1D arrays is currently in progress: EXPOSED-359
r
I see. Well my custom ListColumnType worked perfectly, so I'll wait for official solution