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-278 Invalid Oracle statement when adding a new column that is used in a primary key #2259

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
17 changes: 8 additions & 9 deletions exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Column.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@ package org.jetbrains.exposed.sql

import org.jetbrains.exposed.exceptions.throwUnsupportedException
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.vendors.H2Dialect
import org.jetbrains.exposed.sql.vendors.MysqlDialect
import org.jetbrains.exposed.sql.vendors.SQLServerDialect
import org.jetbrains.exposed.sql.vendors.SQLiteDialect
import org.jetbrains.exposed.sql.vendors.currentDialect
import org.jetbrains.exposed.sql.vendors.inProperCase
import java.util.*
import org.jetbrains.exposed.sql.vendors.*

private val comparator: Comparator<Column<*>> = compareBy({ it.table.tableName }, { it.name })

Expand Down Expand Up @@ -76,15 +70,20 @@ class Column<T>(
override fun createStatement(): List<String> {
val alterTablePrefix = "ALTER TABLE ${TransactionManager.current().identity(table)} ADD"
val isH2withCustomPKConstraint = currentDialect is H2Dialect && isLastColumnInPK
val isOracle = currentDialect is OracleDialect
val columnDefinition = when {
isPrimaryConstraintWillBeDefined && isLastColumnInPK && !isH2withCustomPKConstraint ->
isPrimaryConstraintWillBeDefined && isLastColumnInPK && !isH2withCustomPKConstraint && !isOracle ->
descriptionDdl(false) + ", ADD ${table.primaryKeyConstraint()}"

isH2withCustomPKConstraint -> descriptionDdl(true)
else -> descriptionDdl(false)
}

val addConstr = if (isH2withCustomPKConstraint) "$alterTablePrefix ${table.primaryKeyConstraint()}" else null
val addConstr = if (isH2withCustomPKConstraint || (isOracle && isPrimaryConstraintWillBeDefined)) {
"$alterTablePrefix ${table.primaryKeyConstraint()}"
} else {
null
}
return listOfNotNull("$alterTablePrefix $columnDefinition", addConstr)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.tests.DatabaseTestsBase
import org.jetbrains.exposed.sql.tests.TestDB
import org.jetbrains.exposed.sql.tests.currentDialectTest
import org.jetbrains.exposed.sql.tests.inProperCase
import org.jetbrains.exposed.sql.tests.shared.Category
import org.jetbrains.exposed.sql.tests.shared.Item
import org.jetbrains.exposed.sql.tests.shared.assertEqualCollections
import org.jetbrains.exposed.sql.tests.shared.assertEquals
import org.jetbrains.exposed.sql.tests.shared.assertTrue
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.vendors.SQLiteDialect
import org.junit.Test
import java.util.*
import kotlin.test.assertFails
Expand Down Expand Up @@ -204,28 +202,8 @@ class CreateTableTests : DatabaseTestsBase() {
}

@Test
fun addCompositePrimaryKeyToTableH2Test() {
withDb(TestDB.H2_V2) {
val tableName = Person.tableName
val tableProperName = tableName.inProperCase()
val id1ProperName = Person.id1.name.inProperCase()
val ddlId1 = Person.id1.ddl
val id2ProperName = Person.id2.name.inProperCase()
val ddlId2 = Person.id2.ddl
val pkConstraintName = Person.primaryKey.name

assertEquals(1, ddlId1.size)
assertEquals("ALTER TABLE $tableProperName ADD ${Person.id1.descriptionDdl(false)}", ddlId1.first())

assertEquals(2, ddlId2.size)
assertEquals("ALTER TABLE $tableProperName ADD $id2ProperName ${Person.id2.columnType.sqlType()}", ddlId2.first())
assertEquals("ALTER TABLE $tableProperName ADD CONSTRAINT $pkConstraintName PRIMARY KEY ($id1ProperName, $id2ProperName)", Person.id2.ddl.last())
}
}

@Test
fun addCompositePrimaryKeyToTableNotH2Test() {
withTables(excludeSettings = TestDB.ALL_H2, tables = arrayOf(Person)) {
fun addCompositePrimaryKeyToTableTest() {
withDb { testDb ->
val tableName = Person.tableName
val tableProperName = tableName.inProperCase()
val id1ProperName = Person.id1.name.inProperCase()
Expand All @@ -237,29 +215,45 @@ class CreateTableTests : DatabaseTestsBase() {
assertEquals(1, ddlId1.size)
assertEquals("ALTER TABLE $tableProperName ADD ${Person.id1.descriptionDdl(false)}", ddlId1.first())

assertEquals(1, ddlId2.size)
assertEquals(
"ALTER TABLE $tableProperName ADD ${Person.id2.descriptionDdl(false)}, ADD CONSTRAINT $pkConstraintName PRIMARY KEY ($id1ProperName, $id2ProperName)",
ddlId2.first()
)
when (testDb) {
in TestDB.ALL_H2, TestDB.ORACLE -> {
assertEquals(2, ddlId2.size)
assertEquals("ALTER TABLE $tableProperName ADD $id2ProperName ${Person.id2.columnType.sqlType()}", ddlId2.first())
assertEquals("ALTER TABLE $tableProperName ADD CONSTRAINT $pkConstraintName PRIMARY KEY ($id1ProperName, $id2ProperName)", Person.id2.ddl.last())
}
else -> {
assertEquals(1, ddlId2.size)
assertEquals(
"ALTER TABLE $tableProperName ADD ${Person.id2.descriptionDdl(false)}, " +
"ADD CONSTRAINT $pkConstraintName PRIMARY KEY ($id1ProperName, $id2ProperName)",
ddlId2.first()
)
}
}
}
}

@Test
fun addOneColumnPrimaryKeyToTableNotH2Test() {
withTables(excludeSettings = TestDB.ALL_H2, tables = arrayOf(Book)) {
fun addOneColumnPrimaryKeyToTableTest() {
withTables(Book) { testDb ->
val tableProperName = Book.tableName.inProperCase()
val pkConstraintName = Book.primaryKey.name
val id1ProperName = Book.id.name.inProperCase()
val ddlId1 = Book.id.ddl

if (currentDialectTest !is SQLiteDialect) {
assertEquals(
when (testDb) {
TestDB.SQLITE -> assertEquals("ALTER TABLE $tableProperName ADD ${Book.id.descriptionDdl(false)}", ddlId1.first())
in TestDB.ALL_H2, TestDB.ORACLE -> assertEqualCollections(
listOf(
"ALTER TABLE $tableProperName ADD ${Book.id.descriptionDdl(false)}",
"ALTER TABLE $tableProperName ADD CONSTRAINT $pkConstraintName PRIMARY KEY ($id1ProperName)"
),
ddlId1
)
else -> assertEquals(
"ALTER TABLE $tableProperName ADD ${Book.id.descriptionDdl(false)}, ADD CONSTRAINT $pkConstraintName PRIMARY KEY ($id1ProperName)",
ddlId1.first()
)
} else {
assertEquals("ALTER TABLE $tableProperName ADD ${Book.id.descriptionDdl(false)}", ddlId1.first())
}
}
}
Expand Down
Loading