-
Notifications
You must be signed in to change notification settings - Fork 695
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
Composite foreign key #511
Comments
@SackCastellon , it the moment it's possible only the manual way, like : val t = TransactionManager.current()
val fk = ForeignKeyConstraint("fk_name",
t.identity(TableA), "{t.identity(TableA.idA)}, {t.identity(TableA.idA)}",
t.identity(TableB), "{t.identity(TableB.idA)}, {t.identity(TableB.idA)}",
ReferenceOption.RESTRICT,
ReferenceOption.RESTRICT)
t.exec(fk.createStatement().firsts()) |
@Tapac |
What's the workaround for this now? |
A possible workaround is to declare "virtual" columns, composing referencing and referenced columns respectively, and pass them into the For convenience, it could be wrapped into auxiliary function: fun Transaction.foreignKeyCompositeConstraint(
columnsReferences: Map<Column<*>, Column<*>>,
onUpdate: ReferenceOption?,
onDelete: ReferenceOption?,
name: String? = null,
): ForeignKeyConstraint {
val fromColumns = columnsReferences.keys
val fromTable = fromColumns.first().table
require(fromColumns.all { it.table == fromTable }) { "All referencing columns must belong to the same table" }
val targetColumns = columnsReferences.values
val targetTable = targetColumns.first().table
require(targetColumns.all { it.table == targetTable }) { "All referenced columns must belong to the same table" }
// this API is private, so redeclare it as an extension method
fun IdentifierManagerApi.quote(identity: String) = "$quoteString$identity$quoteString".trim()
val virtualColumnOf = { columns: Iterable<Column<*>> ->
val someColumn = columns.first()
val columnsIdentities = columns.joinToString(",") { db.identifierManager.quote(identity(it)) }
Column<Any>(someColumn.table, columnsIdentities, someColumn.columnType)
}
fun Iterable<Column<*>>.joinNamesToString() = joinToString("_") { it.name }
return ForeignKeyConstraint(
target = virtualColumnOf(targetColumns),
from = virtualColumnOf(fromColumns),
onUpdate = onUpdate,
onDelete = onDelete,
name = name ?: "fk_${fromTable.tableName.substringAfter(".")}_${fromColumns.joinNamesToString()}__${targetColumns.joinNamesToString()}"
)
} Usage (still manual): val t = TransactionManager.current()
val fk = t.foreignKeyCompositeConstraint(
mapOf(TableB.idA to TableA.idA, TableB.idB to TableA.idB),
ReferenceOption.RESTRICT,
ReferenceOption.RESTRICT
)
t.exec(fk.createStatement().first()) Works for MySQL, PostgreSQL, H2; will not work for SQLite, due to limitations of its |
hi @naftalmm , prior to version 0.37.1 of kotlin-exposed, there was this function in UpdateBuilder.kt: in 0.37.1 its signature was changed to: is there a compelling reason for S to be a subtype of "Any", instead of "Any?" ? |
I have this two tables:
The generated SQL statements look like this:
This works in some databases like SQLite ot H2, however it doesn't in MySQL or PostgreSQL.
For it to work on all databases whe generated SQL should look like this:
Is it possible to achive this using the SQL DSL?
The text was updated successfully, but these errors were encountered: