diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MariaDBDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MariaDBDialect.kt index 9301742d3f..4299efb852 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MariaDBDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MariaDBDialect.kt @@ -24,6 +24,17 @@ internal object MariaDBFunctionProvider : MysqlFunctionProvider() { append("LOCATE(\'", substring, "\',", expr, ")") } + override fun update( + targets: Join, + columnsAndValues: List, Any?>>, + limit: Int?, + where: Op?, + transaction: Transaction + ): String { + val sql = super.update(targets, columnsAndValues, null, where, transaction) + return if (limit != null) "$sql LIMIT $limit" else sql + } + override fun explain( analyze: Boolean, options: String?, diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MysqlDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MysqlDialect.kt index 7d868a7e6d..f6862701ae 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MysqlDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MysqlDialect.kt @@ -219,21 +219,26 @@ internal open class MysqlFunctionProvider : FunctionProvider() { limit: Int?, where: Op?, transaction: Transaction - ): String = with(QueryBuilder(true)) { - +"UPDATE " - targets.describe(transaction, this) - +" SET " - columnsAndValues.appendTo(this) { (col, value) -> - append("${transaction.fullIdentity(col)}=") - registerArgument(col, value) + ): String { + if (limit != null) { + transaction.throwUnsupportedException("MySQL doesn't support LIMIT in UPDATE with join clause.") } - where?.let { - +" WHERE " - +it + return with(QueryBuilder(true)) { + +"UPDATE " + targets.describe(transaction, this) + +" SET " + columnsAndValues.appendTo(this) { (col, value) -> + append("${transaction.fullIdentity(col)}=") + registerArgument(col, value) + } + + where?.let { + +" WHERE " + +it + } + toString() } - limit?.let { +" LIMIT $it" } - toString() } override fun upsert( 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 eb88856759..36e29465fc 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 @@ -212,7 +212,7 @@ internal object SQLServerFunctionProvider : FunctionProvider() { targets.checkJoinTypes(StatementType.UPDATE) if (limit != null) { - +"UPDATE TOP($limit)" + +"UPDATE TOP($limit) " } else { +"UPDATE " } @@ -229,7 +229,6 @@ internal object SQLServerFunctionProvider : FunctionProvider() { +" AND " +it } - limit?.let { +" LIMIT $it" } toString() } diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/dml/UpdateTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/dml/UpdateTests.kt index f506ee1d2b..d3ddca08c3 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/dml/UpdateTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/dml/UpdateTests.kt @@ -11,6 +11,7 @@ import org.jetbrains.exposed.sql.tests.shared.assertEquals import org.jetbrains.exposed.sql.tests.shared.expectException import org.jetbrains.exposed.sql.vendors.SQLiteDialect import org.junit.Test +import kotlin.test.assertTrue class UpdateTests : DatabaseTestsBase() { private val notSupportLimit by lazy { @@ -95,6 +96,27 @@ class UpdateTests : DatabaseTestsBase() { } } + @Test + fun testUpdateWithJoinAndLimit() { + val supportsUpdateWithJoinAndLimit = TestDB.ALL_MARIADB + TestDB.ORACLE + TestDB.SQLSERVER + withCitiesAndUsers(exclude = TestDB.ALL - supportsUpdateWithJoinAndLimit) { _, users, userData -> + val join = users.innerJoin(userData) + + val maxToUpdate = 2 + assertTrue { join.selectAll().count() > maxToUpdate } + + val updatedValue = 123 + val valueQuery = join.selectAll().where { userData.value eq updatedValue } + assertEquals(0, valueQuery.count()) + + join.update(limit = 2) { + it[userData.value] = 123 + } + + assertEquals(2, valueQuery.count()) + } + } + @Test fun testUpdateWithMultipleJoins() { withCitiesAndUsers(exclude = TestDB.ALL_H2 + TestDB.SQLITE) { cities, users, userData ->