Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.jetbrains.exposed.v1.core.statements.api.RowApi
import org.jetbrains.exposed.v1.core.vendors.H2Dialect
import org.jetbrains.exposed.v1.core.vendors.PostgreSQLDialect
import org.jetbrains.exposed.v1.core.vendors.currentDialect
import java.sql.Clob

/**
* Column for storing JSON data, either in non-binary text format or the vendor's default JSON type format.
Expand Down Expand Up @@ -73,14 +74,18 @@ open class JsonColumnType<T : Any>(
}

override fun readObject(rs: RowApi, index: Int): Any? {
return if (currentDialect is PostgreSQLDialect) {
rs.getString(index)
} else {
super.readObject(rs, index)
if (currentDialect is PostgreSQLDialect) return rs.getString(index)

return when (val value = super.readObject(rs, index)) {
is Clob -> value.readText()
else -> value
}
}
}

/** Reads this large object completely, releasing the reader it was streamed through. */
private fun Clob.readText(): String = characterStream.use { it.readText() }

/**
* Creates a column, with the specified [name], for storing JSON data.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import org.jetbrains.exposed.v1.core.vendors.PostgreSQLDialect
import org.jetbrains.exposed.v1.core.vendors.SQLServerDialect
import org.jetbrains.exposed.v1.exceptions.UnsupportedByDialectException
import org.jetbrains.exposed.v1.jdbc.*
import org.jetbrains.exposed.v1.jdbc.transactions.inTopLevelTransaction
import org.jetbrains.exposed.v1.tests.DatabaseTestsBase
import org.jetbrains.exposed.v1.tests.MISSING_R2DBC_TEST
import org.jetbrains.exposed.v1.tests.TestDB
Expand Down Expand Up @@ -492,4 +493,49 @@ class JsonColumnTests : DatabaseTestsBase() {
assertEquals(newUser, result[infoAsJson])
}
}

private val textIsNotClob = TestDB.ALL - TestDB.ALL_ORACLE_LIKE

@Test
fun testJsonStoredAsClob() {
val textTester = object : IntIdTable("json_large_text_tester") {
val payload = text("payload")
}
val jsonTester = object : IntIdTable("json_large_text_tester") {
val payload = json<User>("payload", Json.Default)
}

val newUser = User("Pro", "Alpha")
var writtenAsText: EntityID<Int>? = null
var writtenAsJson: EntityID<Int>? = null

withTables(excludeSettings = textIsNotClob, textTester) {
val columnDdl = textTester.payload.descriptionDdl()
kotlin.test.assertTrue(
columnDdl.contains("CLOB"),
"The column must be created as a CLOB for this test to exercise anything, but was: $columnDdl"
)

inTopLevelTransaction {
maxAttempts = 1
val textId = textTester.insertAndGetId { it[payload] = Json.encodeToString(newUser) }
val jsonId = jsonTester.insertAndGetId { it[payload] = newUser }
writtenAsText = textId
writtenAsJson = jsonId

for (id in listOf(textId, jsonId)) {
val row = jsonTester.selectAll().where { jsonTester.id eq id }.single()
assertEquals(newUser, row[jsonTester.payload])
}
}

inTopLevelTransaction {
maxAttempts = 1
for (id in listOf(assertNotNull(writtenAsText), assertNotNull(writtenAsJson))) {
val row = jsonTester.selectAll().where { jsonTester.id eq id }.single()
assertEquals(newUser, row[jsonTester.payload])
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import org.jetbrains.exposed.v1.r2dbc.tests.shared.assertEqualLists
import org.jetbrains.exposed.v1.r2dbc.tests.shared.assertEquals
import org.jetbrains.exposed.v1.r2dbc.tests.shared.assertTrue
import org.jetbrains.exposed.v1.r2dbc.tests.shared.expectException
import org.jetbrains.exposed.v1.r2dbc.transactions.inTopLevelSuspendTransaction
import org.junit.jupiter.api.Test
import kotlin.test.assertContentEquals
import kotlin.test.assertNotNull
Expand Down Expand Up @@ -464,4 +465,47 @@ class JsonColumnTests : R2dbcDatabaseTestsBase() {
assertEquals(newUser, result[infoAsJson])
}
}

@Test
fun testJsonStoredAsClob() {
val textTester = object : IntIdTable("json_large_text_tester") {
val payload = text("payload")
}
val jsonTester = object : IntIdTable("json_large_text_tester") {
val payload = json<User>("payload", Json.Default)
}

val newUser = User("Pro", "Alpha")
var writtenAsText: EntityID<Int>? = null
var writtenAsJson: EntityID<Int>? = null

withTables(excludeSettings = TestDB.ALL - TestDB.ALL_ORACLE_LIKE, textTester) {
val columnDdl = textTester.payload.descriptionDdl()
kotlin.test.assertTrue(
columnDdl.contains("CLOB"),
"The column must be created as a CLOB for this test to exercise anything, but was: $columnDdl"
)

inTopLevelSuspendTransaction {
maxAttempts = 1
val textId = textTester.insertAndGetId { it[payload] = Json.encodeToString(newUser) }
val jsonId = jsonTester.insertAndGetId { it[payload] = newUser }
writtenAsText = textId
writtenAsJson = jsonId

for (id in listOf(textId, jsonId)) {
val row = jsonTester.selectAll().where { jsonTester.id eq id }.single()
assertEquals(newUser, row[jsonTester.payload])
}
}

inTopLevelSuspendTransaction {
maxAttempts = 1
for (id in listOf(assertNotNull(writtenAsText), assertNotNull(writtenAsJson))) {
val row = jsonTester.selectAll().where { jsonTester.id eq id }.single()
assertEquals(newUser, row[jsonTester.payload])
}
}
}
}
}
Loading