diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt index c7228e8734..f16d3775f0 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt @@ -271,8 +271,11 @@ open class TextColumnType(collate: String? = null) : StringColumnType(collate) { } } -class BinaryColumnType(val length: Int) : ColumnType() { - override fun sqlType(): String = currentDialect.dataTypeProvider.binaryType(length) +/** + * Implements the binary column type. + */ +open class BasicBinaryColumnType : ColumnType() { + override fun sqlType(): String = currentDialect.dataTypeProvider.binaryType() override fun valueFromDB(value: Any): Any { if (value is Blob) { @@ -287,6 +290,15 @@ class BinaryColumnType(val length: Int) : ColumnType() { } } +/** + * Implements the binary column type. + * + * @param length The maximum amount of bytes to store + */ +class BinaryColumnType(val length: Int) : BasicBinaryColumnType() { + override fun sqlType(): String = currentDialect.dataTypeProvider.binaryType(length) +} + class BlobColumnType : ColumnType() { override fun sqlType(): String = currentDialect.dataTypeProvider.blobType() diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt index 92068c8d9c..c265723b16 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt @@ -398,11 +398,24 @@ open class Table(name: String = ""): ColumnSet(), DdlAware { /** * A binary column to store an array of bytes. * + * @sample org.jetbrains.exposed.sql.tests.shared.DDLTests.testBinary + * * @param name The column name - * @param length The maximum amount of bytes to store + * @param length The maximum amount of bytes to store, this parameter is necessary only in H2, SQLite, MySQL, + * MariaDB, and SQL Server dialects. */ fun binary(name: String, length: Int): Column = registerColumn(name, BinaryColumnType(length)) + /** + * A binary column to store an array of bytes. This function is supported only by Oracle and PostgeSQL dialects. + * If you are using another dialect, please use instead the [binary] function by adding the length parameter. + * + * @sample org.jetbrains.exposed.sql.tests.shared.DDLTests.testBinaryWithoutLength + * + * @param name The column name + */ + fun binary(name: String): Column = registerColumn(name, BasicBinaryColumnType()) + /** * A uuid column to store a UUID. * diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Default.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Default.kt index 38bd6589a0..95a777a260 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Default.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Default.kt @@ -9,7 +9,7 @@ import java.util.concurrent.ConcurrentHashMap internal typealias TableAndColumnName = Pair -open class DataTypeProvider { +abstract class DataTypeProvider { open fun integerAutoincType() = "INT AUTO_INCREMENT" open fun integerType() = "INT" @@ -30,6 +30,8 @@ open class DataTypeProvider { open fun binaryType(length: Int): String = "VARBINARY($length)" + open abstract fun binaryType(): String + open fun booleanType(): String = "BOOLEAN" open fun booleanToStatementString(bool: Boolean) = bool.toString() diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/H2.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/H2.kt index 36a0dd8b04..7ea83e8bf9 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/H2.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/H2.kt @@ -11,6 +11,11 @@ import java.util.* internal object H2DataTypeProvider : DataTypeProvider() { override fun uuidType(): String = "UUID" + + override fun binaryType(): String { + exposedLogger.error("The length of the Binary column is missing.") + error("The length of the Binary column is missing.") + } } private val Transaction.isMySQLMode: Boolean diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Mysql.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Mysql.kt index c407454ea8..24acbe7809 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Mysql.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/Mysql.kt @@ -7,6 +7,11 @@ import java.math.BigDecimal internal object MysqlDataTypeProvider : DataTypeProvider() { override fun dateTimeType(): String = if ((currentDialect as MysqlDialect).isFractionDateTimeSupported()) "DATETIME(6)" else "DATETIME" + + override fun binaryType(): String { + exposedLogger.error("The length of the Binary column is missing.") + error("The length of the Binary column is missing.") + } } internal open class MysqlFunctionProvider : FunctionProvider() { diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/OracleDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/OracleDialect.kt index b78c5c29b4..eb8df10480 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/OracleDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/OracleDialect.kt @@ -22,7 +22,12 @@ internal object OracleDataTypeProvider : DataTypeProvider() { override fun blobType() = "BLOB" - override fun binaryType(length: Int): String = "BLOB" + override fun binaryType(length: Int): String { + exposedLogger.warn("The length of the binary column is not required.") + return binaryType() + } + + override fun binaryType(): String = "BLOB" override fun booleanType() = "CHAR(1)" diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/PostgreSQL.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/PostgreSQL.kt index e3fd730e9c..abb4b50fb6 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/PostgreSQL.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/PostgreSQL.kt @@ -17,7 +17,12 @@ internal object PostgreSQLDataTypeProvider : DataTypeProvider() { override fun blobType(): String = "bytea" - override fun binaryType(length: Int): String = "bytea" + override fun binaryType(length: Int): String { + exposedLogger.warn("The length of the binary column is not required.") + return binaryType() + } + + override fun binaryType(): String = "bytea" override fun uuidToDB(value: UUID): Any = value diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLServerDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLServerDialect.kt index e255366276..63f32011af 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLServerDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLServerDialect.kt @@ -23,6 +23,11 @@ internal object SQLServerDataTypeProvider : DataTypeProvider() { override fun uuidType() = "uniqueidentifier" override fun uuidToDB(value: UUID) = value.toString() + + override fun binaryType(): String { + exposedLogger.error("The length of the Binary column is missing.") + error("The length of the Binary column is missing.") + } } internal object SQLServerFunctionProvider : FunctionProvider() { diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt index ca6268e3e2..64c1788639 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SQLiteDialect.kt @@ -11,6 +11,11 @@ internal object SQLiteDataTypeProvider : DataTypeProvider() { override fun booleanToStatementString(bool: Boolean) = if (bool) "1" else "0" override fun dateTimeType(): String = "NUMERIC" override val blobAsStream: Boolean = true + + override fun binaryType(): String { + exposedLogger.error("The length of the Binary column is missing.") + error("The length of the Binary column is missing.") + } } internal object SQLiteFunctionProvider : FunctionProvider() { diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/DDLTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/DDLTests.kt index 04246193f7..59a4bd1d93 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/DDLTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/DDLTests.kt @@ -434,8 +434,42 @@ class DDLTests : DatabaseTestsBase() { } } + @Test + fun testBinaryWithoutLength() { + val tableWithBinary = object : Table("TableWithBinary") { + val binaryColumn = binary("binaryColumn") + } + + fun SizedIterable.readAsString() = map { String(it[tableWithBinary.binaryColumn]) } + + withDb(listOf(TestDB.ORACLE,TestDB.POSTGRESQL)) { + val exposedBytes = "Exposed".toByteArray() + val kotlinBytes = "Kotlin".toByteArray() + + SchemaUtils.create(tableWithBinary) + + tableWithBinary.insert { + it[tableWithBinary.binaryColumn] = exposedBytes + } + val insertedExposed = tableWithBinary.selectAll().readAsString().single() + + assertEquals("Exposed", insertedExposed) + + tableWithBinary.insert { + it[tableWithBinary.binaryColumn] = kotlinBytes + } + + assertEqualCollections(tableWithBinary.selectAll().readAsString(), "Exposed", "Kotlin") + + val insertedKotlin = tableWithBinary.select { tableWithBinary.binaryColumn eq kotlinBytes }.readAsString() + assertEqualCollections(insertedKotlin, "Kotlin") + + SchemaUtils.drop(tableWithBinary) + } + } + @Test fun testBinary() { - val t = object : Table() { + val t = object : Table("t") { val binary = binary("bytes", 10) val byteCol = binary("byteCol", 1).clientDefault { byteArrayOf(0) } }