Skip to content

Commit

Permalink
fix!: Byte column allows out-of-range values
Browse files Browse the repository at this point in the history
  • Loading branch information
joc-a committed Sep 11, 2024
1 parent cf8c71a commit 8149891
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 4 deletions.
11 changes: 8 additions & 3 deletions exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,9 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {
// Numeric columns

/** Creates a numeric column, with the specified [name], for storing 1-byte integers. */
fun byte(name: String): Column<Byte> = registerColumn(name, ByteColumnType())
fun byte(name: String): Column<Byte> = registerColumn(name, ByteColumnType()).apply {
check("${generatedSignedCheckPrefix}byte_$name") { it.between(Byte.MIN_VALUE, Byte.MAX_VALUE) }
}

/** Creates a numeric column, with the specified [name], for storing 1-byte unsigned integers.
*
Expand Down Expand Up @@ -1651,14 +1653,17 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {
}
is SQLServerDialect -> checkConstraints.filterNot { (name, _) ->
name.startsWith("${generatedUnsignedCheckPrefix}byte_") ||
name.startsWith(generatedSignedCheckPrefix)
name.startsWith("${generatedSignedCheckPrefix}short")
}
is PostgreSQLDialect -> checkConstraints.filterNot { (name, _) ->
name.startsWith(generatedSignedCheckPrefix)
name.startsWith("${generatedSignedCheckPrefix}short")
}
is H2Dialect -> {
when (dialect.h2Mode) {
H2Dialect.H2CompatibilityMode.Oracle -> checkConstraints
H2Dialect.H2CompatibilityMode.PostgreSQL -> checkConstraints.filterNot { (name, _) ->
name.startsWith("${generatedSignedCheckPrefix}short")
}
else -> checkConstraints.filterNot { (name, _) ->
name.startsWith(generatedSignedCheckPrefix)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import java.util.*

@Suppress("TooManyFunctions")
internal object OracleDataTypeProvider : DataTypeProvider() {
override fun byteType(): String = "SMALLINT"
override fun byteType(): String = "NUMBER(3)"
override fun ubyteType(): String = "NUMBER(4)"
override fun shortType(): String = "NUMBER(5)"
override fun ushortType(): String = "NUMBER(6)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.jetbrains.exposed.sql.transactions.TransactionManager
import java.util.*

internal object SQLServerDataTypeProvider : DataTypeProvider() {
override fun byteType(): String = "SMALLINT"
override fun ubyteType(): String {
return if ((currentDialect as? H2Dialect)?.h2Mode == H2Dialect.H2CompatibilityMode.SQLServer) {
"SMALLINT"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,41 @@ class NumericColumnTypesTests : DatabaseTestsBase() {
}
}
}

@Test
fun testByteAcceptsOnlyAllowedRange() {
val testTable = object : Table("test_table") {
val byte = byte("byte")
}

withTables(testTable) { testDb ->
val columnName = testTable.byte.nameInDatabaseCase()
val ddlEnding = when (testDb) {
in TestDB.ALL_POSTGRES, in TestDB.ALL_ORACLE_LIKE,
TestDB.H2_V2_PSQL, TestDB.SQLITE, TestDB.SQLSERVER -> "CHECK ($columnName BETWEEN ${Byte.MIN_VALUE} and ${Byte.MAX_VALUE}))"
else -> "($columnName ${testTable.byte.columnType} NOT NULL)"
}
assertTrue(testTable.ddl.single().endsWith(ddlEnding, ignoreCase = true))

// exec("INSERT INTO test_table (byte) VALUES (-128)")

testTable.insert { it[byte] = Byte.MIN_VALUE }
testTable.insert { it[byte] = Byte.MAX_VALUE }
assertEquals(2, testTable.select(testTable.byte).count())

val tableName = testTable.nameInDatabaseCase()
assertFailAndRollback(
message = "CHECK constraint violation or out-of-range error for MySQL, MariaDB, and H2 (except for H2_V2_ORACLE and H2_V2_PSQL)"
) {
val outOfRangeValue = Byte.MIN_VALUE - 1
exec("INSERT INTO $tableName ($columnName) VALUES ($outOfRangeValue)")
}
assertFailAndRollback(
message = "CHECK constraint violation or out-of-range error for MySQL, MariaDB, and H2 (except for H2_V2_ORACLE and H2_V2_PSQL)"
) {
val outOfRangeValue = Byte.MAX_VALUE + 1
exec("INSERT INTO $tableName ($columnName) VALUES ($outOfRangeValue)")
}
}
}
}

0 comments on commit 8149891

Please sign in to comment.