mirror of
https://github.com/jlengrand/Exposed.git
synced 2026-03-10 08:11:20 +00:00
Adding the feature of defining the primarykey constraint name (#725)
Minor code improvements
This commit is contained in:
@@ -39,7 +39,8 @@ abstract class IdTable<T:Comparable<T>>(name: String = ""): Table(name) {
|
||||
* @param columnName name for a primary key, "id" by default
|
||||
*/
|
||||
open class IntIdTable(name: String = "", columnName: String = "id") : IdTable<Int>(name) {
|
||||
override val id: Column<EntityID<Int>> = integer(columnName).autoIncrement().primaryKey().entityId()
|
||||
override val id: Column<EntityID<Int>> = integer(columnName).autoIncrement().entityId()
|
||||
override val primaryKey = PrimaryKey(id)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +50,8 @@ open class IntIdTable(name: String = "", columnName: String = "id") : IdTable<In
|
||||
* @param columnName name for a primary key, "id" by default
|
||||
*/
|
||||
open class LongIdTable(name: String = "", columnName: String = "id") : IdTable<Long>(name) {
|
||||
override val id: Column<EntityID<Long>> = long(columnName).autoIncrement().primaryKey().entityId()
|
||||
override val id: Column<EntityID<Long>> = long(columnName).autoIncrement().entityId()
|
||||
override val primaryKey = PrimaryKey(id)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +65,8 @@ open class LongIdTable(name: String = "", columnName: String = "id") : IdTable<L
|
||||
* @param columnName name for a primary key, "id" by default
|
||||
*/
|
||||
open class UUIDTable(name: String = "", columnName: String = "id") : IdTable<UUID>(name) {
|
||||
override val id: Column<EntityID<UUID>> = uuid(columnName).primaryKey()
|
||||
override val id: Column<EntityID<UUID>> = uuid(columnName)
|
||||
.autoGenerate()
|
||||
.entityId()
|
||||
override val primaryKey = PrimaryKey(id)
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ class Column<T>(val table: Table, val name: String, override val columnType: ICo
|
||||
|
||||
override fun createStatement(): List<String> {
|
||||
val alterTablePrefix = "ALTER TABLE ${TransactionManager.current().identity(table)} ADD"
|
||||
val isLastColumnInPK = table.primaryKey.columns.lastOrNull() == this
|
||||
val isLastColumnInPK = table.primaryKey?.columns?.last() == this
|
||||
val columnDefinition = when {
|
||||
isOneColumnPK() && table.isCustomPKNameDefined && isLastColumnInPK && currentDialect !is H2Dialect -> descriptionDdl() + ", ADD ${table.primaryKeyConstraint()}"
|
||||
isOneColumnPK() && table.isCustomPKNameDefined() && isLastColumnInPK && currentDialect !is H2Dialect -> descriptionDdl() + ", ADD ${table.primaryKeyConstraint()}"
|
||||
isOneColumnPK() && (currentDialect is H2Dialect || currentDialect is SQLiteDialect) -> descriptionDdl().removeSuffix(" PRIMARY KEY")
|
||||
!isOneColumnPK() && isLastColumnInPK && currentDialect !is H2Dialect -> descriptionDdl() + ", ADD ${table.primaryKeyConstraint()}"
|
||||
else -> descriptionDdl()
|
||||
@@ -55,19 +55,19 @@ class Column<T>(val table: Table, val name: String, override val columnType: ICo
|
||||
|
||||
override fun dropStatement() = listOf(TransactionManager.current().let {"ALTER TABLE ${it.identity(table)} DROP COLUMN ${it.identity(this)}" })
|
||||
|
||||
internal fun isOneColumnPK() = table.primaryKey.columns.singleOrNull() == this
|
||||
internal fun isOneColumnPK() = table.primaryKey?.columns?.singleOrNull() == this
|
||||
|
||||
fun descriptionDdl(): String = buildString {
|
||||
val tr = TransactionManager.current()
|
||||
append(tr.identity(this@Column))
|
||||
append(" ")
|
||||
val isPKColumn = table.primaryKey.columns.contains(this@Column)
|
||||
val isPKColumn = table.primaryKey?.columns?.contains(this@Column) == true
|
||||
val colType = columnType
|
||||
val isSQLiteAutoIncColumn = currentDialect is SQLiteDialect && colType.isAutoInc
|
||||
|
||||
when {
|
||||
!isPKColumn && isSQLiteAutoIncColumn -> tr.throwUnsupportedException("Auto-increment could be applied only to primary key column")
|
||||
isSQLiteAutoIncColumn && !isOneColumnPK() && table.primaryKey.columns.isNotEmpty() -> append(currentDialect.dataTypeProvider.integerType())
|
||||
isSQLiteAutoIncColumn && !isOneColumnPK() && table.primaryKey != null -> append(currentDialect.dataTypeProvider.integerType())
|
||||
else -> append(colType.sqlType())
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ class Column<T>(val table: Table, val name: String, override val columnType: ICo
|
||||
append(" NOT NULL")
|
||||
}
|
||||
|
||||
if (!table.isCustomPKNameDefined && isOneColumnPK() && !isSQLiteAutoIncColumn) {
|
||||
if (!table.isCustomPKNameDefined() && isOneColumnPK() && !isSQLiteAutoIncColumn) {
|
||||
append(" PRIMARY KEY")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,37 +236,27 @@ open class Table(name: String = ""): ColumnSet(), DdlAware {
|
||||
return newColumn
|
||||
}
|
||||
|
||||
var isCustomPKNameDefined = false
|
||||
internal fun isCustomPKNameDefined() : Boolean = primaryKey?.let { it.name != "pk_$tableName" } == true
|
||||
|
||||
/**
|
||||
* The primary key class.
|
||||
*/
|
||||
inner class PrimaryKey {
|
||||
val columns: List<Column<*>>
|
||||
val name: String
|
||||
|
||||
/**
|
||||
* Define the columns in the primary key of the current table. You can also provide the name of primary key constraint
|
||||
* by passing the "name" argument. Example : PrimaryKey(id1, id2, id3..., name = "CustomPKName")
|
||||
*
|
||||
* @param columns list of columns in the primary key
|
||||
* @param name the primary key constraint name, by default it will be resolved from the table name with "pk_" prefix
|
||||
*/
|
||||
constructor(vararg columns: Column<*>, name: String = "") {
|
||||
this.columns = columns.toList()
|
||||
* Define the columns in the primary key of the current table. You can also provide the name of primary key constraint
|
||||
* by passing the "name" argument. Example : PrimaryKey(id1, id2, id3..., name = "CustomPKName")
|
||||
*
|
||||
* @param columns list of columns in the primary key
|
||||
* @param name the primary key constraint name, by default it will be resolved from the table name with "pk_" prefix
|
||||
*/
|
||||
inner class PrimaryKey(
|
||||
vararg val columns: Column<*>,
|
||||
val name: String = "pk_$tableName"
|
||||
) {
|
||||
|
||||
init {
|
||||
checkMultipleDeclaration()
|
||||
|
||||
for (column in columns) {
|
||||
column.markPrimaryKey()
|
||||
}
|
||||
|
||||
if (name.isEmpty()) {
|
||||
this.name = "pk_${tableName}"
|
||||
} else {
|
||||
this.name = name
|
||||
isCustomPKNameDefined = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,10 +264,7 @@ open class Table(name: String = ""): ColumnSet(), DdlAware {
|
||||
*
|
||||
* This constructor must be removed when [primaryKey] method is no longer supported.
|
||||
*/
|
||||
internal constructor(columns: List<Column<*>>) {
|
||||
this.columns = columns
|
||||
this.name = "pk_${tableName}"
|
||||
}
|
||||
internal constructor(columns: List<Column<*>>) : this(*columns.toTypedArray())
|
||||
|
||||
/**
|
||||
* Mark @receiver column as an element of primary key.
|
||||
@@ -309,14 +296,17 @@ open class Table(name: String = ""): ColumnSet(), DdlAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the primary key of the table. It is initialized with existing keys.
|
||||
* Represents the primary key of the table if present.
|
||||
* It is initialized with existing keys defined by [Column.primaryKey] function for a backward compatibility,
|
||||
* but you have to define it explicitly by overriding that val instead.
|
||||
*/
|
||||
open val primaryKey by lazy { PrimaryKey(getPrimaryKeyColumns()) }
|
||||
open val primaryKey: PrimaryKey? by lazy { getPrimaryKeyColumns()?.let { PrimaryKey(it) } }
|
||||
|
||||
/**
|
||||
* Returns the list of columns in the primary key.
|
||||
* Returns the list of columns in the primary key if present.
|
||||
*/
|
||||
private fun getPrimaryKeyColumns(): List<Column<*>> = columns.filter { it.indexInPK != null }.sortedWith(compareBy({ !it.columnType.isAutoInc }, { it.indexInPK }))
|
||||
private fun getPrimaryKeyColumns(): List<Column<*>>?
|
||||
= columns.filter { it.indexInPK != null }.sortedWith(compareBy({ !it.columnType.isAutoInc }, { it.indexInPK })).takeIf { it.isNotEmpty() }
|
||||
|
||||
/**
|
||||
* Mark @receiver column as primary key.
|
||||
@@ -329,7 +319,7 @@ open class Table(name: String = ""): ColumnSet(), DdlAware {
|
||||
*/
|
||||
@Deprecated("This function will be no longer supported. Please use the new declarations of primary key by " +
|
||||
"overriding the primaryKey property in the current table. " +
|
||||
"Example : object TableName : Table() { override val primaryKey = PrimaryKey(columns, name = \"CustomPKConstraintName\") }")
|
||||
"Example : object TableName : Table() { override val primaryKey = PrimaryKey(column1, column2, name = \"CustomPKConstraintName\") }")
|
||||
fun <T> Column<T>.primaryKey(indx: Int? = null): Column<T> {
|
||||
if (indx != null && table.columns.any { it.indexInPK == indx } ) throw IllegalArgumentException("Table $tableName already contains PK at $indx")
|
||||
indexInPK = indx ?: table.columns.count { it.indexInPK != null } + 1
|
||||
@@ -716,7 +706,7 @@ open class Table(name: String = ""): ColumnSet(), DdlAware {
|
||||
append(TransactionManager.current().identity(this@Table))
|
||||
if (columns.any()) {
|
||||
append(columns.joinToString(prefix = " (") { it.descriptionDdl() })
|
||||
if (isCustomPKNameDefined || columns.none { it.isOneColumnPK() }) {
|
||||
if (isCustomPKNameDefined() || columns.none { it.isOneColumnPK() }) {
|
||||
primaryKeyConstraint()?.let {
|
||||
append(", $it")
|
||||
}
|
||||
@@ -749,17 +739,14 @@ open class Table(name: String = ""): ColumnSet(), DdlAware {
|
||||
}
|
||||
|
||||
internal fun primaryKeyConstraint(): String? {
|
||||
val pkey = primaryKey.columns
|
||||
|
||||
if (pkey.isNotEmpty()) {
|
||||
return primaryKey?.let { primaryKey ->
|
||||
val tr = TransactionManager.current()
|
||||
val constraint = tr.db.identifierManager.cutIfNecessaryAndQuote(primaryKey.name)
|
||||
return pkey.joinToString(
|
||||
return primaryKey.columns.joinToString(
|
||||
prefix = "CONSTRAINT $constraint PRIMARY KEY (", postfix = ")") {
|
||||
tr.identity(it)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun dropStatement() : List<String> {
|
||||
|
||||
Reference in New Issue
Block a user