Skip to content

Commit f7026ef

Browse files
committed
Fix for EXPOSED-86, allowing blobs with streams of unknown size
1 parent fa38a77 commit f7026ef

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcPreparedStatementImpl.kt

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import org.jetbrains.exposed.sql.BinaryColumnType
44
import org.jetbrains.exposed.sql.BlobColumnType
55
import org.jetbrains.exposed.sql.IColumnType
66
import org.jetbrains.exposed.sql.statements.api.PreparedStatementApi
7+
import java.io.ByteArrayInputStream
8+
import java.io.FileInputStream
79
import java.io.InputStream
810
import java.sql.PreparedStatement
911
import java.sql.ResultSet
12+
import java.sql.SQLFeatureNotSupportedException
1013
import java.sql.Types
1114

1215
class JdbcPreparedStatementImpl(val statement: PreparedStatement, val wasGeneratedKeysRequested: Boolean) : PreparedStatementApi {
@@ -15,7 +18,9 @@ class JdbcPreparedStatementImpl(val statement: PreparedStatement, val wasGenerat
1518

1619
override var fetchSize: Int?
1720
get() = statement.fetchSize
18-
set(value) { value?.let { statement.fetchSize = value } }
21+
set(value) {
22+
value?.let { statement.fetchSize = value }
23+
}
1924

2025
override fun addBatch() {
2126
statement.addBatch()
@@ -38,7 +43,25 @@ class JdbcPreparedStatementImpl(val statement: PreparedStatement, val wasGenerat
3843
}
3944

4045
override fun setInputStream(index: Int, inputStream: InputStream) {
41-
statement.setBinaryStream(index, inputStream, inputStream.available())
46+
try {
47+
when {
48+
// streams with known length where available matches the actual length
49+
inputStream is ByteArrayInputStream ->
50+
statement.setBinaryStream(index, inputStream, inputStream.available())
51+
52+
// FileInputStream.available() returns returns Int.MAX_VALUE
53+
// if the underlying file is larger than 2GB
54+
inputStream is FileInputStream && inputStream.available() < Int.MAX_VALUE ->
55+
statement.setBinaryStream(index, inputStream, inputStream.available())
56+
57+
// default handling for unknown length
58+
else -> statement.setBinaryStream(index, inputStream)
59+
60+
}
61+
} catch (e: SQLFeatureNotSupportedException) {
62+
// fallback to bytes
63+
statement.setBytes(index, inputStream.readAllBytes())
64+
}
4265
}
4366

4467
override fun closeIfPossible() {

exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/DDLTests.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import org.jetbrains.exposed.sql.vendors.SQLServerDialect
2222
import org.jetbrains.exposed.sql.vendors.SQLiteDialect
2323
import org.junit.Test
2424
import org.postgresql.util.PGobject
25+
import java.io.ByteArrayInputStream
26+
import java.io.SequenceInputStream
2527
import java.util.*
2628
import kotlin.random.Random
2729
import kotlin.test.assertNotNull
@@ -454,7 +456,12 @@ class DDLTests : DatabaseTestsBase() {
454456
val shortBytes = "Hello there!".toByteArray()
455457
val longBytes = Random.nextBytes(1024)
456458
val shortBlob = ExposedBlob(shortBytes)
457-
val longBlob = ExposedBlob(longBytes)
459+
val longBlob = ExposedBlob(
460+
inputStream = SequenceInputStream(
461+
ByteArrayInputStream(longBytes, 0, 512),
462+
ByteArrayInputStream(longBytes, 512, 512)
463+
)
464+
)
458465
// if (currentDialectTest.dataTypeProvider.blobAsStream) {
459466
// SerialBlob(bytes)
460467
// } else connection.createBlob().apply {

0 commit comments

Comments
 (0)