Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: EXPOSED-695 DDL for unnamed check constraints fails when table has schema name #2368

Merged
merged 1 commit into from
Jan 23, 2025
Merged
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
30 changes: 13 additions & 17 deletions exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt
Original file line number Diff line number Diff line change
Expand Up @@ -474,10 +474,16 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {
* @see org.jetbrains.exposed.sql.vendors.VendorDialect.metadataMatchesTable
*/
internal val tableNameWithoutSchemeSanitized: String
get() = tableNameWithoutScheme
.replace("\"", "")
.replace("'", "")
.replace("`", "")
get() = tableNameWithoutScheme.unquoted()

/**
* Returns the full table name with all quotes removed. If the table name includes a dot-prefixed schema name,
* the full name will be returned with '_' replacing the dot characters.
*/
private val tableNameWithSchemaSanitized: String
get() = tableName.unquoted().replace('.', '_')

private fun String.unquoted(): String = replace("\"", "").replace("'", "").replace("`", "")

private val _columns = mutableListOf<Column<*>>()

Expand Down Expand Up @@ -518,20 +524,10 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {
private val checkConstraints = mutableListOf<Pair<String, Op<Boolean>>>()

private val generatedUnsignedCheckPrefix
get() = "chk_${
tableName.replace("\"", "")
.replace("'", "")
.replace("`", "")
.replace('.', '_')
}_unsigned_"
get() = "chk_${tableNameWithSchemaSanitized}_unsigned_"

private val generatedSignedCheckPrefix
get() = "chk_${
tableName.replace("\"", "")
.replace("'", "")
.replace("`", "")
.replace('.', '_')
}_signed_"
get() = "chk_${tableNameWithSchemaSanitized}_signed_"

/**
* Returns the table name in proper case.
Expand Down Expand Up @@ -1755,7 +1751,7 @@ open class Table(name: String = "") : ColumnSet(), DdlAware {
}
}.ifEmpty { null }
filteredChecks?.mapIndexed { index, (name, op) ->
val resolvedName = name.ifBlank { "check_${tableName}_$index" }
val resolvedName = name.ifBlank { "check_${tableNameWithSchemaSanitized}_$index" }
CheckConstraint.from(this@Table, resolvedName, op).checkPart
}?.joinTo(this, prefix = ", ")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package org.jetbrains.exposed.sql.tests.shared

import org.jetbrains.exposed.sql.Schema
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.tests.DatabaseTestsBase
import org.jetbrains.exposed.sql.tests.TestDB
import org.jetbrains.exposed.sql.transactions.TransactionManager
Expand Down Expand Up @@ -174,4 +178,54 @@ class SchemaTests : DatabaseTestsBase() {
SchemaUtils.dropSchema(schema)
}
}

@Test
fun testCheckConstraintsNamedWithoutSchemaPrefix() {
val schemaName = "my_schema"
val tester = object : Table("$schemaName.test_table") {
val amount1 = ushort("amount1") // implicit column check constraint
val amount2 = integer("amount2").check { it lessEq 100 } // explicit column check constraint
init {
check { (amount1 less 100.toUShort()) and (amount2 greater 50) } // explicit table check constraint
}
}

// SQLite does not recognize creation of schema other than the attached database.
// Check constraints only introduced in MySQL v8+.
withDb(excludeSettings = listOf(TestDB.SQLITE, TestDB.MYSQL_V5)) { testDb ->
val schema = prepareSchemaForTest(schemaName)
try {
SchemaUtils.createSchema(schema)
SchemaUtils.create(tester)

tester.insert {
it[amount1] = 99u
it[amount2] = 56
}

assertEquals(1L, tester.selectAll().count())

assertFailAndRollback("Column check constraints") {
tester.insert {
it[amount1] = 99999.toUShort()
it[amount2] = Int.MAX_VALUE + 1
}
}

assertFailAndRollback("Table check constraints") {
tester.insert {
it[amount1] = 101u
it[amount2] = 49
}
}
} finally {
if (testDb == TestDB.SQLSERVER) {
SchemaUtils.drop(tester)
SchemaUtils.dropSchema(schema)
} else {
SchemaUtils.dropSchema(schema, cascade = true)
}
}
}
}
}
Loading